FSharpModule
PackageFCQRS
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 -> ...)
Summary
| Name | Signature | Synopsis |
|---|---|---|
| toOriginator | toOriginator factory command | Send a command back to the saga's originator aggregate. |
| toAggregate | toAggregate factory id command | Send a command to a specific aggregate instance by id (cross-aggregate). |
| toActor | toActor actorRef command | Send a command to a concrete actor ref. |
| toSelf | toSelf command | Send a command to the saga itself (raw, lands in HandleEvent), for example a timeout. |
| toOriginatorAfter | toOriginatorAfter factory delayMs taskName command | Delayed variant of toOriginator (delayMs, taskName key). |
| toAggregateAfter | toAggregateAfter factory id delayMs taskName command | Delayed variant of toAggregate. |
| toActorAfter | toActorAfter actorRef delayMs taskName command | Delayed variant of toActor. |
| toSelfAfter | toSelfAfter delayMs taskName command | 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. |
| expecting | expecting deadline retryEvery resend | 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. |
| journalType | journalType name | A (type, stable-journal-name) pair for Fcqrs.journalTypes. |
| persist | persist event | No description available. |
| persistAll | persistAll events | No description available. |
| persistAndSnapshot | persistAndSnapshot event | No description available. |
| defer | defer event | No description available. |
| persistIf | persistIf shouldPersist event | Persist the event when `shouldPersist`, else defer it (published and folded but not journalled). |
| transitionTo | transitionTo state | No description available. |
| dispatch | dispatch description | Dispatch an async side effect (a "mini saga" without persistence) by its DATA description. |
| total | total onError work | 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). |
| stay | stay | No description available. |
| stop | stop | No description available. |
| nextState | nextState state | No description available. |
Send a command back to the saga's originator aggregate.
Parameters
| Name | Type | Description |
|---|---|---|
| factory | AggregateFactory | |
| command | obj |
Returns
ExecuteCommand
Send a command to a specific aggregate instance by id (cross-aggregate).
Parameters
| Name | Type | Description |
|---|---|---|
| factory | AggregateFactory | |
| id | string | |
| command | obj |
Returns
ExecuteCommand
Send a command to a concrete actor ref.
Parameters
| Name | Type | Description |
|---|---|---|
| actorRef | IActorRef<obj> | |
| command | obj |
Returns
ExecuteCommand
Send a command to the saga itself (raw, lands in HandleEvent), for example a timeout.
Parameters
| Name | Type | Description |
|---|---|---|
| command | obj |
Returns
ExecuteCommand
Delayed variant of toOriginator (delayMs, taskName key).
Parameters
| Name | Type | Description |
|---|---|---|
| factory | AggregateFactory | |
| delayMs | int64 | |
| taskName | string | |
| command | obj |
Returns
ExecuteCommand
Delayed variant of toAggregate.
Parameters
| Name | Type | Description |
|---|---|---|
| factory | AggregateFactory | |
| id | string | |
| delayMs | int64 | |
| taskName | string | |
| command | obj |
Returns
ExecuteCommand
Delayed variant of toActor.
Parameters
| Name | Type | Description |
|---|---|---|
| actorRef | IActorRef<obj> | |
| 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.
Parameters
| Name | Type | Description |
|---|---|---|
| delayMs | int64 | |
| taskName | string | |
| command | obj |
Returns
ExecuteCommand
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.
Parameters
| Name | Type | Description |
|---|---|---|
| deadline | TimeSpan | |
| retryEvery | RetrySchedule | |
| resend | ExecuteCommand list |
Returns
SagaTransition<'State>
A (type, stable-journal-name) pair for Fcqrs.journalTypes.
Parameters
| Name | Type | Description |
|---|---|---|
| name | string |
Returns
Type * string
Parameters
| Name | Type | Description |
|---|---|---|
| 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.
Parameters
| Name | Type | Description |
|---|---|---|
| shouldPersist | bool | |
| event | 'e |
Returns
EventAction<'e>
Parameters
| Name | Type | Description |
|---|---|---|
| state | 'state |
Returns
EventAction<'state>
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`.
Parameters
| Name | Type | Description |
|---|---|---|
| description | 'description |
Returns
EventAction<'event>
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).
Parameters
| Name | Type | Description |
|---|---|---|
| onError | exn -> 'command | |
| work | Async<'command> |
Returns
Async<'command>