Skip to main content
The durable park index a driver keeps for the runs it parks on an async ask. When a driver parks a run, the platform keeps only the interaction id; the driver reverses it to its own run through this index. One consumer namespace holds, on one Redis:
  • an ENTRY per resume key (an interaction id, or any key the consumer resumes by), carrying the consumer’s own opaque rebuild payload;
  • a BARRIER per parked super-step (a thread’s set of asks resolved together): the consumer’s opaque expected map, keyed by member id, the answers buffered so far, and any opaque consumer fields;
  • a DRIVE LEASE per super-step, so exactly one worker drives a completed barrier, with a heartbeat and a token-checked release;
  • a RESOLUTION RECORD per resolved super-step and a TOMBSTONE in place of every member entry, so a lapped redelivery replays what the first drive returned;
  • a RUN-RESOLUTION INDEX per thread (every resolved super-step and its members), so a kill can reach every stored outcome of a run;
  • a LIVE SET per thread (its super-steps whose barrier is live), so a checkpoint sweep can tell a parked thread from an abandoned one.
The module imports no Redis client at import time: the client is reached lazily, so a consumer whose import graph excludes Redis may import this module. Every Redis error propagates.

BARRIER_TTL_MARGIN_SECONDS

tai42_kit.interactions.park_index.BARRIER_TTL_MARGIN_SECONDS

DRIVE_LEASE_HEARTBEAT_SECONDS

tai42_kit.interactions.park_index.DRIVE_LEASE_HEARTBEAT_SECONDS

DRIVE_LEASE_SECONDS

tai42_kit.interactions.park_index.DRIVE_LEASE_SECONDS

ENTRY_TTL_FLOOR_SECONDS

tai42_kit.interactions.park_index.ENTRY_TTL_FLOOR_SECONDS

RESOLVED_FIELD

tai42_kit.interactions.park_index.RESOLVED_FIELD

Barrier

tai42_kit.interactions._park_types.Barrier
A super-step barrier: the consumer’s expected map, the answers buffered so far, its own fields. Attributes

BarrierNotFoundError

tai42_kit.interactions._park_types.BarrierNotFoundError
The super-step barrier an answer converges on is gone (expired or never written). Attributes

BufferResult

tai42_kit.interactions._park_types.BufferResult
Progress after an answer was buffered: answered members, all members, the still-open members in order. Attributes

DriveInProgressError

tai42_kit.interactions._park_types.DriveInProgressError
Another worker holds the super-step’s drive lease. Raised (never a benign return) so the platform keeps the caller’s durable retry ticket and redelivers until the live drive completes or its lease expires. Attributes

DriveLease

tai42_kit.interactions.park_index.DriveLease
A super-step’s drive lease: SET NX EX to win it, a heartbeat while held, a token-checked release. Win it by entering (async with) or acquire; leave it by exiting or close, which stops the heartbeat and releases it unless ParkIndex.finalize consumed it. Attributes

Members

acquire

tai42_kit.interactions.park_index.DriveLease.acquire
Win the lease and start its heartbeat.

holds

tai42_kit.interactions.park_index.DriveLease.holds
Whether this lease’s token still holds the super-step right now.

release

tai42_kit.interactions.park_index.DriveLease.release
Drop the lease if this token still holds it (a reclaimer’s lease is never dropped).

close

tai42_kit.interactions.park_index.DriveLease.close
Stop the heartbeat and release the lease once; a consumed lease is left as finalize left it. A cancel of the calling task delivered while the heartbeat stops propagates, after the release.

mark_consumed

tai42_kit.interactions.park_index.DriveLease.mark_consumed
Record that a finalize dropped the lease key; stops the heartbeat so no renew reports it lost.

LeaseLostError

tai42_kit.interactions._park_types.LeaseLostError
The caller no longer holds the drive lease its write is guarded by; another writer owns the super-step. Attributes

ParkIndex

