Skip to content

Behavior workers

Virtufin.Behavior.DevKit turns any Virtufin.Core behavior (IProcess, IAsyncProcess, IDecide, IIndicator, IExecutor, IAlgebra) into a worker by binding it to CloudEvents:

public sealed class MyWorker() : BehaviorWorkerBase(
    "my",                                   // worker type: names the source and errors
    myProcess.FromCloudEvents(Decode)       // decode, or Decoded<T>.Skip
             .ToCloudEvents(Encode)         // zero or more Outgoing per step
             .RequireConfig("scenarioid")); // checked before stepping

BehaviorWorkerBase is an IMultiOutputWorker: one input may produce zero, one or several outputs, each with its own id, type, topic and subject, and the common envelope (carried extensions, inherited eventtime). The domain devkits are thin layers over it: StrategyWorkerBase (strategy-devkit), ExecutorWorkerBase (execution-devkit), IndicatorWorkerBase (indicator-devkit) and MarketDataWorkerBase (market-data-devkit).

Composing processes

BehaviorExtensions holds the generic combinators; every result is a plain value, testable without WorkManager or CloudEvents:

Combinator Result
process.AsAsync() lifts an IProcess to IAsyncProcess
algebra.AsProcess() an IAlgebra as a process whose output is the folded state
process.PerKey<…, TKey>() one independent copy of the process per key (e.g. per symbol)

The domain adapters live with their domains: decide.WithPortfolio(algebra) in Strategy.DevKit, executor.AsAsyncProcess() in Execution.DevKit, and indicator.AsProcess() in Indicator.DevKit.

Binary payloads

A binding's decoder normally receives the event's JSON payload, decoded by the strict codec (StrictJsonCodec), where a payload that is not JSON is an error. For a payload that is not JSON (an order book image, a FlatBuffers sample), construct the worker with LenientJsonCodec (BehaviorWorkerBase(workerType, new LenientJsonCodec())): such an event decodes to an empty object and the decoder reads CloudEvent.Data (bytes) from the event it is given.

Names

NameFragments.For(typeof(MyWorker)) composes the worker's naming registry: virtufin.core, every fragment embedded in the worker's assembly, and the fragments this package owns, virtufin.worlds and virtufin.trading (see Naming). Names are never built by hand.

Testing

BehaviorTestHost drives a worker in-process: ProcessAllAsync returns every output of one input, and Payload decodes an output's JSON data.

Moved here from strategy-devkit in 0.31.0, with the naming fragments it owns.