Skuld.SerializableCoroutine (skuld v0.30.0)
View SourceHelpers for building coroutines with serializable effect logs.
new/2 constructs a struct with EffectLogger installed innermost,
so every effect invocation across all handlers is captured in a
JSON-serializable log.
When the coroutine suspends, the log is accessible via get_log/1
(from the env in %Coroutine.ExternalSuspended{}). serialize/1 and
deserialize/1 convert the log to/from JSON.
run handles all states — fresh start, live resume, and cold resume
from serialised state.
Usage
sc = SerializableCoroutine.new(wizard, fn comp ->
comp |> State.with_handler(0) |> Yield.with_handler() |> Throw.with_handler()
end)
# Run fresh — suspends at first yield
suspended = SerializableCoroutine.run(sc)
# Serialize and persist
json = SerializableCoroutine.serialize(SerializableCoroutine.get_log(suspended))
# Later: cold resume from serialised state
SerializableCoroutine.run(json, sc, "Alice")
# Or resume a live suspended coroutine directly
SerializableCoroutine.run(suspended, "Alice")
Summary
Functions
Deserialize a log from JSON.
Extract the EffectLogger log from a suspended coroutine.
Build a serialisable coroutine.
Run a serialisable coroutine.
Serialize a log to JSON.
Types
@type t() :: %Skuld.SerializableCoroutine{ comp: Skuld.Comp.Types.computation(), handlers_fun: (Skuld.Comp.Types.computation() -> Skuld.Comp.Types.computation()) }
A serialisable coroutine capturing the computation and handler stack.
Functions
@spec deserialize(String.t()) :: {:ok, Skuld.Effects.EffectLogger.Log.t()} | {:error, Jason.DecodeError.t()}
Deserialize a log from JSON.
Returns {:ok, log} on success.
@spec get_log(Skuld.Coroutine.ExternalSuspended.t()) :: Skuld.Effects.EffectLogger.Log.t() | nil
Extract the EffectLogger log from a suspended coroutine.
The log is stored in the environment at suspension time.
Returns nil if no log is found.
@spec new(Skuld.Comp.Types.computation(), (Skuld.Comp.Types.computation() -> Skuld.Comp.Types.computation())) :: t()
Build a serialisable coroutine.
handlers_fun receives the computation after EffectLogger is installed.
Install application-level handlers here (State, Throw, Yield, etc.).
Example
SerializableCoroutine.new(my_comp, fn comp ->
comp |> State.with_handler(0) |> Throw.with_handler()
end)
@spec run(t()) :: Skuld.Coroutine.t()
Run a serialisable coroutine.
Clauses dispatch on the input type:
t()— start fresh, returns a Coroutine sum-typet(),value— resume a live suspended fiber (delegates toCoroutine.run)%Log{},t(),value— cold resume from a deserialised logbinary,t(),value— deserialise JSON to a log, then cold resumeCoroutine.t(),value— resume a live Coroutine fiber directly
Examples
sc = SerializableCoroutine.new(wizard, handlers)
# Start fresh
suspended = SerializableCoroutine.run(sc)
# Resume a live suspended fiber
SerializableCoroutine.run(suspended, "Alice")
# Cold resume from a deserialised log
SerializableCoroutine.run(log, sc, "Alice")
# Cold resume from serialised JSON
SerializableCoroutine.run(json, sc, "Alice")
@spec run(Skuld.Effects.EffectLogger.Log.t(), t(), term()) :: Skuld.Coroutine.t()
@spec run(String.t(), t(), term()) :: Skuld.Coroutine.t()
@spec serialize(Skuld.Effects.EffectLogger.Log.t()) :: String.t()
Serialize a log to JSON.
Returns a JSON string suitable for storage.