tai42_kit.interactions.park_index.ParkIndex
One consumer’s park index under its own key namespace on its own Redis. Attributes

Members

entry_key

tai42_kit.interactions.park_index.ParkIndex.entry_key
The key of the entry stored for entry_id. Parameters

barrier_key

tai42_kit.interactions.park_index.ParkIndex.barrier_key
The key of a super-step’s barrier hash. Parameters

lease_key

tai42_kit.interactions.park_index.ParkIndex.lease_key
The key of a super-step’s drive lease. Parameters

resolution_key

tai42_kit.interactions.park_index.ParkIndex.resolution_key
The key of a resolved super-step’s resolution record. Parameters

run_resolutions_key

tai42_kit.interactions.park_index.ParkIndex.run_resolutions_key
The key of a thread’s run-resolution index. Parameters

live_set_key

tai42_kit.interactions.park_index.ParkIndex.live_set_key
The key of a thread’s set of super-steps whose barrier is live. Parameters

persist

tai42_kit.interactions.park_index.ParkIndex.persist
Write a parked super-step’s entries, its barrier and its live-set membership, all or nothing. Each entry is written whole under its own TTL; the barrier holds expected (keyed by member id) and barrier_fields; the thread’s live set lasts as long as its longest-lived barrier. Parameters

threads_with_live_barriers

tai42_kit.interactions.park_index.ParkIndex.threads_with_live_barriers
The subset of thread_ids with at least one live barrier. Parameters

read_entry

tai42_kit.interactions.park_index.ParkIndex.read_entry
The entry or tombstone stored for entry_id, or None when there is none. Parameters

tombstone_kind

tai42_kit.interactions.park_index.ParkIndex.tombstone_kind
Whether a read entry is a live entry, a resolved tombstone, or a detached tombstone. Parameters

tombstone_coordinates

tai42_kit.interactions.park_index.ParkIndex.tombstone_coordinates
The (thread_id, superstep) a resolved tombstone points at. Parameters

read_tombstone_resolution

tai42_kit.interactions.park_index.ParkIndex.read_tombstone_resolution
The record a tombstone resolves to: the stored record of a resolved one, None for a detached one. Parameters

read_barrier

tai42_kit.interactions.park_index.ParkIndex.read_barrier
A super-step’s barrier, or None when it is gone; buffered answers are decoded. Parameters

set_barrier_fields

tai42_kit.interactions.park_index.ParkIndex.set_barrier_fields
Write consumer fields onto a live barrier; False (nothing written) when the barrier is gone. Parameters

buffer

tai42_kit.interactions.park_index.ParkIndex.buffer
Buffer one member’s answer into its barrier, idempotently, and report progress. A redelivered answer for a member already answered keeps the first one. Parameters

claim

tai42_kit.interactions.park_index.ParkIndex.claim
A drive lease on a super-step, won by entering it (async with or DriveLease.acquire). Parameters

finalize

tai42_kit.interactions.park_index.ParkIndex.finalize
Resolve a super-step under lease: tombstone its members, store its record, drop its barrier and lease. One guarded step: it lands only while lease still holds the super-step, and it also records the super-step in its thread’s run-resolution index and leaves the thread’s live set. On success the lease is consumed and its heartbeat stopped. Parameters

read_resolution

tai42_kit.interactions.park_index.ParkIndex.read_resolution
A resolved super-step’s record, or None when it has none. Parameters

run_resolutions

tai42_kit.interactions.park_index.ParkIndex.run_resolutions
Every resolved super-step of a thread with its members, {} when none. Parameters

drop_run_resolutions

tai42_kit.interactions.park_index.ParkIndex.drop_run_resolutions
Drop every resolved super-step of a thread but keep (member tombstones and record), then its index. Parameters

drop_resolution

tai42_kit.interactions.park_index.ParkIndex.drop_resolution
Drop one resolved super-step: its record, its members’ tombstones (and member_ids), its index member. Parameters

