Skuld.SerializableCoroutine (skuld v0.27.1)
View SourceHelpers for building coroutines with serializable effect logs.
new/2 constructs a Coroutine with EffectLogger installed innermost,
so every effect invocation across all handlers is captured in a
JSON-serializable log. The returned value is a plain %Coroutine.Pending{}
— run it, suspend it, resume it just like any other coroutine.
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.
For resume: deserialize the log, build a new computation with
EffectLogger.with_resume/4, install handlers, and wrap in a new
Coroutine.
Usage
coroutine =
SerializableCoroutine.new(my_comp, fn comp ->
comp
|> State.with_handler(0)
|> Throw.with_handler()
|> Yield.with_handler()
end)
case Coroutine.run(coroutine) do
%Coroutine.ExternalSuspended{value: yielded, env: env} = suspended ->
log = SerializableCoroutine.get_log(suspended)
json = SerializableCoroutine.serialize(log)
# persist json...
{:ok, log} = SerializableCoroutine.deserialize(json)
# build a new coroutine for resume:
resume_comp =
my_comp
|> EffectLogger.with_resume(log, user_input)
|> then(&handlers_fun.(&1))
Coroutine.run(Coroutine.new(resume_comp, Env.new()))
%Coroutine.Completed{result: result} ->
result
endEffectLogger placement
EffectLogger.with_logging() is installed innermost (right after
the computation, before handlers_fun), so its scope runs last and
wraps all subsequently installed handlers. This ensures every effect
invocation is captured.
Summary
Functions
Deserialize a log from JSON.
Extract the EffectLogger log from a suspended coroutine.
Build a Coroutine with EffectLogger installed innermost.
Serialize a log to JSON.
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())) :: Skuld.Coroutine.Pending.t()
Build a Coroutine with EffectLogger installed innermost.
handlers_fun receives the computation after EffectLogger is installed.
Install application-level handlers here (State, Throw, Yield, etc.).
Returns a plain %Coroutine.Pending{}.
Example
SerializableCoroutine.new(my_comp, fn comp ->
comp
|> State.with_handler(0)
|> Throw.with_handler()
end)
@spec serialize(Skuld.Effects.EffectLogger.Log.t()) :: String.t()
Serialize a log to JSON.
Returns a JSON string suitable for storage.