diff --git a/README.md b/README.md index 9a6db7d..3e34663 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,11 @@ Idiomatic F# extensions for the C# RethinkDB driver ## Using -Install the [NuGet](https://www.nuget.org/packages/RethinkDb.Driver.FSharp/) package `RethinkDb.Driver.FSharp`. You will need to specify pre-release, as the package has an alpha designation at this time. +Install the [NuGet](https://www.nuget.org/packages/RethinkDb.Driver.FSharp/) package `RethinkDb.Driver.FSharp`. You will need to specify pre-release, as the package currently has a beta designation. -## Goals +## What It Provides -The goal is to provide: -- A composable pipeline for creating ReQL statements: +### A composable pipeline for creating ReQL statements ```fsharp open RethinkDb.Driver.FSharp.Functions @@ -24,7 +23,7 @@ let fetchPost (postId : string) = |> withRetryDefault ``` -- An F# domain-specific language (DSL) using a `rethink` computation expression (CE): +### An F# domain-specific language (DSL) using a `rethink` computation expression (CE) ```fsharp open RethinkDb.Driver.FSharp @@ -39,7 +38,7 @@ let fetchPost (postId : string) = } ``` -- A standard way to translate JSON into a strongly-typed configuration: +### A standard way to translate JSON into a strongly-typed configuration ```fsharp /// type: DataConfig @@ -55,15 +54,15 @@ let conn = config.Connect () let! post = fetchPost "the-post-id" conn ``` -- Robust queries +### Robust queries The RethinkDB connection is generally stored as a singleton. Over time, this connection can lose its connection to the server. Both the CE and functions have `withRetryDefault`, which will retry a failed command up to 3 times (4 counting the initial try), waiting 200ms, 500ms, and 1 second between the respective attempts. There are other options as well; `withRetryOnce` will retry one time immediately. `withRetry` takes a list of `float`s, which will be interpreted as seconds to delay between each retry; it will retry until it has exhausted the delays. The examples above both use the default retry logic. -- Only rename functions/methods where required +### Only rename functions/methods where required -Within the CE, there are a few differing names, mostly notably at the start (selecting databases and tables); this is to allow for a more natural language flow. Its names may change in the 0.8.x series; it is the most alpha part of the project at this point. Also, while CEs now support overloading (thank you F# 6 developers!), they do not detect if the first value in the tupled arguments is different. This is most noticeable once `result*` or `write*` commands have been issued; these support `Task<'T>`, `Async<'T>`, and synchronous `'T` operations, but the follow-on commands will be different (e.x. `withRetryDefault` (tasks) vs. `withAsyncRetryDefault` vs. `withSyncRetryDefault`). There are also versions of these that support optional arguments (for all) and cancellation tokens (for task/async). +Within the CE, there are a few differing names, mostly notably at the start (selecting databases and tables); this is to allow for a more natural language flow. Also, while CEs now support overloading (thank you F# 6 developers!), they do not detect if the first value in the tupled arguments is different. This is most noticeable once `result*` or `write*` commands have been issued; these support `Task<'T>`, `Async<'T>`, and synchronous `'T` operations, but the follow-on commands will be different (e.x. `withRetryDefault` (tasks) vs. `withAsyncRetryDefault` vs. `withSyncRetryDefault`). There are also versions of these that support optional arguments (for all) and cancellation tokens (for task/async). The functions show this pattern throughout, as functions in a module do not support overloading; an example for `filter` is below. @@ -88,4 +87,3 @@ license on this project's dependencies. Please see [the heading on the C# driver If you are using the project, feel free to file issues about your pain points; there is no substitute for real-world feedback! [license]: https://github.com/bchavez/RethinkDb.Driver#open-source-and-commercial-licensing -[nuget]: https://ci.appveyor.com/nuget/danieljsummers-rethinkdb-driver-fsharp \ No newline at end of file diff --git a/src/RethinkDb.Driver.FSharp/README.md b/src/RethinkDb.Driver.FSharp/README.md new file mode 100644 index 0000000..515ea1f --- /dev/null +++ b/src/RethinkDb.Driver.FSharp/README.md @@ -0,0 +1,80 @@ +## RethinkDb.Driver.FSharp + +This package provides idiomatic F# extensions on the [official C# driver][csharp-pkg]. Within this package: + +### Connection Configuration / Creation + +```fsharp +open RethinkDb.Driver.FSharp + +let dataCfg = DataConfig.fromJson "rethink-config.json" +// - or - +let dataCfg = DataConfig.fromConfiguration [config-section] + +let conn = dataCfg.CreateConnection () // IConnection +``` + +### Domain-Specific Language (DSL) / Computation Expression (CE) Style + +```fsharp +open RethinkDb.Driver.FSharp + +// Remove the conn parameter and usage for point-free style + +let getPost postId conn = + rethink { + fromTable "Post" + get postId + resultOption + withRetryOptionDefault conn + } + +let updatePost post conn = + rethink { + fromTable "Post" + get post.id + update post + write + ignoreResult + withRetryDefault conn + } +``` + +### Function Style + +```fsharp +open RethinkDb.Driver.FSharp.Functions + +// NOTE: this returns Task; checking for null/option is not handled +// as it is with the CE version +let getPost postId conn = + fromTable "Post" + |> get postId + |> runResult + |> withRetryDefault conn + +// NOTE: this returns Task; ignoring inline is not available as +// it is with the CE version +let updatePost post conn = + fromTable "Post" + |> get post.id + |> update post + |> runWrite + |> withRetryDefault conn +``` + +### Retry Logic + +The driver does not reconnect automatically when the underlying connection has been interrupted. When specified, the retry logic attempts to reconnect; default retries wait 200ms, 500ms, and 1 second. There are also functions to retry once, and those that allow the intervals to be specified. + +### Strongly-Typed Optional Arguments + +Many RethinkDB commands support optional arguments to tweak the behavior of that command. A quick example using the `between` command (clause): + +```fsharp +// ... + between 1 100 [ LowerBound Open; UpperBound Closed ] +// ... +``` + +[csharp-pkg]: https://www.nuget.org/packages/RethinkDb.Driver/ \ No newline at end of file diff --git a/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj b/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj index e4da046..4bf73a3 100644 --- a/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj +++ b/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj @@ -6,13 +6,14 @@ Daniel J. Summers Apache-2.0 https://github.com/danieljsummers/RethinkDb.Driver.FSharp - + https://github.com/danieljsummers/RethinkDb.Driver.FSharp/raw/main/pkg/icon.png + icon.png + README.md false See LICENSE RethinkDB document F# - 0.8.0 - alpha-0009 - Alpha; use at your own risk + 0.9.0 + beta-01 @@ -21,6 +22,8 @@ + + diff --git a/src/RethinkDb.Driver.FSharp/Retry.fs b/src/RethinkDb.Driver.FSharp/Retry.fs index c19eb7c..1aee920 100644 --- a/src/RethinkDb.Driver.FSharp/Retry.fs +++ b/src/RethinkDb.Driver.FSharp/Retry.fs @@ -13,12 +13,9 @@ let retryPolicy (intervals : float seq) (conn : IConnection) = .WaitAndRetryAsync( intervals |> Seq.map TimeSpan.FromSeconds, System.Action (fun ex _ _ _ -> - printf $"Encountered RethinkDB exception: {ex.Message}" - match ex.Message.Contains "socket" with - | true -> - printf "Reconnecting to RethinkDB" - (conn :?> Connection).Reconnect false - | false -> ())) + printfn $"Encountered RethinkDB exception: {ex.Message}" + printfn "Reconnecting to RethinkDB..." + (conn :?> Connection).Reconnect false)) /// Create a retry policy that attempts to reconnect to RethinkDB when a synchronous operation encounters an error let retryPolicySync (intervals : float seq) (conn : IConnection) = diff --git a/src/RethinkDb.Driver.FSharp/icon.png b/src/RethinkDb.Driver.FSharp/icon.png new file mode 100644 index 0000000..08362a9 Binary files /dev/null and b/src/RethinkDb.Driver.FSharp/icon.png differ