Header menu logo FCQRS

FSharp Module

 Idiomatic-F# functional facade for FCQRS.

 Gives F# consumers the same one-call ergonomics the C# host-builder
 (HostExtensions.fs) gives C#, but with F# idioms: records-of-functions for the
 definitions, typed handles for the results, an explicit wiring pipeline, and
 plain helpers for saga side effects. It is a *pure addition* that wraps only the
 existing primitives (IActor.InitializeActor / SagaBuilder.initSimple / Query.init
 / InitializeSagaStarter / CreateCommandSubscription / Actor.api) and changes
 nothing in the C# interop layer or the core.

     open FCQRS.FSharp
     let api       = Fcqrs.actor config loggerFactory (Some (Fcqrs.connect DBType.Sqlite conn)) "Cluster"
     let documents = Fcqrs.aggregate api { Name="Document"; Initial=...; Decide=...; Fold=... }
     let slugs     = Fcqrs.aggregate api { Name="Slug"; Initial=...; Decide=...; Fold=... }
     let publication = Fcqrs.saga api (publicationDef documents.Factory slugs.Factory)
     Fcqrs.wireSagaStarters api [ publication ]
     let subs      = Fcqrs.projection api (Projection.single 0 updateReadModel)
     // (Projection.multi when you must control which notifications publish)
     // send a command and await the matching aggregate reply:
     let! ev = documents.Send (Fcqrs.newCid()) (Fcqrs.aggregateId id) cmd (fun e -> ...)

Types and nested modules

Type/Module Description

Fcqrs

Projection (Module)

Constructors for the two projection-handler shapes.

Aggregate<'State, 'Command, 'Event>

A pure aggregate definition: the four things that define an event-sourced aggregate. No wiring, no IActor.

AggregateFactory

An aggregate's entity-ref factory: an id -> its sharded actor ref.

AggregateHandle<'Command, 'Event>

What you get back after registering an aggregate.

Projection (Type)

A read-model projection definition.

Saga<'Data, 'State, 'OriginatorEvent>

A pure saga definition. HandleEvent is obj-based so a single saga can match events from several aggregates; ApplySideEffects returns the transition plus the commands to dispatch.

SagaHandle

What you get back after registering a saga.

Functions and values

Function or value Description

defer event

Full Usage: defer event

Parameters:
    event : 'e

Returns: EventAction<'e>
event : 'e
Returns: EventAction<'e>

dispatch description

Full Usage: dispatch description

Parameters:
    description : 'description

Returns: EventAction<'event>

Dispatch an async side effect (a "mini saga" without persistence) by its DATA description. `decide` stays pure and inspectable; `decide cmd state = dispatch (ClusterThemes texts)` holds by structural equality, and the oracle lives in the runner registered at `Fcqrs.aggregateWithEffects`. EPHEMERAL: the in-flight work is not journaled; use a saga when the result must survive a crash. See `EventAction.RunAsync`.

description : 'description
Returns: EventAction<'event>

expecting deadline retryEvery resend

Full Usage: expecting deadline retryEvery resend

Parameters:
Returns: SagaTransition<'State>

Declare a saga expectation: stay in this state, send `resend` now, re-send exactly those commands on `retryEvery`, and once `deadline` (measured from the persisted state-entry time, so restarts cannot postpone it) has passed without a state transition, deliver an ExpectationExhausted message to HandleEvent. The handler must answer it with a transition, typically to a failure or compensation state. Resend commands must be retry-safe and must not carry their own DelayInMs.

deadline : TimeSpan
retryEvery : RetrySchedule
resend : ExecuteCommand list
Returns: SagaTransition<'State>

journalType name

Full Usage: journalType name

Parameters:
    name : string

Returns: Type * string

A (type, stable-journal-name) pair for Fcqrs.journalTypes.

name : string
Returns: Type * string

nextState state

Full Usage: nextState state

Parameters:
    state : 'state

Returns: SagaTransition<'state>
state : 'state
Returns: SagaTransition<'state>

persist event

Full Usage: persist event

Parameters:
    event : 'e

Returns: EventAction<'e>
event : 'e
Returns: EventAction<'e>

