Jido.Persist
(Jido v2.0.0-rc.4)
View Source
Coordinates hibernate/thaw operations for agents with thread support.
This module is the invariant enforcer - it ensures:
- Journal is flushed before checkpoint
- Checkpoint never contains full Thread, only a pointer
- Thread is rehydrated on thaw
API
The primary API accepts a storage configuration tuple:
Jido.Persist.hibernate({adapter, opts}, agent)
Jido.Persist.thaw({adapter, opts}, agent_module, key)Or a Jido instance with embedded storage config:
Jido.Persist.hibernate(jido_instance, agent)
Jido.Persist.thaw(jido_instance, agent_module, key)hibernate/2 Flow
- Extract thread from
agent.state[:__thread__] - If thread exists with entries, flush journal via
adapter.append_thread/3 - Call
agent_module.checkpoint/2if implemented, else use default - Enforce invariant: Remove
:__thread__from state, store only thread pointer - Call
adapter.put_checkpoint/3
thaw/3 Flow
- Call
adapter.get_checkpoint/2 - If
:not_found, return:not_found - Call
agent_module.restore/2if implemented, else use default - If checkpoint has thread pointer, load and attach thread
- Verify loaded thread.rev matches checkpoint pointer rev
Agent Callbacks
Agents may optionally implement:
checkpoint(agent, ctx)- Returns{:ok, checkpoint_data}for custom serializationrestore(checkpoint_data, ctx)- Returns{:ok, agent}for custom deserialization
If not implemented, default serialization is used.
Examples
# Using storage config tuple
storage = {Jido.Storage.ETS, table: :my_storage}
# Hibernate an agent
:ok = Jido.Persist.hibernate(storage, agent)
# Thaw an agent
case Jido.Persist.thaw(storage, MyAgent, "agent-123") do
{:ok, agent} -> agent
:not_found -> start_fresh()
{:error, :missing_thread} -> handle_missing_thread()
{:error, :thread_mismatch} -> handle_mismatch()
end
Summary
Functions
Persists an agent to storage, flushing any pending thread entries first.
Restores an agent from storage, rehydrating thread if present.
Types
@type agent() :: struct()
@type agent_module() :: module()
@type checkpoint() :: %{ version: pos_integer(), agent_module: agent_module(), id: term(), state: map(), thread: thread_pointer() | nil }
@type checkpoint_key() :: {agent_module(), term()}
@type key() :: term()
@type thread_pointer() :: %{id: String.t(), rev: non_neg_integer()}
Functions
@spec hibernate(storage_config() | module() | struct(), agent()) :: :ok | {:error, term()}
Persists an agent to storage, flushing any pending thread entries first.
Accepts either a {adapter, opts} tuple or a struct with :storage field.
Examples
storage = {Jido.Storage.ETS, table: :agents}
:ok = Jido.Persist.hibernate(storage, my_agent)Returns
:ok- Successfully hibernated{:error, reason}- Failed to hibernate
@spec thaw(storage_config() | module() | struct(), agent_module(), key()) :: {:ok, agent()} | :not_found | {:error, term()}
Restores an agent from storage, rehydrating thread if present.
Accepts either a {adapter, opts} tuple or a struct with :storage field.
Examples
storage = {Jido.Storage.ETS, table: :agents}
{:ok, agent} = Jido.Persist.thaw(storage, MyAgent, "agent-123")Returns
{:ok, agent}- Successfully thawed:not_found- No checkpoint exists for this key{:error, :missing_thread}- Checkpoint references thread that doesn't exist{:error, :thread_mismatch}- Loaded thread.rev != checkpoint thread.rev{:error, reason}- Other errors