specs

fun specs(): List<<Error class: unknown class>>

Every constraint and index the store depends on.

Constraints.

  • ExtractionRun(contextId, runId) — the tenant-qualified natural key. Two tenants minting the same run id are two runs, which is the whole reason the tenant is in the key.

  • ExtractionRunInvocation(contextId, runId, invocationIndex, attempt) — the deterministic child key. A retried attempt lands on its own row, and a replayed write of the same attempt upserts in place.

  • ExtractionRunTerminalWrite(contextId, runId) — at most one terminal write per run, ever. This is the compare-and-set. Two writers that both read a run as RUNNING both try to create this node, and the database lets exactly one of them commit.

Indexes. Each one is what a specific read seeks on, and none of them carries status or the terminal fingerprint — deliberately, because the compare-and-set reads both after taking its lock and an indexed property could be served from an index entry read before it.

  • (contextId)runsInContext. A composite index cannot stand in: Neo4j will not use one for a predicate on only its leading property, so without this the tenant predicate is a label scan. Same reasoning as the Proposition(contextId) index.

  • (contextId, rootRunId)runsOfRoot, the read the denormalized root exists for.

  • (contextId, parentRunId)childrenOf, one hop down the parent axis.

  • (contextId, startedAtEpochSecond) — the paging sort key. Pages are newest-first by start time within one tenant.

  • ExtractionRunInvocation(contextId, runId) — reading one run's attempts. The four-property constraint index is keyed on the whole identity and is not a substitute for a lookup on the first two.