Skip to content

Commit

Permalink
refactor: Remove pipeline abstraction (#144)
Browse files Browse the repository at this point in the history
* refactor: Remove pipeline abstraction

* Remove unnecessary code

* Move exception to core

* Formatting

* Cleanup code

* Update version

* Bump major version
  • Loading branch information
dbrattli authored Apr 18, 2024
1 parent a521683 commit 2ac2e0e
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 379 deletions.
5 changes: 2 additions & 3 deletions src/HttpHandler/Builder.fs → src/Builder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace Oryx

open Oryx.Pipeline

type RequestBuilder() =
member _.Zero() : HttpHandler<unit> = httpRequest
Expand All @@ -12,14 +11,14 @@ type RequestBuilder() =
member _.Return(content: 'TResult) : HttpHandler<'TResult> = singleton content
member _.ReturnFrom(req: HttpHandler<'TResult>) : HttpHandler<'TResult> = req
member _.Delay(fn) = fn ()
member _.Combine(source, other) = source |> Core.bind (fun _ -> other)
member _.Combine(source, other) = source |> bind (fun _ -> other)

member _.For(source: 'TSource seq, func: 'TSource -> HttpHandler<'TResult>) : HttpHandler<'TResult list> =
source |> Seq.map func |> sequential

/// Binds value of 'TValue for let! All handlers runs in same context within the builder.
member _.Bind(source: HttpHandler<'TSource>, fn: 'TSource -> HttpHandler<'TResult>) : HttpHandler<'TResult> =
source |> Core.bind fn
source |> bind fn

[<AutoOpen>]
module Builder =
Expand Down
19 changes: 19 additions & 0 deletions src/Core.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2020 Cognite AS
// SPDX-License-Identifier: Apache-2.0

namespace Oryx

open System.Threading.Tasks

type IHttpNext<'TSource> =
abstract member OnSuccessAsync: ctx: HttpContext * content: 'TSource -> Task<unit>
abstract member OnErrorAsync: ctx: HttpContext * error: exn -> Task<unit>
abstract member OnCancelAsync: ctx: HttpContext -> Task<unit>

type HttpHandler<'TResult> = IHttpNext<'TResult> -> Task<unit>

exception HttpException of (HttpContext * exn) with
override this.ToString() =
match this :> exn with
| HttpException(_, err) -> err.ToString()
| _ -> failwith "This should not never happen."
58 changes: 25 additions & 33 deletions src/Pipeline/Error.fs → src/Error.fs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
// Copyright 2020 Cognite AS
// SPDX-License-Identifier: Apache-2.0

namespace Oryx.Pipeline
namespace Oryx

open System

open FSharp.Control.TaskBuilder
open Oryx

module Error =
/// Handler for protecting the pipeline from exceptions and protocol violations.
let protect<'TContext, 'TSource> (source: Pipeline<'TContext, 'TSource>) : Pipeline<'TContext, 'TSource> =
/// Handler for protecting the HttpHandler from exceptions and protocol violations.
let protect<'TSource> (source: HttpHandler<'TSource>) : HttpHandler<'TSource> =
fun next ->
let mutable stopped = false

{ new IAsyncNext<'TContext, 'TSource> with
{ new IHttpNext<'TSource> with
member _.OnSuccessAsync(ctx, content) =
task {
match stopped with
Expand Down Expand Up @@ -47,12 +46,12 @@ module Error =
|> source

/// Handler for catching errors and then delegating to the error handler on what to do.
let catch<'TContext, 'TSource>
(errorHandler: 'TContext -> exn -> Pipeline<'TContext, 'TSource>)
(source: Pipeline<'TContext, 'TSource>)
: Pipeline<'TContext, 'TSource> =
let catch<'TSource>
(errorHandler: HttpContext -> exn -> HttpHandler<'TSource>)
(source: HttpHandler<'TSource>)
: HttpHandler<'TSource> =
fun next ->
{ new IAsyncNext<'TContext, 'TSource> with
{ new IHttpNext<'TSource> with
member _.OnSuccessAsync(ctx, content) =
task {
try
Expand All @@ -66,7 +65,6 @@ module Error =
match err with
| PanicException error -> return! next.OnErrorAsync(ctx, error)
| _ -> do! (errorHandler ctx err) next

}

member _.OnCancelAsync(ctx) = next.OnCancelAsync(ctx) }
Expand All @@ -79,22 +77,22 @@ module Error =
| Error
| Panic

/// Choose from a list of pipelines to use. The first middleware that succeeds will be used. Handlers will be
/// Choose from a list of HttpHandlers to use. The first middleware that succeeds will be used. Handlers will be
/// tried until one does not produce any error, or a `PanicException`.
let choose<'TContext, 'TSource, 'TResult>
(handlers: (Pipeline<'TContext, 'TSource> -> Pipeline<'TContext, 'TResult>) list)
(source: Pipeline<'TContext, 'TSource>)
: Pipeline<'TContext, 'TResult> =
let choose<'TSource, 'TResult>
(handlers: (HttpHandler<'TSource> -> HttpHandler<'TResult>) list)
(source: HttpHandler<'TSource>)
: HttpHandler<'TResult> =
fun next ->
let exns: ResizeArray<exn> = ResizeArray()

{ new IAsyncNext<'TContext, 'TSource> with
{ new IHttpNext<'TSource> with
member _.OnSuccessAsync(ctx, content) =
let mutable state = ChooseState.Error

task {
let obv =
{ new IAsyncNext<'TContext, 'TResult> with
{ new IHttpNext<'TResult> with
member _.OnSuccessAsync(ctx, content) =
task {
exns.Clear() // Clear to avoid buildup of exceptions in streaming scenarios.
Expand All @@ -106,10 +104,10 @@ module Error =
member _.OnErrorAsync(_, error) =
task {
match error, state with
| PanicException(_), st when st <> ChooseState.Panic ->
| PanicException _, st when st <> ChooseState.Panic ->
state <- ChooseState.Panic
return! next.OnErrorAsync(ctx, error)
| SkipException(_), st when st = ChooseState.NoError ->
| SkipException _, st when st = ChooseState.NoError ->
// Flag error, but do not record skips.
state <- ChooseState.Error
| _, ChooseState.Panic ->
Expand All @@ -122,7 +120,7 @@ module Error =

member _.OnCancelAsync(ctx) = next.OnCancelAsync(ctx) }

/// Proces handlers until `NoError` or `Panic`.
// Process handlers until `NoError` or `Panic`.
for handler in handlers do
if state = ChooseState.Error then
state <- ChooseState.NoError
Expand All @@ -134,9 +132,9 @@ module Error =
()
| ChooseState.Error, exns when exns.Count > 1 ->
return! next.OnErrorAsync(ctx, AggregateException(exns))
| ChooseState.Error, exns when exns.Count = 1 -> return! next.OnErrorAsync(ctx, exns.[0])
| ChooseState.Error, exns when exns.Count = 1 -> return! next.OnErrorAsync(ctx, exns[0])
| ChooseState.Error, _ ->
return! next.OnErrorAsync(ctx, SkipException "Choose: No hander matched")
return! next.OnErrorAsync(ctx, SkipException "Choose: No handler matched")
| ChooseState.NoError, _ -> ()
}

Expand All @@ -151,25 +149,19 @@ module Error =
|> source

/// Error handler for forcing error. Use with e.g `req` computational expression if you need to "return" an error.
let fail<'TContext, 'TSource, 'TResult>
(err: Exception)
(source: Pipeline<'TContext, 'TSource>)
: Pipeline<'TContext, 'TResult> =
let fail<'TSource, 'TResult> (err: Exception) (source: HttpHandler<'TSource>) : HttpHandler<'TResult> =
fun next ->
{ new IAsyncNext<'TContext, 'TSource> with
{ new IHttpNext<'TSource> with
member _.OnSuccessAsync(ctx, content) = next.OnErrorAsync(ctx, err)
member _.OnErrorAsync(ctx, exn) = next.OnErrorAsync(ctx, exn)
member _.OnCancelAsync(ctx) = next.OnCancelAsync(ctx) }
|> source

/// Error handler for forcing a panic error. Use with e.g `req` computational expression if you need break out of
/// the any error handling e.g `choose` or `catch`•.
let panic<'TContext, 'TSource, 'TResult>
(err: Exception)
(source: Pipeline<'TContext, 'TSource>)
: Pipeline<'TContext, 'TResult> =
let panic<'TSource, 'TResult> (err: Exception) (source: HttpHandler<'TSource>) : HttpHandler<'TResult> =
fun next ->
{ new IAsyncNext<'TContext, 'TSource> with
{ new IHttpNext<'TSource> with
member _.OnSuccessAsync(ctx, content) =
next.OnErrorAsync(ctx, PanicException(err))

Expand Down
File renamed without changes.
2 changes: 0 additions & 2 deletions src/HttpHandler/Fetch.fs → src/Fetch.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ open System.Net.Http.Headers
open System.Web

open FSharp.Control.TaskBuilder
open Oryx.Pipeline

[<AutoOpen>]
module Fetch =
Expand Down Expand Up @@ -101,7 +100,6 @@ module Fetch =
response.Content
)


response.Dispose()
return result
with ex when not (ex :? HttpException) ->
Expand Down
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 2ac2e0e

Please sign in to comment.