Skip to content

Store

Event stores, URL parsing, and migration. For the conceptual model see concepts/graph (graph as projection of the event log) and concepts/replay.

Stores

Bases: Protocol

Append-only per-run event log. CONTRACT v0.5 #2.

Volatile, list-backed event store. CONTRACT v0.5 #2.

The reference implementation of the EventStore protocol: append-only, id-addressed, iteration in append order. Everything lives in process memory and nothing survives the interpreter — exactly right for tests and ephemeral runs, and exactly wrong for anything that must be resumed, forked, or audited later; use SQLiteEventStore or PostgresEventStore for those.

Per-run view onto a SQLite-backed event log.

Direct construction expects an explicit path and run_id. For most cases prefer Runtime(graph, persist_to=...), which opens the store, mints a run_id if needed, and wires it onto the runtime — the v1.0.1 user-test surfaced that constructing SQLiteEventStore by hand is a low-frequency operator path, not the happy path.

fork_run(path, *, parent_run_id, new_run_id, at_event_id, label, created_at) classmethod

Copy events from parent_run_id up to and including at_event_id into new_run_id (CONTRACT v0.5 #11: copy rows, no row-sharing).

Returns the number of events copied.

Graph stores

The materialized graph projection (objects, relations, patches) lives behind a GraphStore, distinct from the durable EventStore above. See the Using the FalkorDB graph store guide.

Bases: ABC

Backend for the materialized graph projection.

Implementations store objects, relations, and patches keyed by id. put_* is an upsert (insert or overwrite the entity with the same id). get_* returns None when the id is unknown. remove_* is a no-op when the id is unknown (the projector already guards against double-removal, but tolerating it keeps backends simple).

put_object(obj) abstractmethod

Insert or overwrite obj keyed by obj.id.

get_object(object_id) abstractmethod

Return the object with object_id or None.

remove_object(object_id) abstractmethod

Drop the object with object_id if present.

all_objects() abstractmethod

Return every object. Order is unspecified.

put_relation(rel) abstractmethod

Insert or overwrite rel keyed by rel.id.

get_relation(relation_id) abstractmethod

Return the relation with relation_id or None.

remove_relation(relation_id) abstractmethod

Drop the relation with relation_id if present.

all_relations() abstractmethod

Return every relation. Order is unspecified.

put_patch(patch) abstractmethod

Insert or overwrite patch keyed by patch.id.

get_patch(patch_id) abstractmethod

Return the patch with patch_id or None.

all_patches() abstractmethod

Return every patch. Order is unspecified.

find_objects(type=None)

Return objects, optionally filtered to those whose type equals type. None means "every object". Type-equality only — the where predicate is applied by the caller, not here.

find_objects_in_types(types)

Return objects whose type is any of types (OR), preserving :meth:all_objects enumeration order. An empty types returns []. Like :meth:find_objects this is type-equality only — the where predicate stays with the caller. The default scans once; a backend MAY push a type IN [...] filter into the database, but MUST preserve the single-pass order so it matches this base class.

find_relations(source=None, target=None, type=None)

Return relations matching every provided filter (AND). A None filter is unconstrained; passing none returns every relation.

neighborhood(object_id, depth=1)

Undirected breadth-first walk from object_id out to depth edges. Returns (objects, relations) where objects are the reachable materialized objects (the start included; endpoints that are not objects are skipped) and relations are every relation traversed. Returns ([], []) if object_id is not an object.

match_chain(node_types, rels)

Enumerate every structural match of a linear node→rel→node chain.

node_types is one entry per node position (None = any type); rels is one (rel_type, direction) per hop, where direction is "right" ((a)-[]->(b)) or "left" ((a)<-[]-(b)) and rel_type None means any. len(rels) must be len(node_types) - 1.

Only the structural filters — node types, relation types, and directions — are applied here; node {prop: value} equality and WHERE are layered on by the caller. Semantics are homomorphic: a single object or relation may fill more than one position (matching the pattern matcher and FalkorDB, neither of which enforces node/relationship uniqueness). The default walks the chain depth-first via :meth:find_objects / :meth:find_relations; a backend MAY override to resolve the whole chain in one query, but MUST return exactly what this default would (order aside).

clear()

Drop all objects, relations, and patches. Default: per-kind removal.

remove_patch(patch_id)

Drop the patch with patch_id if present.

Not part of the projector's hot path (patches are never deleted by events — only superseded), but :meth:clear needs it. Subclasses that store patches must override.

close()

Release any backend resources. Default: no-op.

Bases: GraphStore

Volatile, dict-backed GraphStore. The default backend.

Stores the live :class:~activegraph.core.graph.Object / :class:~activegraph.core.graph.Relation / :class:~activegraph.core.patch.Patch instances by id and returns them directly (no copy), so the projector's in-place mutations (obj.data.update(...), obj.version += 1) behave exactly as they did before the GraphStore seam existed.

Bases: GraphStore

A :class:GraphStore backed by a FalkorDB graph.

Parameters

path: Filesystem path for the embedded falkordblite database. Used only in embedded mode (no connection info given). When None, an ephemeral embedded instance is created. graph_name: Name of the FalkorDB graph to use within the database/server. Defaults to "activegraph". Ignored when graph is supplied. graph: An existing FalkorDB graph handle (anything exposing query / ro_query). When provided, all other connection parameters are ignored and this store does not own the connection's lifecycle. url: FalkorDB server URL (e.g. "falkor://host:6379"). Triggers server mode via the falkordb client. host, port, username, password: FalkorDB server connection settings. Supplying host triggers server mode. port defaults to 6379.

Connection resolution order: explicit graph → explicit url / hostFALKORDB_URL / FALKORDB_HOST env vars → embedded falkordblite.

Install the server client with pip install 'activegraph[falkordb]' or the embedded engine with pip install 'activegraph[falkordb-embedded]'.

URL parsing + helpers

Open a store for run_id at url. Returns an EventStore.

This is the single entry point the runtime and CLI use to open a store from a URL. Drivers are imported lazily so the Postgres dependency stays optional.

Parse a store URL, or raise InvalidStoreURL with a helpful message.

Migration

Copy every run (or a subset) from source_url into dest_url.

Parameters:

Name Type Description Default
source_url str

e.g. sqlite:///dev.db

required
dest_url str

e.g. postgres://localhost/prod

required
only_run_ids Optional[list[str]]

if given, migrate only these runs.

None
on_progress Optional[Callable[[MigrationRunReport], None]]

called after each run finishes (success or failure) with the MigrationRunReport for that run.

None
skip_corrupted bool

if True, rows whose payload fails JSON decode are skipped (not migrated, not failing the run). The skipped event ids appear in the per-run report's skipped_events. The resulting destination run is partial — the operator is on notice.

False

Returns:

Type Description
MigrationReport

A MigrationReport. The overall operation is considered

MigrationReport

successful iff every run's status is "ok" or "skipped".