Overview
The effect system consists of:Effect- A single side effect (immediate message or future)EffectFuture- An asynchronous effect that will eventually produce a messageEffects- A collection of effects with change tracking
Effect
Represents a single side effect to be executed.Variants
Msg
An immediate message that will be dispatched to the model.Future
An asynchronous operation that will eventually produce a message.EffectFuture
Defines how an asynchronous effect should be executed.Variants
Concurrent
Executes the future concurrently (in parallel) usingEnv::exec_concurrent.
Use for:
- Independent operations
- API requests that can run in parallel
- Non-blocking background tasks
Sequential
Executes the future sequentially (queued) usingEnv::exec_sequential.
Use for:
- Operations that must happen in order
- Storage updates that shouldn’t race
- Operations that depend on previous results
Effects
A collection of effects with metadata about whether they change the model state.Fields
effects- Vector of effects to executehas_changed- Whether the effects represent a state change
Constructors
none
Creates an Effects with no effects but marked as changed.one
Creates an Effects with a single effect.many
Creates an Effects with multiple effects.msg
Creates an Effects from a single message.msgs
Creates an Effects from multiple messages.future
Creates an Effects from a single future.futures
Creates an Effects from multiple futures.Methods
unchanged
Marks the effects as not changing the model state.has_changed is false, the Runtime won’t emit a NewState event.
Example:
join
Combines two Effects collections.has_changed will be true if either collection has changed.
Example:
len
Returns the number of effects.is_empty
Returns whether there are any effects.Default
The default Effects is an empty, unchanged collection.Usage Patterns
Model Update with Effects
Multiple Effects
Conditional Effects
Sequential vs Concurrent
Best Practices
Always handle effect results
Always handle effect results
Every future effect should eventually produce a message that the model handles. This ensures proper error handling and state updates.
Use unchanged() for side-effect-only operations
Use unchanged() for side-effect-only operations
If an update only produces effects without changing state, mark it as
unchanged() to avoid unnecessary NewState events.Prefer concurrent for independent operations
Prefer concurrent for independent operations
Use
EffectFuture::Concurrent for operations that can run in parallel, like multiple API requests.Use sequential for dependent operations
Use sequential for dependent operations
Use
EffectFuture::Sequential for operations that must complete in order, like storage updates.