link

abstract fun link(key: ExtractionRunKey, propositionIds: Collection<String>): Int

Records that key's run produced each of propositionIds, in that run's tenant.

Idempotent: the link is merged on the pair, so re-running an extraction that produced the same claims writes nothing new and returns the same number. That is what makes the relation safe to write from a path that can be retried.

An empty batch is a no-op and touches nothing.

Return

How many links now join this run to these propositions. Equal on a replay.

Parameters

key

The run, tenant-qualified.

propositionIds

Canonical ids of the propositions the run produced. Duplicates in the collection are one link.

Throws

if this tenant has no run under that id. A claim attributed to a run nobody recorded is a dangling audit row.

if any id names a proposition this tenant does not hold, whether it does not exist at all or belongs to a neighbour. Nothing is written.

The failures listed above must not damage the caller. Lineage is written best-effort by a caller that catches and carries on, so raising one of them has to leave everything else exactly as it was — including a transaction the caller is running in. They are all raised after the implementation's own reads and writes have succeeded, which is what makes that possible; an implementation that joins a caller's transaction must not condemn it on the way out. DrivinePropositionRunLinkStore's integration tests hold the one backend that has a transaction to condemn to this. The in-memory reference has none, so the shared contract suite has nothing to assert here and does not pretend to.

A failure below an implementation — a database that terminates the transaction itself — is outside this and outside any catch. See DrivinePropositionRunLinkStore.link.


open fun link(key: ExtractionRunKey, propositionId: String): Int

link for a single proposition.