From a8af285cae061609463f885cb26376166f57d9e2 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Tue, 14 Jun 2022 09:31:37 -0400 Subject: [PATCH] Add cursor / toList functions and methods --- src/RethinkDb.Driver.FSharp/Builder.fs | 119 +++++++++++++++++- src/RethinkDb.Driver.FSharp/Functions.fs | 87 +++++++++++-- src/RethinkDb.Driver.FSharp/Functions.fsi | 48 ++++++- .../RethinkDb.Driver.FSharp.fsproj | 5 +- 4 files changed, 239 insertions(+), 20 deletions(-) diff --git a/src/RethinkDb.Driver.FSharp/Builder.fs b/src/RethinkDb.Driver.FSharp/Builder.fs index 2a24b80..0973e2d 100644 --- a/src/RethinkDb.Driver.FSharp/Builder.fs +++ b/src/RethinkDb.Driver.FSharp/Builder.fs @@ -473,6 +473,43 @@ type RethinkBuilder<'T> () = conn : IConnection) = this.ResultOption (expr, opts, cancelToken) conn + /// Execute the query, returning a cursor for the type specified using the given cancellation token + [] + member _.ResultCursor (expr : ReqlExpr, cancelToken : CancellationToken) = runCursorWithCancel<'T> cancelToken expr + + /// Execute the query, returning a cursor for the type specified using the given cancellation token + [] + member this.ResultCursor (expr : ReqlExpr, cancelToken : CancellationToken, conn : IConnection) = + this.ResultCursor (expr, cancelToken) conn + + /// Execute the query, returning a cursor for the type specified + [] + member _.ResultCursor (expr : ReqlExpr) = runCursor<'T> expr + + /// Execute the query, returning a cursor for the type specified + [] + member this.ResultCursor (expr : ReqlExpr, conn : IConnection) = this.ResultCursor expr conn + + /// Execute the query, returning a cursor for the type specified, using optional arguments + [] + member _.ResultCursor (expr : ReqlExpr, args : RunOptArg list) = runCursorWithOptArgs<'T> args expr + + /// Execute the query, returning a cursor for the type specified + [] + member this.ResultCursor (expr : ReqlExpr, args : RunOptArg list, conn : IConnection) = + this.ResultCursor (expr, args) conn + + /// Execute the query, returning a cursor for the type specified, using optional arguments and a cancellation token + [] + member _.ResultCursor (expr : ReqlExpr, args : RunOptArg list, cancelToken : CancellationToken) = + runCursorWithOptArgsAndCancel<'T> args cancelToken expr + + /// Execute the query, returning a cursor for the type specified, using optional arguments and a cancellation token + [] + member this.ResultCursor (expr : ReqlExpr, args : RunOptArg list, cancelToken : CancellationToken, + conn : IConnection) = + this.ResultCursor (expr, args, cancelToken) conn + /// Execute the query, returning the result of the type specified using the given cancellation token [] member _.AsyncResult (expr : ReqlExpr, cancelToken : CancellationToken) = asyncResultWithCancel<'T> cancelToken expr @@ -494,7 +531,7 @@ type RethinkBuilder<'T> () = [] member _.AsyncResult (expr : ReqlExpr, args : RunOptArg list) = asyncResultWithOptArgs<'T> args expr - /// Execute the query, returning the result of the type specified + /// Execute the query, returning the result of the type specified, using optional arguments [] member this.AsyncResult (expr : ReqlExpr, args : RunOptArg list, conn : IConnection) = this.AsyncResult (expr, args) conn @@ -554,6 +591,43 @@ type RethinkBuilder<'T> () = conn : IConnection) = this.AsyncOption (expr, opts, cancelToken) conn + /// Execute the query, returning a cursor for the type specified using the given cancellation token + [] + member _.AsyncCursor (expr : ReqlExpr, cancelToken : CancellationToken) = asyncCursorWithCancel<'T> cancelToken expr + + /// Execute the query, returning a cursor for the type specified using the given cancellation token + [] + member this.AsyncCursor (expr : ReqlExpr, cancelToken : CancellationToken, conn : IConnection) = + this.AsyncCursor (expr, cancelToken) conn + + /// Execute the query, returning a cursor for the type specified + [] + member _.AsyncCursor (expr : ReqlExpr) = asyncCursor<'T> expr + + /// Execute the query, returning a cursor for the type specified + [] + member this.AsyncCursor (expr : ReqlExpr, conn : IConnection) = this.AsyncCursor expr conn + + /// Execute the query, returning a cursor for the type specified, using optional arguments + [] + member _.AsyncCursor (expr : ReqlExpr, args : RunOptArg list) = asyncCursorWithOptArgs<'T> args expr + + /// Execute the query, returning a cursor for the type specified, using optional arguments + [] + member this.AsyncCursor (expr : ReqlExpr, args : RunOptArg list, conn : IConnection) = + this.AsyncCursor (expr, args) conn + + /// Execute the query, returning a cursor for the type specified, using optional arguments and a cancellation token + [] + member _.AsyncCursor (expr : ReqlExpr, args : RunOptArg list, cancelToken : CancellationToken) = + asyncCursorWithOptArgsAndCancel<'T> args cancelToken expr + + /// Execute the query, returning a cursor for the type specified, using optional arguments and a cancellation token + [] + member this.AsyncCursor (expr : ReqlExpr, args : RunOptArg list, cancelToken : CancellationToken, + conn : IConnection) = + this.AsyncCursor (expr, args, cancelToken) conn + /// Execute the query synchronously, returning the result of the type specified [] member _.SyncResult (expr : ReqlExpr) = syncResult<'T> expr @@ -566,7 +640,7 @@ type RethinkBuilder<'T> () = [] member _.SyncResult (expr : ReqlExpr, args : RunOptArg list) = syncResultWithOptArgs<'T> args expr - /// Execute the query synchronously, returning the result of the type specified + /// Execute the query synchronously, returning the result of the type specified, using optional arguments [] member this.SyncResult (expr : ReqlExpr, args : RunOptArg list, conn : IConnection) = this.SyncResult (expr, args) conn @@ -590,6 +664,23 @@ type RethinkBuilder<'T> () = member this.SyncOption (expr : ReqlExpr, opts : RunOptArg list, conn : IConnection) = this.SyncOption (expr, opts) conn + /// Execute the query synchronously, returning a cursor for the type specified + [] + member _.SyncCursor (expr : ReqlExpr) = syncCursor<'T> expr + + /// Execute the query synchronously, returning a cursor for the type specified + [] + member this.SyncCursor (expr : ReqlExpr, conn : IConnection) = this.SyncCursor expr conn + + /// Execute the query synchronously, returning a cursor for the type specified, using optional arguments + [] + member _.SyncCursor (expr : ReqlExpr, args : RunOptArg list) = syncCursorWithOptArgs<'T> args expr + + /// Execute the query synchronously, returning a cursor for the type specified, using optional arguments + [] + member this.SyncCursor (expr : ReqlExpr, args : RunOptArg list, conn : IConnection) = + this.SyncCursor (expr, args) conn + /// Perform a write operation [] member _.Write (expr : ReqlExpr) = runWrite expr @@ -799,6 +890,30 @@ type RethinkBuilder<'T> () = [] member this.IgnoreSync (f : IConnection -> 'T, conn) = this.IgnoreSync f conn + /// Convert the items in a cursor to a list + [] + member _.ToList (f : IConnection -> Task>) = toList<'T> f + + /// Convert the items in a cursor to a list + [] + member this.ToList (f : IConnection -> Task>, conn) = this.ToList f conn + + /// Convert the items in a cursor to a list + [] + member _.ToListAsync (f : IConnection -> Async>) = toListAsync f + + /// Convert the items in a cursor to a list + [] + member this.ToListAsync (f : IConnection -> Async>, conn) = this.ToListAsync f conn + + /// Convert the items in a cursor to a list + [] + member _.ToListSync (f : IConnection -> Cursor<'T>) = toListSync f + + /// Convert the items in a cursor to a list + [] + member this.ToListSync (f : IConnection -> Cursor<'T>, conn) = this.ToListSync f conn + // Reconnection /// Retries a variable number of times, waiting each time for the seconds specified diff --git a/src/RethinkDb.Driver.FSharp/Functions.fs b/src/RethinkDb.Driver.FSharp/Functions.fs index d805200..3f2e1c6 100644 --- a/src/RethinkDb.Driver.FSharp/Functions.fs +++ b/src/RethinkDb.Driver.FSharp/Functions.fs @@ -2,6 +2,7 @@ module RethinkDb.Driver.FSharp.Functions open System.Threading +open System.Threading.Tasks open RethinkDb.Driver open RethinkDb.Driver.Ast open RethinkDb.Driver.Net @@ -14,13 +15,6 @@ module private Helpers = /// Create a Javascript object from a string (used mostly for type inference) let toJS (js : string) = Javascript js -// ~~ EXECUTION ~~ - -/// Get a cursor with the results of an expression -let asyncCursor<'T> (expr : ReqlExpr) conn = - expr.RunCursorAsync<'T> conn - |> Async.AwaitTask - // ~~ WRITES ~~ /// Write a ReQL command with a cancellation token, always returning a result @@ -110,13 +104,14 @@ let syncWriteWithOptArgs args expr = fun conn -> asyncWriteWithOptArgs args expr conn |> Async.RunSynchronously // ~~ QUERY RESULTS AND MANIPULATION ~~ - + +// ~~ Full results (atom / sequence) ~~ + /// Run the ReQL command using a cancellation token, returning the result as the type specified let runResultWithCancel<'T> cancelToken (expr : ReqlExpr) = fun conn -> expr.RunResultAsync<'T> (conn, cancelToken) -/// Run the ReQL command using optional arguments and a cancellation token, returning the result as the type -/// specified +/// Run the ReQL command using optional arguments and a cancellation token, returning the result as the type specified let runResultWithOptArgsAndCancel<'T> args cancelToken (expr : ReqlExpr) = fun conn -> expr.RunResultAsync<'T> (conn, RunOptArg.create args, cancelToken) @@ -138,8 +133,7 @@ let asyncResultWithOptArgs<'T> args expr = fun conn -> let asyncResultWithCancel<'T> cancelToken expr = fun conn -> runResultWithCancel<'T> cancelToken expr conn |> Async.AwaitTask -/// Run the ReQL command using optional arguments and a cancellation token, returning the result as the type -/// specified +/// Run the ReQL command using optional arguments and a cancellation token, returning the result as the type specified let asyncResultWithOptArgsAndCancel<'T> args cancelToken expr = fun conn -> runResultWithOptArgsAndCancel<'T> args cancelToken expr conn |> Async.AwaitTask @@ -176,6 +170,75 @@ let ignoreResult<'T> (f : IConnection -> Tasks.Task<'T>) conn = task { () } +// ~~ Cursors / partial results (sequence / partial) ~~ + +/// Run the ReQL command using a cancellation token, returning a cursor for the type specified +let runCursorWithCancel<'T> cancelToken (expr : ReqlExpr) = fun conn -> + expr.RunCursorAsync<'T> (conn, cancelToken) + +/// Run the ReQL command using optional arguments and a cancellation token, returning a cursor for the type specified +let runCursorWithOptArgsAndCancel<'T> args cancelToken (expr : ReqlExpr) = fun conn -> + expr.RunCursorAsync<'T> (conn, RunOptArg.create args, cancelToken) + +/// Run the ReQL command, returning a cursor for the type specified +let runCursor<'T> expr = runCursorWithCancel<'T> CancellationToken.None expr + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +let runCursorWithOptArgs<'T> args expr = runCursorWithOptArgsAndCancel<'T> args CancellationToken.None expr + +/// Run the ReQL command, returning a cursor for the type specified +let asyncCursor<'T> expr = fun conn -> + runCursor<'T> expr conn |> Async.AwaitTask + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +let asyncCursorWithOptArgs<'T> args expr = fun conn -> + runCursorWithOptArgs<'T> args expr conn |> Async.AwaitTask + +/// Run the ReQL command using a cancellation token, returning a cursor for the type specified +let asyncCursorWithCancel<'T> cancelToken expr = fun conn -> + runCursorWithCancel<'T> cancelToken expr conn |> Async.AwaitTask + +/// Run the ReQL command using optional arguments and a cancellation token, returning a cursor for the type specified +let asyncCursorWithOptArgsAndCancel<'T> args cancelToken expr = fun conn -> + runCursorWithOptArgsAndCancel<'T> args cancelToken expr conn |> Async.AwaitTask + +/// Run the ReQL command, returning a cursor for the type specified +let syncCursor<'T> expr = fun conn -> + asyncCursor<'T> expr conn |> Async.RunSynchronously + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +let syncCursorWithOptArgs<'T> args expr = fun conn -> + asyncCursorWithOptArgs<'T> args expr conn |> Async.RunSynchronously + +/// Convert a cursor to a list (once the cursor has been obtained) +let cursorToList<'T> (cursor : Cursor<'T>) = backgroundTask { + let! hasNext = cursor.MoveNextAsync () + let mutable hasData = hasNext + let mutable items = [] + while hasData do + items <- cursor.Current :: items + let! hasNext = cursor.MoveNextAsync () + hasData <- hasNext + return items +} + +/// Convert a cursor to a list of items +let toList<'T> (f : IConnection -> Task>) = fun conn -> backgroundTask { + use! cursor = f conn + return! cursorToList cursor +} + +/// Convert a cursor to a list of items +let toListAsync<'T> (f : IConnection -> Async>) = fun conn -> async { + use! cursor = f conn + return! cursorToList<'T> cursor |> Async.AwaitTask +} + +/// Convert a cursor to a list of items +let toListSync<'T> (f : IConnection -> Cursor<'T>) = fun conn -> + use cursor = f conn + cursorToList cursor |> Async.AwaitTask |> Async.RunSynchronously + /// Apply a connection to the query pipeline (typically the final step) let withConn<'T> conn (f : IConnection -> 'T) = f conn diff --git a/src/RethinkDb.Driver.FSharp/Functions.fsi b/src/RethinkDb.Driver.FSharp/Functions.fsi index b9844eb..f61dd17 100644 --- a/src/RethinkDb.Driver.FSharp/Functions.fsi +++ b/src/RethinkDb.Driver.FSharp/Functions.fsi @@ -7,9 +7,6 @@ open RethinkDb.Driver open RethinkDb.Driver.Ast open RethinkDb.Driver.Net -/// Get a cursor with the results of an expression -val asyncCursor<'T> : ReqlExpr -> IConnection -> Async> - // ~~ WRITE, ALWAYS RETURNING A RESULT ~~ /// Write a ReQL command with a cancellation token, always returning a result @@ -80,6 +77,8 @@ val syncWriteWithOptArgs : RunOptArg list -> ReqlExpr -> (IConnection -> Model.R // ~~ RUNNING QUERIES AND MANIPULATING RESULTS ~~ +// ~~ Full results ~~ + /// Run the ReQL command using a cancellation token, returning the result as the type specified val runResultWithCancel<'T> : CancellationToken -> ReqlExpr -> (IConnection -> Task<'T>) @@ -122,6 +121,49 @@ val asSyncOption : (IConnection -> 'T) -> IConnection -> 'T option /// Ignore the result of a task-based execution val ignoreResult<'T> : (IConnection -> Task<'T>) -> IConnection -> Task +// ~~ Cursors / Partial results ~~ + +/// Run the ReQL command using a cancellation token, returning a cursor for the type specified +val runCursorWithCancel<'T> : CancellationToken -> ReqlExpr -> (IConnection -> Task>) + +/// Run the ReQL command using optional arguments and a cancellation token, returning a cursor for the type specified +val runCursorWithOptArgsAndCancel<'T> : + RunOptArg list -> CancellationToken -> ReqlExpr -> (IConnection -> Task>) + +/// Run the ReQL command, returning a cursor for the type specified +val runCursor<'T> : ReqlExpr -> (IConnection -> Task>) + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +val runCursorWithOptArgs<'T> : RunOptArg list -> ReqlExpr -> (IConnection -> Task>) + +/// Run the ReQL command, returning a cursor for type specified +val asyncCursor<'T> : ReqlExpr -> (IConnection -> Async>) + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +val asyncCursorWithOptArgs<'T> : RunOptArg list -> ReqlExpr -> (IConnection -> Async>) + +/// Run the ReQL command using a cancellation token, returning a cursor for the type specified +val asyncCursorWithCancel<'T> : CancellationToken -> ReqlExpr -> (IConnection -> Async>) + +/// Run the ReQL command using optional arguments and a cancellation token, returning a cursor for the type specified +val asyncCursorWithOptArgsAndCancel<'T> : + RunOptArg list -> CancellationToken -> ReqlExpr -> (IConnection -> Async>) + +/// Run the ReQL command, returning a cursor for the type specified +val syncCursor<'T> : ReqlExpr -> (IConnection -> Cursor<'T>) + +/// Run the ReQL command using optional arguments, returning a cursor for the type specified +val syncCursorWithOptArgs<'T> : RunOptArg list -> ReqlExpr -> (IConnection -> Cursor<'T>) + +/// Convert a cursor to a list of items +val toList<'T> : (IConnection -> Task>) -> IConnection -> Task<'T list> + +/// Convert a cursor to a list of items +val toListAsync<'T> : (IConnection -> Async>) -> IConnection -> Async<'T list> + +/// Convert a cursor to a list of items +val toListSync<'T> : (IConnection -> Cursor<'T>) -> IConnection -> 'T list + /// Apply a connection to the query pipeline (typically the final step) val withConn<'T> : IConnection -> (IConnection -> 'T) -> 'T diff --git a/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj b/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj index 1e03e3d..64749b3 100644 --- a/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj +++ b/src/RethinkDb.Driver.FSharp/RethinkDb.Driver.FSharp.fsproj @@ -14,10 +14,9 @@ See LICENSE RethinkDB document F# 0.9.0 - beta-03 + beta-04 - Retry logic now works with functions; added signature for function moduel and explicit type annotations to the - DSL builder + Add cursor / toList functions and DSL operations