persistAll events

Full Usage: persistAll events

Parameters:
    events : 'e list

Returns: EventAction<'e>
events : 'e list
Returns: EventAction<'e>

persistAndSnapshot event

Full Usage: persistAndSnapshot event

Parameters:
    event : 'e

Returns: EventAction<'e>
event : 'e
Returns: EventAction<'e>

persistIf shouldPersist event

Full Usage: persistIf shouldPersist event

Parameters:
    shouldPersist : bool
    event : 'e

Returns: EventAction<'e>

Persist the event when `shouldPersist`, else defer it (published and folded but not journalled). The deferred fold should preserve state, because it cannot be replayed. This is the idempotent "emit this verdict, write it only once" shape.

shouldPersist : bool
event : 'e
Returns: EventAction<'e>

stay

Full Usage: stay

Returns: SagaTransition<'state>
Returns: SagaTransition<'state>

stop

Full Usage: stop

Returns: SagaTransition<'state>
Returns: SagaTransition<'state>

toActor actorRef command

Full Usage: toActor actorRef command

Parameters:
Returns: ExecuteCommand

Send a command to a concrete actor ref.

actorRef : IActorRef<obj>
command : obj
Returns: ExecuteCommand

toActorAfter actorRef delayMs taskName command

Full Usage: toActorAfter actorRef delayMs taskName command

Parameters:
    actorRef : IActorRef<obj>
    delayMs : int64
    taskName : string
    command : obj

Returns: ExecuteCommand

Delayed variant of toActor.

actorRef : IActorRef<obj>
delayMs : int64
taskName : string
command : obj
Returns: ExecuteCommand

toAggregate factory id command

Full Usage: toAggregate factory id command

Parameters:
Returns: ExecuteCommand

Send a command to a specific aggregate instance by id (cross-aggregate).

factory : AggregateFactory
id : string
command : obj
Returns: ExecuteCommand

toAggregateAfter factory id delayMs taskName command

Full Usage: toAggregateAfter factory id delayMs taskName command

Parameters:
    factory : AggregateFactory
    id : string
    delayMs : int64
    taskName : string
    command : obj

Returns: ExecuteCommand

Delayed variant of toAggregate.

factory : AggregateFactory
id : string
delayMs : int64
taskName : string
command : obj
Returns: ExecuteCommand

toOriginator factory command

Full Usage: toOriginator factory command

Parameters:
Returns: ExecuteCommand

Send a command back to the saga's originator aggregate.

factory : AggregateFactory
command : obj
Returns: ExecuteCommand

toOriginatorAfter factory delayMs taskName command

Full Usage: toOriginatorAfter factory delayMs taskName command

Parameters:
Returns: ExecuteCommand

Delayed variant of toOriginator (delayMs, taskName key).

factory : AggregateFactory
delayMs : int64
taskName : string
command : obj
Returns: ExecuteCommand

toSelf command

Full Usage: toSelf command

Parameters:
    command : obj

Returns: ExecuteCommand

Send a command to the saga itself (raw, lands in HandleEvent), for example a timeout.

command : obj
Returns: ExecuteCommand

toSelfAfter delayMs taskName command

Full Usage: toSelfAfter delayMs taskName command

Parameters:
    delayMs : int64
    taskName : string
    command : obj

Returns: ExecuteCommand

Schedule a message to the saga itself after a delay, the idiomatic saga timeout: enter a state, toSelfAfter a reminder, and HandleEvent decides whether it still matters when it arrives.

delayMs : int64
taskName : string
command : obj
Returns: ExecuteCommand

total onError work

Full Usage: total onError work

Parameters:
    onError : exn -> 'command
    work : Async<'command>

Returns: Async<'command>

Make an effect-runner body TOTAL: run `work`, mapping ANY exception (oracle error, timeout, cancellation) to a command via `onError`, so the runner never lets an exception escape (which would fail-fast the process).

onError : exn -> 'command
work : Async<'command>
Returns: Async<'command>

transitionTo state

Full Usage: transitionTo state

Parameters:
    state : 'state

Returns: EventAction<'state>
state : 'state
Returns: EventAction<'state>

Type something to start searching.