detach

tai42_kit.interactions.park_index.ParkIndex.detach
Tombstone keys that were claimed but never parked on, never overwriting an existing key. Parameters

extend_horizon

tai42_kit.interactions.park_index.ParkIndex.extend_horizon
Grow a live entry’s, its barrier’s and its live set’s TTLs to outlast expiry_at; never shrink one. Returns False when no live entry backs entry_id (absent or a tombstone). Parameters

ParkIndexCorruptError

tai42_kit.interactions._park_types.ParkIndexCorruptError
A stored park index value does not have the shape the index writes.

ParkIndexError

tai42_kit.interactions._park_types.ParkIndexError
Base of every park index failure.

ParkValueCodecError

tai42_kit.interactions._park_types.ParkValueCodecError
A value cannot be stored in, or read back from, the park index.

Resolution

tai42_kit.interactions._park_types.Resolution

ResolutionMissingError

tai42_kit.interactions._park_types.ResolutionMissingError
A resolved tombstone points at a resolution record that is gone. Attributes

ResolutionRecord

tai42_kit.interactions._park_types.ResolutionRecord
What a resolved super-step stored: how it resolved and the value a redelivery replays. Attributes

SuperstepAlreadyResolvedError

tai42_kit.interactions._park_types.SuperstepAlreadyResolvedError
The barrier was finalized while an answer was being buffered into it; the super-step already resolved. Attributes

TombstoneKind

tai42_kit.interactions.park_index.TombstoneKind

barrier_ttl_seconds

tai42_kit.interactions.park_index.barrier_ttl_seconds
A barrier’s TTL: the entry floor, extended to outlast the LATEST deadline it coordinates plus the margin. Parameters

decode_value

tai42_kit.interactions._park_types.decode_value
Rebuild a value from its tagged mapping (encode_value’s inverse). Parameters

encode_value

tai42_kit.interactions._park_types.encode_value
Encode a resolution value or a buffered answer as a tagged JSON mapping. A contract outcome type keeps its type across the store; any other pydantic model is refused, and a plain value must be JSON-serializable. Parameters

entry_ttl_seconds

tai42_kit.interactions.park_index.entry_ttl_seconds
An entry’s TTL: the floor, extended to outlast its ask’s deadline plus the margin. Parameters

resolution_ttl_seconds

tai42_kit.interactions.park_index.resolution_ttl_seconds
The TTL of a resolution record and its tombstones: twice the platform’s redelivery horizon. They must outlive the last redelivery the reaper can fire, plus reaper-cycle and clock-skew margin, and no longer (they hold a run’s outcome).

superstep_id

tai42_kit.interactions.park_index.superstep_id
A deterministic super-step id: a sha256 over the sorted member ids, insensitive to their order. Parameters Park adoption and the chained-call notices: which park a run records for a returned sentinel, and what it fires. A park belongs to exactly ONE resume continuation — the one bound when it was raised — and carries that owner BOTH on its sentinel and on its wire-form marker. assert_park_adoptable is the guard every seam that turns a park into the CALLER’s own suspended state applies: the object seams that adopt a returned sentinel, and the CLAIM point where a driver records resume state against a marker read off a serialized tool result. So a nested run’s park is never adopted by its caller (which would then wait for a resume fired only at the nested run). The owner is the continuation NAME, not a per-run token, because that is the whole of what the platform dispatches: the name is what the interaction stores and what a later answer invokes, so a scoped owner would have to be unscoped again before dispatch and would fork the meaning of the resume binding. Name equality alone is not what makes the guard sound — two runs of the same driver share a name — the None rule is: a park crossing a nested RUN’s face carries no owner at all, so a same-named sibling is refused on that, never on a name comparison happening to differ. Refusing is not the only answer to a park this caller does not own. resolve_park_adoption is the OBJECT seams’ form of the guard, and it answers adopt-your-own or CHAIN: a nested dispatch a CHAIN routing (ChainedResume) was bound around parks on the nested CALL — a key of its own, owned by its own resume continuation — while the nested run keeps its park and its resume, and its terminal re-enters the caller through the routing’s delivery tool. A dispatch nothing chained still gets the loud refusal. The CLAIM point cannot chain: a park reaching it as content belongs to no dispatch it could attribute the call to, so there it is adopt-or-refuse. Every driver builds the chain fires here too — repark_notice when a chained run re-parks, terminal_chain_notice at its terminal — so each payload has one shape.

