-
Notifications
You must be signed in to change notification settings - Fork 40
Home
Welcome to the FSharpLu wiki!
This modules provides improved Json serialization over the default formatting used by
Newtonsoft's Json.Net. The generated Json is more compact and maps more closely to the corresponding value definition in F#.
For example the value [Some 5; None; Some 6]
gets serialized to just
val it : string = "[ 5, null, 6 ]"
instead of the rather verbose
(* Default Json.Net serialization *)
val it : string = "[
{
"Case": "Some",
"Fields": [ 5 ]
},
null,
{
"Case": "Some",
"Fields": [ 6 ]
}
]"
If you are doing web development with Giraffe you can also set FSharpLu.Json as the default serializer.
For more details see documentation for module FSharpLu.Json.
This modules offers F#-like strongly-typed logging helpers for the System.Diagnostics
logging functions.
For instance instead of calling System.Diagnostics.TraceInformation
and providing untyped formatting parameters ala C# you can write instead:
Trace.info "Command '%s' with arguments %A exited with code: %d" command arguments exitCode
Another useful helper is Trace.failwith
which behaves like F#'s failwith
operator except that it also trace the error message using System.Diagnostics.TraceError
before throwin an exception. Example:
if succeeds then
someResult
else
Trace.failwith "Something went wrong. Error message: %s" errorMessage
This module provides a general purpose strongly-typed logging class for use in situations where global trace logging is not desirable. This can be used for instance in a multi-agent/multi-threaded setting where each agent needs to log information to a separate output channel without interfering with each other and without requiring synchronizing access to a global logger entity. It lets you instantiate logging objects of type Logger<'a,'s>
where 'a
is the type of messages being logged and 's
is the type of the internal state maintained by the logger. You only need to provide a custom Action
to be performed when a message is being logged and the Logger
types provides all the strongly-typed logging helpers for you.
These modules implements a state-machine framework that you can use to implement
reliable long-running asynchronous operations. The ServiceRequest
module exposes queue-based
request processing functions. The StateMachine
module exposes an API to easily implement request
handlers using state machines. The service requests manager persists the state of the state machine
on some underlying queue system. This guarantees that requests gets picked up even if the agents processing the request die or get killed (e.g. VM failure, system update).
Two queueing API implementations are provided: one in-memory (based on concurrent dictionary) and one based on Azure Storage queue API.
Here is an example demonstrating a service offering a single request Calculate
implemented
as an state-machine agent with four states. This examples demonstrate how agents can recursively call each other.
In addition to the 'Goto' and 'Call' transitions used in the following example, other more complex types of transition are
supported, like fork, joining on WhenAll and WhenAny condition, CoReturn, in-process and out-of-process asynchronous Sleep. See unit tests HofstadterCallTest.fs
, StateMachineAgentTests.fs
, QueueSchedulerTests.fs
and AzureQueueSchedulerTests.fs
for more examples.
/// Hofstadter Female and Male sequences test
/// See https://en.wikipedia.org/wiki/Hofstadter_sequence#Hofstadter_Female_and_Male_sequences
open Microsoft.FSharpLu.Actor.StateMachine
open Microsoft.FSharpLu.Actor.StateMachine.Agent
open Microsoft.FSharpLu.Actor.QueueScheduler
open Microsoft.FSharpLu.Actor.ServiceRequests
open Microsoft.FSharpLu.Actor
open System.Collections.Generic
type States =
| Start
| FirstCallReturn
| SecondCallReturn
| ReturnResult of int
type Gender = Male | Female
with
member x.Opposite =
match x with
| Male -> Female
| Female -> Male
type Message =
| Calculate of StatefulRequest<Gender * int, States>
/// Transition function for a state machine agent calculating the
/// Hofstadter Female and Male sequences
let transition gender =
run (sprintf "%A" gender) []
Message.Calculate
(fun (operations:Operations<_, _, _>) (gender:Gender, n:int) ->
function
| States.Start -> async {
return
match n with
| 0 when gender = Gender.Female ->
Transition.Goto (States.ReturnResult 1)
| 0 when gender = Gender.Male ->
Transition.Goto (States.ReturnResult 0)
| n ->
Transition.Call
((fun m -> {
metadata = Some m
header = ()
calleeReturnResult = None
request = Calculate { state = States.Start; input = gender, n-1 } }),
States.FirstCallReturn)
}
| States.FirstCallReturn -> async {
return Transition.Call
((fun m ->
{
metadata = Some m
header = ()
calleeReturnResult = None
request = Calculate { state = States.Start; input = gender.Opposite, operations.ReturnResult<int>() }
}),
States.SecondCallReturn)
}
| States.SecondCallReturn -> async {
let r = n - operations.ReturnResult<int>()
return Transition.Goto <| ReturnResult r
}
| States.ReturnResult result -> async {
return Transition.Return result
})
Provides a set of common option
type manipulation functions, including the Maybe
monad.
Provides access to application (app.config
) and website (web.config
) configuration file.
let MySetting = Microsoft.FSharpLu.Configuration.getConfigValue "MySettingName"
Helpers for System.Diagnostics
. For instance the startProcessAsync
function allow you to start a system process within an async
block and asynchronoulsy wait for it to terminate:
open Microsoft.FSharpLu.Diagnostics
async {
let! exitCode = Process.startProcessAsync
command
arguments
workingDirectory
Process.ProcessStartFlags.None
Process.ProcessTimeoutAction.NoTimeout
return exitCode = 0
}
Defines combinators and operators to work with asynchronous workflows.
The Compete
operator for instance allows you to start multiple asynchronous operations simultaneously and return
as soon as one of them completes:
let waitForNetworkOrCache =
Async.Compete
[
async {
let! networkResponse = AsyncReadFromNetwork()
return networkResponse
}
async {
let! cache = AsyncReadFromCache()
return cache
}
]
The Synchronization
sub-module implements classic thread synchronization objects like critical section, semaphore and events for use use with asynchronous computation.
open Microsoft.FSharpLu.Async
open Microsoft.FSharpLu.Async.Synchronization
let myTokenPool = new Async.Pool(10)
async {
Trace.info "Acquiring token from the pool without timeout..."
let! token = myTokenPool.AcquireAsync None
Trace.info "Token acquired."
return token
}
File manipulation utilities.
Text parsing utilities.
Security related utilities.
String manipulation functions.
Active patterns used to handle .Net aggregated exceptions in F#.
Augments Seq
module with additional sequence operators; provide F# helpers to operat on the IDictionary
type.