F# async service library

HyperF

F# async service framework prototype inspired in part by Your server as a function. The framework provides combinators for implementing various service interaction patterns. The goal isn't to abstract over transports, but to instead embrace them and make working with them easier.

Central Abstractions

Service

type Service<'Req, 'Res> = 'Req -> Async<'Res>

A service is a function from a request onto an asynchronous response. A service and a service client are symmetric - expressed by the same interface.

Filter

type Filter<'Req, 'ReqInner, 'ResInner, 'Res> = 'Req -> Service<'ReqInner, 'ResInner> -> Async<'Res>

Filters compose and they allow interception of service requests and responses. They can be used to implement various cross-cutting concerns, such as authentication, logging, metrics, serialization, etc. Filters can be interpretted as Kleisli arrows onto the continuation monad and therefore they compose via Kleisli composition.

Modules

HTTP Module

The HTTP module contains combinators for HTTP services carried by message types in System.Net.Http.

#r "HyperF.dll"

open Http
open Route

let routes = [
     
    Get("/get_plain_text/:id") => fun _ -> HttpRes.plainText "hello world"

    Get("/echo_id/:id") => (^) (fun (req,ri,model:int) -> HttpRes.plainText (sprintf "id=%i" model))

    Post("/post/:id") => 
        fun _ -> async {
            do! Async.Sleep(1000)
            return! HttpRes.plainText "post" }

    Sub("/sub") ==> [
    
        Get("/nested") => fun _ -> HttpRes.plainText "/sub/nested"

    ]    

    All => (fun _ -> HttpRes.plainText "*")
] 

let httpService = 
    Filter.identity 
    |> Filter.andThen Filters.printBeforeAfterTag
    |> Filter.toService (routes |> Route.toService)

Http.host "http://+:8081/" httpService |> Async.RunSynchronously

Services are hosted via System.Net.HttpListener.

Routing

type Route = HttpReq -> Async<HttpResp> option

A route is represented simlarly to a service with the exception that a response may or may not be provided depending on whether the route criteria were matched. Routes are typically declared as a combination of a match criteria and a service. Routing multiplexes HTTP requests into finer grained services. Routes form monoids and as such can be combined. Finally, given a catch-all route, such as an HTTP 404 route, routes are combined into services.

Bus Module

The bus module contains combinators to support various messaging patters, such as pub/sub, request/reply, query/response, fire and forget, process managers (sagas), etc.

Central Abstractions

Message Service

type MessageService<'res> = Service<Message, 'res>

type MessageService = MessageService<Message>

type MessageSink = MessageService<unit>

Process Manager

Coming soon...

Event Sourcing Module

Coming soon...

Please refer to errornoerror.com for more similar questions