assert_park_adoptable

tai42_kit.interactions.park_adoption.assert_park_adoptable
Guard the seam where a caller ADOPTS a park as its OWN. Applies to a returned sentinel or the wire-form marker, where the caller records resume state of its own against that interaction. resume_owner is the park’s SuspendedInteraction.resume_owner, and the guard’s role is a NESTING DISCRIMINATOR, not an authenticity token: it separates a park a run raised UNDER ITS OWN resume binding (adoptable) from one that crossed a NESTED run’s face on the way up (not — that nested run is resumed on its own path, so adopting it would wait for a resume fired elsewhere and hang forever). A park a run raises for itself carries the continuation it was raised under; a park crossing a nested RUN’s face carries no owner at all. So the guard is sound on the None rule, not on name equality: a same-named sibling run is refused because its park reaches here ownerless, never because two names happened to differ. None is never adoptable, by ANY caller: it is the signal a park crossed a nested run’s face (or is content shaped to look like a park), neither of which this caller may turn into its own suspended state. An unbound caller is refused too — it has no continuation the platform could fire, so a park it claimed could only hang. A BLANK owner reads as no owner: it names no registered tool the platform could dispatch. This name check does NOT authenticate the marker against any store — the resume owner is a public continuation name, so a well-formed marker naming the bound continuation is treated as adoptable here. Structural validation of the marker shape lives in read_suspended_interaction_marker; store-authoritative existence is a separate concern the claim seams that hold a store handle apply. Raises NestedParkOwnershipError BEFORE any state of the caller’s own is recorded, so the owning run’s park stays untouched and resumable on its own path. A seam holding the sentinel a nested CALL returned applies resolve_park_adoption instead, which answers this same question but can also CHAIN the call rather than refuse it. Parameters

attach_chained_park

tai42_kit.interactions.park_adoption.attach_chained_park
Mark a claimed chained key as ATTACHED so the ledger drops it. The driver recorded a park on it, so it is no longer a dead chain. A no-op when no chained_park_claims ledger is open, or when the key was never claimed inside it. Parameters

chained_park_claims

tai42_kit.interactions.park_adoption.chained_park_claims
Bind the per-drive ledger of chained keys resolve_park_adoption CLAIMED, yield the set. A driver opens one around each drive so it can tell, when the drive stops, which chained calls it actually parked on: it drops each key it persists, and whatever REMAINS is a claim the drive never turned into a park (the run errored, or moved on without parking). Those are dead chains — the nested run will still fire its terminal at them — so the driver detaches them rather than leaving the fire to hunt a park that will never exist. The yielded set is mutated in place, so a claim recorded inside a task the drive spawns (every nested dispatch runs in a child context) is visible to the opener. claims lets a caller pass an EXISTING set to re-bind rather than a fresh one. A driver that binds per drive-step — the resume binding cannot span a generator’s yields, so it is re-entered around each __anext__ — owns one accumulating set for the whole drive and re-binds it here each step, so a claim recorded in an early step survives to the reconcile at the end. Omit it (the default) to open a fresh ledger for the whole drive at once. Parameters

is_chained_park_key

tai42_kit.interactions.park_adoption.is_chained_park_key
Whether key names a chained CALL rather than a platform interaction. The discriminator a driver indexing both key kinds reads before applying any policy that only makes sense for one of them (a chained key has no interaction, so nothing expires it and no answer is ever delivered against it directly). Parameters

