Skip to content

Commit

Permalink
Simplify runAsync (#70)
Browse files Browse the repository at this point in the history
* Simplify runAsync

* Fix test
  • Loading branch information
dbrattli authored Feb 26, 2021
1 parent 60b7415 commit b1123a5
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 38 deletions.
21 changes: 8 additions & 13 deletions src/Error.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,15 @@ module Error =
let catch (errorHandler: exn -> HttpHandler<'TSource>): HttpHandler<'TSource> =
HttpHandler
<| fun next ->
let rec obv =
{ new IHttpNext<'TSource> with
member _.NextAsync(ctx, ?content) = next.NextAsync(ctx, ?content = content)
{ new IHttpNext<'TSource> with
member _.NextAsync(ctx, ?content) = next.NextAsync(ctx, ?content = content)

member _.ErrorAsync(ctx, err) =
task {
printfn "Got error"

let handler = (errorHandler err).Subscribe(next)
return! handler.NextAsync(ctx)
}
}

obv
member _.ErrorAsync(ctx, err) =
task {
let handler = (errorHandler err).Subscribe(next)
return! handler.NextAsync(ctx)
}
}

/// Error handler for decoding fetch responses into an user defined error type. Will ignore successful responses.
let withError
Expand Down
21 changes: 7 additions & 14 deletions src/Handler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,27 @@ module Handler =
member __.ErrorAsync(_, error) = task { tcs.SetException error }
}

/// Run the HTTP handler in the given context. Returns HttpResponse with headers and status-code etc.
let runAsync' (ctx: Context) (handler: HttpHandler<'TSource, 'TResult>): Task<Result<'TResult option, exn>> =
/// Run the HTTP handler in the given context. Returns content as result type.
let runAsync (ctx: Context) (handler: HttpHandler<'TSource, 'TResult>): Task<Result<'TResult, exn>> =
let tcs = TaskCompletionSource<'TResult option>()

task {
do! handler.Subscribe(result tcs).NextAsync(ctx)

try
let! result = tcs.Task
return Ok result
match! tcs.Task with
| Some value -> return Ok value
| _ -> return OperationCanceledException() :> Exception |> Error
with err -> return Error err
}

/// Run the HTTP handler in the given context. Returns content as result type.
let runAsync (ctx: Context) (handler: HttpHandler<'T, 'TResult>): Task<Result<'TResult option, exn>> =
task {
let! result = runAsync' ctx handler
return result
}

/// Run th HTTP handler in the given context. Returns content and throws exception if any error occured.
let runUnsafeAsync (ctx: Context) (handler: HttpHandler<'T, 'TResult>): Task<'TResult> =
task {
let! result = runAsync' ctx handler
let! result = runAsync ctx handler

match result with
| Ok (Some result) -> return result
| Ok (None) -> return raise <| OperationCanceledException()
| Ok value -> return value
| Error err -> return raise err
}

Expand Down
2 changes: 1 addition & 1 deletion test/Builder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let ``Zero builder is Ok`` () =
let! result = req { () } |> runAsync ctx

// Assert
test <@ Result.isOk result @>
test <@ Result.isError result @>
}

[<Fact>]
Expand Down
4 changes: 2 additions & 2 deletions test/Fetch.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ let ``Get with return expression is Ok`` () =
return result + 1
}

let! result = request |> runAsync' ctx
let! result = request |> runAsync ctx
let retries' = retries

match result with
| Ok (Some response) -> test <@ response = 43 @>
| Ok response -> test <@ response = 43 @>
| _ -> ()

// Assert
Expand Down
32 changes: 24 additions & 8 deletions test/Handler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ let ``Simple unit handler is Ok`` () =
let ctx = Context.defaultContext

// Act
let! content = singleton 42 >=> singleton 43 |> runUnsafeAsync ctx
let! content =
singleton 42 >=> singleton 43
|> runUnsafeAsync ctx

// Assert
test <@ content = 43 @>
Expand Down Expand Up @@ -105,7 +107,10 @@ let ``Catching errors is Ok`` () =
let ctx = Context.defaultContext
let errorHandler = badRequestHandler 420

let req = singleton 42 >=> error "failed" >=> catch errorHandler
let req =
singleton 42
>=> error "failed"
>=> catch errorHandler

// Act
let! content = req |> runUnsafeAsync ctx
Expand All @@ -121,7 +126,10 @@ let ``Not catching errors is Error`` () =
let ctx = Context.defaultContext
let errorHandler = badRequestHandler 420

let req = singleton 42 >=> catch errorHandler >=> error "failed"
let req =
singleton 42
>=> catch errorHandler
>=> error "failed"

// Act
let! result = req |> runAsync ctx
Expand All @@ -137,7 +145,9 @@ let ``Sequential handlers is Ok`` () =
task {
// Arrange
let ctx = Context.defaultContext
let req = sequential [ singleton 1; singleton 2; singleton 3; singleton 4; singleton 5 ]

let req =
sequential [ singleton 1; singleton 2; singleton 3; singleton 4; singleton 5 ]

// Act
let! content = req |> runUnsafeAsync ctx
Expand All @@ -151,7 +161,9 @@ let ``Sequential handlers with an Error is Error`` () =
task {
// Arrange
let ctx = Context.defaultContext
let req = sequential [ singleton 1; singleton 2; error "fail"; singleton 4; singleton 5 ]

let req =
sequential [ singleton 1; singleton 2; error "fail"; singleton 4; singleton 5 ]

// Act
let! result = req |> runAsync ctx
Expand All @@ -169,7 +181,9 @@ let ``Concurrent handlers is Ok`` () =
task {
// Arrange
let ctx = Context.defaultContext
let req = concurrent [ singleton 1; singleton 2; singleton 3; singleton 4; singleton 5 ]

let req =
concurrent [ singleton 1; singleton 2; singleton 3; singleton 4; singleton 5 ]

// Act
let! result = req |> runAsync ctx
Expand All @@ -178,7 +192,7 @@ let ``Concurrent handlers is Ok`` () =
test <@ Result.isOk result @>

match result with
| Ok content -> test <@ content = Some [ 1; 2; 3; 4; 5 ] @>
| Ok content -> test <@ content = [ 1; 2; 3; 4; 5 ] @>
| Error err -> failwith "error"
}

Expand All @@ -187,7 +201,9 @@ let ``Concurrent handlers with an Error is Error`` () =
task {
// Arrange
let ctx = Context.defaultContext
let req = concurrent [ singleton 1; singleton 2; error "fail"; singleton 4; singleton 5 ]

let req =
concurrent [ singleton 1; singleton 2; error "fail"; singleton 4; singleton 5 ]

// Act
let! result = req |> runAsync ctx
Expand Down

0 comments on commit b1123a5

Please sign in to comment.