Run the projection worker
Refresh claim-derived projections asynchronously.
When a session ends, its active claims are queued for derived lexical, vector,
and graph projection refresh (Tier 4). PromotionWorker drains that work off the
response path. It never changes claim authority, evidence, or lifecycle.
Prerequisites
- An
embedderfor vector projection; lexical and graph projections work without one. pool.max_size >= 2for parallel application and worker activity.
Steps
Construct a worker
from pgmem import PromotionWorker
worker = PromotionWorker(mem) # optionally lease_seconds=300Run it as a background loop (production)
run polls the queue and processes jobs until you signal stop. Run it as a
long-lived task alongside your agent.
import asyncio
stop = asyncio.Event()
task = asyncio.create_task(worker.run(poll_interval=5.0, stop=stop, use_listen=False))
# ... later, to shut down:
stop.set()
await taskOr drain on demand (tests, batch, scripts)
await worker.run_once() # claim + process the next job (or None)
n = await worker.process_pending() # drain up to max_jobs (default 1000)Recover interrupted jobs on startup
A worker that crashed mid-job leaves a job leased. recover requeues only jobs
whose lease has expired, so a fresh worker can pick them up without stealing live
ones.
requeued = await worker.recover()Expire elapsed retention deadlines
retention_until is enforced on reads immediately. Run ClaimRetentionWorker
from the same scheduler or worker service to transition elapsed claims to
expired, remove their projections, and queue affected narrative rebuilds:
from pgmem import ClaimRetentionWorker
retention = ClaimRetentionWorker(mem)
await retention.drain() # or await retention.serve(poll_interval=60)Verify
After session.end() and a worker pass, the active claim has a graph projection:
await session.end()
await worker.run_once()
count = await mem.driver.pool.fetchval(
"SELECT count(*) FROM pgmem.memory_claim_graph_edges WHERE claim_uuid = $1",
claim.uuid,
)
print(count)Gotchas
Claim formation is policy-governed; projection is not a second authority gate. Workers derive indexes only from active claims and never turn a provisional claim into an accepted one.
- Multiple workers are safe to run concurrently — jobs are claimed with
FOR UPDATE SKIP LOCKED. - Embedding can be remote and must run off the response path.
Related
- Trust & memory formation — claim lifecycle
- The five-tier model — Tier 3 → derived Tier 4
- PgMem —
build_communitiesand the graph surface