Idiomatic F# extensions for the C# RethinkDB driver https://bitbadger.solutions/open-source/rethinkdb-driver-fsharp/
Go to file
2022-04-18 22:53:04 -04:00
src Prep for 0.8.0 2022-04-18 22:31:48 -04:00
.gitignore Initial commit 2017-07-15 08:05:37 -05:00
appveyor.yml Update CI settings 2022-04-11 23:38:42 -04:00
LICENSE Initial extraction from other project 2017-07-16 20:18:47 -05:00
README.md Update README with NuGet info 2022-04-18 22:53:04 -04:00

RethinkDb.Driver.FSharp

Idiomatic F# extensions for the C# RethinkDB driver

Licensing

While no specific additional license restrictions exist for this project, there are modifications to the Apache v2 license on this project's dependencies. Please see the heading on the C# driver page for details.

Using

Install the NuGet package RethinkDb.Driver.FSharp. You will need to specify pre-release, as the package has an alpha designation at this time.

Goals

The goal is to provide:

  • A composable pipeline for creating ReQL statements:
/// string -> (IConnection -> Task<Post>)
let fetchPost (postId : string) =
    fromDb "Blog"
    |> table "Post"
    |> get postId
    |> runResult<Post>
    |> withRetryDefault
  • An F# domain-specific language (DSL) using a rethink computation expression (CE):
/// string -> (IConnection -> Task<Post>)
let fetchPost (postId : string) =
    rethink<Post> {
        withTableInDb "Post" "Blog"
        get postId
        result
        withRetryDefault
    }
  • A standard way to translate JSON into a strongly-typed configuration:
/// type: DataConfig
let config = DataConfig.fromJsonFile "data-config.json"
// OR
let config = DataConfig.fromConfiguration (config.GetSection "RethinkDB")

/// type: IConnection
let conn = config.Connect ()

/// type: Post (utilizing either example above)
// (within a task CE)
let! post = fetchPost "the-post-id" conn
  • 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 floats, 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

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.

The functions do have to change a bit, since they do not support overloading; an example for filter is below.

// Function names cannot be polymorphic the way object-oriented methods can, so filter's three overloads become
filter (r.HashMap ("age", 30))
// and
filterFunc (fun row -> row.["age"].Eq(30))
// and
filterJS "function (row) { return 30 == row['age'] }"

If you are using the project, feel free to file issues about your pain points; there is no substitute for real-world feedback!