The invocation context handed to Tasklet.run/3. use Flezha.SDK.Tasklet
imports the functions below, so a tasklet writes emit(ctx, value) and
complete(ctx, result); apply/3 is not imported, since it would shadow
Kernel.apply/3, and a use tasklet never calls it: its defchange
recorders do.
emit/2 and emit/3 (with key: and metadata:) accumulate outputs for
this invocation; apply/3 folds a change into the state through the
tasklet's apply_change/2 and records it for the Cell's record stream, the
only recorded mutation path; now/1 is the declared clock's value,
evaluated once by the core for this input, and the scheduled timestamp
inside a firing; cell_key/1 is the owning Cell's key (or nil for
a Single Cell). Emits, changes, timer operations and the completion are held
in the invoking worker's dictionary under a per-invocation ref and are taken
only when run/3 returns {:ok, _}: a failing invocation discards them all.
Reserved flz.-prefixed metadata keys are refused.
A key: rides an emit only where the node's output is declared keyed/1, and a
keyless emit there from a Cell with no key of its own is refused at the call.
timer_after/2 and timer_at_event_time/2 record a registration and answer
{:ok, at}, the absolute timestamp cancel_timer/3 takes beside the kind;
a cancel answers :ok. flz_core judges the item's timer ops when it settles: past the
tasklet's max_timers_per_cell/0, or an event-time timer under another
clock, the item fails, not retried. Inside a compensate/3 hook the three
timer calls answer runtime.timers_unavailable and arm nothing.
spawn_steps/4, effect/4 and part/2 reach flz_core from the live
activation, and only from the worker running the invocation: the same call
from another process is refused.
Summary
Functions
Fold change into state with the tasklet's apply_change/2 and record
it, so the Cell ships it after the invocation succeeds. The returned state
is what run/3 returns in its {:ok, _}.
Cancel the kind timer (:processing_time or :event_time) its registration
answered at for; one not pending changes nothing.
The owning Cell's key, or nil for a Single Cell.
Close the staged checkpoint interval at the end of this invocation. A no-op on a class that did not declare checkpoint granularity.
End the instance this tasklet runs in, with result as the result its
completion reports. result is encoded as spawn_steps/4 encodes its
payload; nil carries no result.
Run fun, a call to anything outside the instance (a model, a tool, a
service), and keep its result: when this invocation runs again (a crash
re-run, a replay, a wake, a move), the call answers the kept result and
fun does not run. The result is kept, synced on the controller, before
this returns; a crash between fun finishing and that point runs fun
again, so give the outside service stable_id/1 as an idempotency key where
it takes one.
Emit a value on the tasklet's outgoing channel.
Emit a value with options: key:, the output's natural key, only on an
output declared keyed/1; metadata:, a map whose reserved flz.-prefixed
keys are refused. Any other option raises ArgumentError.
The declared clock's value for this input; the scheduled timestamp inside a firing.
Send value as a part: a preview of this invocation's output on its
channel, which leaves now rather than when run/3 returns, encoded as an
emit of value would be. It never waits: a part the wire cannot take at once
is dropped, and an invocation of a replayed input sends none.
Whether this invocation replays an input the Cell already ran.
Request spawn-or-deliver of a steps instance of factory_id in this
runner's namespace, with payload as its first input: bytes as they are,
anything else as JSON, and a term with no JSON form raises. Answers a
Flezha.SDK.Spawn handle without waiting, read with
Flezha.SDK.Spawn.await/2 or Flezha.SDK.Spawn.try_result/1 inside this
invocation, or not at all.
A replay-stable 128-bit id, 32 lowercase hex digits: FNV-1a-128 over the Cell's identity, the change seq this invocation started at and a per-invocation ordinal. The same invocation on a replay derives the same ids in the same order, which is what makes an effect idempotent.
Register a processing-time timer delay_ms after now/1; {:ok, at}, the cancellation handle.
Register an event-time timer at at; {:ok, at}.
Types
An emit/3 option.
Functions
Fold change into state with the tasklet's apply_change/2 and record
it, so the Cell ships it after the invocation succeeds. The returned state
is what run/3 returns in its {:ok, _}.
@spec cancel_timer(t(), Flezha.SDK.TimerFiring.kind(), non_neg_integer()) :: :ok | {:error, Flezha.SDK.Error.t()}
Cancel the kind timer (:processing_time or :event_time) its registration
answered at for; one not pending changes nothing.
The owning Cell's key, or nil for a Single Cell.
@spec checkpoint(t()) :: :ok
Close the staged checkpoint interval at the end of this invocation. A no-op on a class that did not declare checkpoint granularity.
End the instance this tasklet runs in, with result as the result its
completion reports. result is encoded as spawn_steps/4 encodes its
payload; nil carries no result.
In a class that runs in steps the rest of the iteration still runs and commits; once that commit is durable the instance ends instead of waiting for its next input. In a flow class the instance runs what its Cells already hold to its outputs, then ends; a later call before that replaces the result.
@spec effect( t(), String.t(), (-> term()), {(term() -> binary()), (binary() -> term())} | nil ) :: {:ok, term()} | {:error, Flezha.SDK.Error.t() | {:non_retryable, Flezha.SDK.Error.t()}}
Run fun, a call to anything outside the instance (a model, a tool, a
service), and keep its result: when this invocation runs again (a crash
re-run, a replay, a wake, a move), the call answers the kept result and
fun does not run. The result is kept, synced on the controller, before
this returns; a crash between fun finishing and that point runs fun
again, so give the outside service stable_id/1 as an idempotency key where
it takes one.
name names the call: a non-empty string of at most 255 bytes, counted per
invocation. One call runs at a time; a concurrent one is refused. The result
is encoded as spawn_steps/4 encodes its payload and read back as JSON, else
as the binary; codec, an {encode, decode} pair of one-argument
functions, replaces both.
An invocation that took no input-log offset runs fun each time and keeps
nothing. A raise in fun propagates and nothing is kept. Answers
{:ok, result}, or {:error, reason} for run/3 to return as it is:
{:non_retryable, error} for effect.bad_name, effect.nested,
effect.outside_invocation and effect.too_large, and the retryable
effect.not_recorded error.
@spec emit(t(), term()) :: :ok | {:error, Flezha.SDK.Error.t()}
Emit a value on the tasklet's outgoing channel.
@spec emit(t(), term(), [emit_option()]) :: :ok | {:error, Flezha.SDK.Error.t()}
Emit a value with options: key:, the output's natural key, only on an
output declared keyed/1; metadata:, a map whose reserved flz.-prefixed
keys are refused. Any other option raises ArgumentError.
The declared clock's value for this input; the scheduled timestamp inside a firing.
@spec part(t(), term()) :: :ok | {:error, Flezha.SDK.Error.t()}
Send value as a part: a preview of this invocation's output on its
channel, which leaves now rather than when run/3 returns, encoded as an
emit of value would be. It never waits: a part the wire cannot take at once
is dropped, and an invocation of a replayed input sends none.
:ok, or {:error, %Error{}}: part.no_output when the node's channel does
not end in an output (a call end is not one), part.outside_invocation
through a ctx whose invocation has returned or from another process.
Whether this invocation replays an input the Cell already ran.
@spec spawn_steps(t(), String.t(), term(), [Flezha.SDK.Spawn.option()]) :: Flezha.SDK.Spawn.t()
Request spawn-or-deliver of a steps instance of factory_id in this
runner's namespace, with payload as its first input: bytes as they are,
anything else as JSON, and a term with no JSON form raises. Answers a
Flezha.SDK.Spawn handle without waiting, read with
Flezha.SDK.Spawn.await/2 or Flezha.SDK.Spawn.try_result/1 inside this
invocation, or not at all.
With id: the instance starts under that id when it is free; while it runs,
if_running: :deliver (the default) hands it payload as one more input and
if_running: :error resolves already_running. if_running: without id:
resolves the core's spawn.if_running_without_id at the call and sends
nothing.
Without id: the controller generates one, and every call starts a new
instance: a call reissued after a lost or timed-out answer starts a second
one, and a replayed invocation resolves skipped_on_replay. A crash re-run
of an input the Cell had not durably consumed asks again under the same
identity, and the controller answers the instance the first ask started.
A replay-stable 128-bit id, 32 lowercase hex digits: FNV-1a-128 over the Cell's identity, the change seq this invocation started at and a per-invocation ordinal. The same invocation on a replay derives the same ids in the same order, which is what makes an effect idempotent.
@spec timer_after(t(), integer()) :: {:ok, non_neg_integer()} | {:error, Flezha.SDK.Error.t()}
Register a processing-time timer delay_ms after now/1; {:ok, at}, the cancellation handle.
@spec timer_at_event_time(t(), non_neg_integer()) :: {:ok, non_neg_integer()} | {:error, Flezha.SDK.Error.t()}
Register an event-time timer at at; {:ok, at}.