new_chained_park_key

tai42_kit.interactions.park_adoption.new_chained_park_key
Mint a fresh chained resume key for ONE nested dispatch. Namespaced and unique per call, so two nested calls never converge on one key.

repark_notice

tai42_kit.interactions.park_adoption.repark_notice
The (tool, payload) fired when a park is raised under a bound chain routing. Returns None when no chain routing is bound around the current dispatch. A chained caller’s own suspension horizon is INHERITED from the nested run’s current ask, so when that run re-parks on a new ask the caller’s horizon must move with it. The notice is that signal: the routing’s delivery_tool paired with {CHAINED_PARK_TOKEN_KEY: routing.chain_key, "expiry_at": <iso>, "status": PARK_COMPLETION_REPARKED} — the one non-terminal status, carrying the new deadline in place of a result and the chain key the delivery tool reverses back to the caller’s park. It resolves nothing; the completion still fires later under a terminal status. Only a bound chain routing is notified, so no other delivery tool ever sees this fire. Parameters

resolve_park_adoption

tai42_kit.interactions.park_adoption.resolve_park_adoption
The park THIS run records for a returned park sentinel — ADOPT-your-own, or CHAIN. Returned as the (key, resume_owner) its own park is keyed and owned by. The OBJECT seams’ form of assert_park_adoptable, for a seam holding the sentinel a nested call returned. Three outcomes, in this order:
  • the park is adoptable here (raised under the continuation bound HERE) — it is this run’s own park, returned unchanged, and the platform resumes it directly;
  • otherwise, if this dispatch was CHAINED (a chain routing was bound around it, get_chained_resume), the run parks on the chained resume KEY instead, owned by this run’s OWN resume continuation — because that park is genuinely this run’s: it waits on the CALL, while the nested run keeps its own park and its own resume and re-enters here through the chain’s delivery tool when it terminates. The key is recorded in the open chained_park_claims ledger, so a drive that never turns the claim into a park can detach it;
  • otherwise NestedParkOwnershipError, exactly as assert_park_adoptable raises it: waiting on a foreign park with nothing chained would leave this run suspended behind a resume fired only at the nested run.
Never returns a foreign interaction id, and never returns a key owned by anything but the continuation bound here — so the claim point downstream reaches the same verdict. Parameters

terminal_chain_notice

tai42_kit.interactions.park_adoption.terminal_chain_notice
The (delivery tool, payload) a run’s terminal fires along its captured chain routing. A RunFailed result is a failed terminal: its opaque outcome rides as the result under the failed status. Any other result is a success, carried whole. The payload keys are exactly the chain key, result and status. Parameters The give-up handler seam: the driver that parked a run tells its waiter when the platform abandons the park. When the platform gives up redelivering an answered park (its continuation-due record outlived the redelivery horizon), the waiter to tell is the one the parking DRIVER captured for that park. The platform names the interaction only; each driver that parks registers one handler, reads its own record of that interaction, runs its own failed-terminal epilogue and returns the outermost outcome for the platform to deliver to the run’s address. A handler returns None for an interaction that is not its park.

ParkGiveUpHandler

tai42_kit.interactions.park_giveup.ParkGiveUpHandler

ParkGiveUpOutcome

tai42_kit.interactions.park_giveup.ParkGiveUpOutcome
The outermost outcome of a run whose abandoned park its driver gave up, for the platform to deliver. Attributes

fire_park_giveup

tai42_kit.interactions.park_giveup.fire_park_giveup
Ask each registered handler in turn to give up interaction_id’s park; return the first one’s outcome. A handler that owns the park returns its outcome and later handlers are not called; None when no handler owns it. A handler’s raise propagates. Parameters

register_park_giveup_handler

tai42_kit.interactions.park_giveup.register_park_giveup_handler
Register a driver’s give-up handler; handlers run in registration order. A driver registers once at import. Parameters