Quick reference for the public modules, types, and functions in Orleans.FSharp.
Reference tables, not tutorials. Every section names the guide that carries the semantics; look
there for what a thing means and here for what it is called.
The functional grain runtime is the current authoring model and comes
first. Shared Orleans helpers follow it. The superseded authoring surface has its own
Legacy API Reference.
Where the names in the functional tables come from. Every custom-operation name and every
context member below is pinned by tests/Orleans.FSharp.Tests/FunctionalSurfaceTests.fs, which
reflects over the builders and the context type and asserts the exact set. A name that appears here
and not there, or there and not here, is a bug in one of the two.
The current grain authoring model. A user-authored API record instead of a C# CodeGen
interface, a contract that declares the wire and delivery policy, and a definition that binds
handlers to it. See Functional Grain Runtime for the full guide.
Stream id whose key is the contract’s own grain-key bytes
FunctionalGrain.channelId
contract -> string -> 'Key -> ChannelId
The same for a broadcast channel
The three contract entry points are type functions — generic values, not functions of unit.
grainContract<RoomActor, RoomId, RoomApi>is the builder, so the CE braces follow the type
arguments directly and there is no () to write. F# re-evaluates a type function at every mention,
so each contract expression opens on its own builder instance (pinned by
tests/Orleans.FSharp.Tests/FunctionalSurfaceTests.fs, “each entry point mention yields its own
builder”). The other four rows are ordinary functions and take their argument as usual.
FunctionalGrain is a static class, so ref/rawRef generalize only where F# lets a static-class
application generalize — see Functional grains, “The FunctionalGrain
static-class inference rule”.
The handler’s returned state is discarded; interleaves with other read-only calls
oneWay
selector
The caller’s Task completes once the message enters the local send path
alwaysInterleave
selector
Interleaves regardless of readOnly/oneWay; also state-neutral. Rejected at sealing when the contract declares reentrant or mayInterleave
transactional
Orleans.TransactionOption -> selector
Orleans transaction policy for one operation (Functional grains, “Distributed ACID transactions”). Orleans’ own enum, not this library’s Orleans.FSharp.Transactions.TransactionOption DU
operationId
string -> selector
Override an operation’s wire ID, decoupling it from the F# field name. A second overload takes a StreamSelector
sinceVersion
int -> selector
The version an operation was introduced at; an admitted older call is refused for it by name. A second overload takes a StreamSelector
reentrant
—
Whole-grain reentrancy — every request may enter a busy activation. Does not make whole-state replacement concurrency-safe
mayInterleave
(IFunctionalRequestMetadata -> bool)
Per-request interleave predicate over protocol metadata only; mutually exclusive with reentrant. Orleans consults it for the running request too
acceptsVersions
VersionPolicy
Exact (default) or BackwardCompatible n — which request versions this definition admits
operationId and sinceVersion are the only two per-operation declarations that compose with a
streaming field; the four admission policies are refused at sealing.
Every API field takes exactly one F# argument. Prefer a named record for multi-input domain data
(typing: Typing -> Task<unit>); tuples remain valid when positional data is intentional. A field
spelled curried fails contract construction. See Functional grains,
“One operation, one argument”.
A journal-aware version of the operations above: request, timer, reminder, stream, and broadcast
handlers return events instead of replacement state. A journal still cannot be a transaction
participant or be shared by the many activations of a stateless worker. See
Event Sourcing.
Keyword
Handler signature
Description
initialEventState
'Key -> 'State
The seed the journal folds onto. Required, and first
apply
'State -> 'Event -> 'State
The pure fold. Required, and second — it introduces the event type
logProvider
string
The registered log-consistency provider. Required
journalStorage
string
The grain storage a built-in provider writes through; defaults to the silo’s default IGrainStorage and cannot be combined with customStorage
The confirmed journal length, as it was when the turn started
journalState<'S>()
unit -> 'S
Current confirmed view
journalTentativeState<'S>()
unit -> 'S
Confirmed view plus submitted events
unconfirmedEvents<'E>()
unit -> 'E list
Locally submitted, unconfirmed suffix
raiseEvent(event) / raiseEvents(events)
'E -> unit / 'E list -> unit
Submit without waiting for confirmation
confirmEvents()
unit -> Task
Confirm all submitted entries
snapshotNow()
unit -> unit
Force a custom-storage snapshot after this successful callback’s events; overrides disabled automatic rules
refreshJournal()
unit -> Task
Confirm all submitted events and synchronize the confirmed view with the global journal
retrieveConfirmedEvents<'E>(from, to)
int * int -> Task<'E list>
Read a provider-supported half-open event segment
clearJournal()
unit -> Task
Clear the whole log and restore the initial state
enableJournalStats() / disableJournalStats()
unit -> unit
Toggle Orleans log-consistency statistics
getJournalStats()
unit -> LogConsistencyStatistics
Read collected statistics
raiseConditional(events)
'Event list -> Task<bool>
Append and confirm inside the turn; reports whether it was accepted
raiseConditionalEvent(event)
'Event -> Task<bool>
Single-event conditional append
tryGetRequestContext<'T>(name)
string -> 'T option
Typed Orleans request-context read
setRequestContext(name, value)
string -> 'V -> unit
Request-context write
removeRequestContext(name)
string -> unit
Request-context removal
The journal members live on the one context type rather than on a journaled variant of it, and
all refuse with a definition-stage diagnostic on an ordinary grainFor definition.
FunctionalGrainRef<'Actor, 'Key, 'Api> — the bound reference
The descriptor’s (stateName, providerName, storedType) triple is its logical identity, and it is
durable identity — see Functional grains, “Persistence model”.
A projection, run inside Orleans’ read lock and returned uncopied
FunctionalTransactionalState<'S>.update
('S -> 'S) -> Task<unit>
Replace the value, inside Orleans’ write lock
FunctionalTransactionalState<'S>.updateWith
('S -> 'S * 'R) -> Task<'R>
Replace and return a result
Both update functions are synchronous by type: Orleans runs them inside the transactional
state’s reader-writer lock and rejects re-entering the same state from inside a callback.
int -> IAsyncEnumerable<'T> -> IAsyncEnumerable<'T>
Set the pull batch size of a functional stream call
A streaming field is 'Arg -> IAsyncEnumerable<'Item>, not 'Arg -> Task<...>; that is what makes
it a second field kind rather than an ordinary operation. See
Streaming replies.
A handler record whose every field is 'Msg -> Task<unit>. Push to a client-hosted observer with
no application code generation; see Functional grains, “Push to clients:
functional observers”.
Wire identity of the observer; defaults to the brand’s simple CLR name, which requires a simple, non-generic, non-nested brand exactly as a derived grainType does
version
int
Contract version; defaults to 1
A push operation’s wire ID is always its handler-record field name — there is no operationId
override, so the notifying and observing sides cannot drift apart.
Liveness window a subscription must be refreshed within
Subscribe
handle -> unit
Add or refresh a subscription
Unsubscribe
handle -> bool
Remove one subscription
Notify
selector -> 'Msg -> Task<unit>
Fan out to every live subscription; resolves its selector once per call, not once per subscriber
RemoveExpired
unit -> unit
Drop subscriptions past the liveness window
Clear
unit -> unit
Forget every subscription
Count
int
Live subscription count
Expiry
TimeSpan
The configured liveness window
A manager is a mutable object held in ephemeral handler state. It holds live object references,
so it must never be part of a persistent state type — the F# codec refuses one.
These are the complete application-facing members of the typed CustomStorage bridge. The storage
implementation, not the runtime, owns durable I/O; the runtime owns replay through the definition’s
single apply fold.
Mutable Policy; mutable ManualSnapshotMaxConflictRetries (default 3, must be >= 0, counts retries after the first CAS attempt)
FunctionalJournalPermanentStorageException
Constructors (message: string) and (message: string, innerException: Exception)
Ordinary exceptions raised while Orleans’ CustomStorage adaptor reads or appends events are
considered transient and remain eligible for its retry loop. A zero-event manual snapshot and
Clear call the typed store directly: an ordinary exception fails that call once without
deactivation, and the caller may retry explicitly. Throw
FunctionalJournalPermanentStorageException only when the same operation cannot succeed without
an application, configuration, or durable-data change. The functional runtime exits that retry
loop, fails the current journal operation, and requests deactivation so a later call starts with a
fresh activation and durable read. The permanent exception also fails and deactivates on both
direct paths.
Snapshot resolution is deterministic: context.snapshotNow() for the successful callback wins;
otherwise the definition’s snapshotPolicy wins; Inherit or no definition policy uses
FunctionalJournalSnapshotOptions.Policy; the silo default is Disabled. These policies apply
only to definitions with customStorage. See Event Sourcing.
ManualSnapshotMaxConflictRetries applies to a zero-event manual snapshot requested through
context.snapshotNow(). The default 3 permits the initial compare-and-swap attempt plus three
retries. Each retry refreshes durable state and recomputes the snapshot; 0 permits only the first
attempt, and exhausting the limit fails the call without writing the snapshot.
Configure the silo-wide rule inherited by custom-storage definitions
UseFunctionalJournalSnapshots
ISiloBuilder * every:int -> ISiloBuilder
Set a positive fixed event-count default
AddFunctionalGrainClient
IClientBuilder -> IClientBuilder
Register the client-side transport on a client-only process (Orleans.FSharp)
Both silo registrations install the client transport too, and both are idempotent per definition
value. A standalone F# host also has to make Orleans see the assemblies it reaches only through F#
— see Functional grains, “Running a silo from a standalone F# process”.
Full options: retry + circuit breaker + timeout. The timeout spans the whole sequence; the pipeline is rebuilt per call, so circuit state is not shared
Tip: For 2–4 fixed grain calls, prefer the F# and! applicative keyword inside task {} — it is more ergonomic and starts every bound call before awaiting any of them, exactly as these do. Use GrainBatch when the number of grains is dynamic.
Deprecated — carries [<Obsolete>] (a warning, not an error) and still returns always None: StreamSubscriptionHandle exposes no token, so there was never anything to return. Replacement: subscribeWithToken / subscribeFromWithToken, or context.streamSequenceToken in an onStream hook
A functional definition consumes a stream declaratively with onStream instead; see
Streaming and Functional grains, “Implicit subscriptions”.