feat(8.0): thread commit generation through the graph-write provider contract
Graph time-travel needs an edge's existence recorded per generation so db.asOf(g) hops resolve historically correct endpoints. The metadata layer already threads brainy's commit generation per write; the graph write path did not, leaving a versioned verb-endpoint store unable to answer "which edges existed at generation g". - GraphIndexProvider.addVerb/removeVerb gain a `generation: bigint` parameter (the same watermark the storage layer stamps onto the record). A provider with a per-generation edge chain stamps the edge at that generation; the JS baseline has no such chain and accepts-and-ignores it — graph time-travel is a native-provider capability, and the open-core path serves edges as-of-now (the one documented graph time-travel limitation). - The two graph transaction operations resolve the generation via a thunk at EXECUTE time: the generation store assigns the batch generation only once the commit begins executing, after the operations are planned. The same generation is reused for an operation's rollback half. - All graph-write call sites pass the in-flight generation. Adds a spy-provider test proving the threading, execute-time resolution, and forward/rollback generation reuse. The JS index ignores the value, so behaviour is unchanged: unit 1402/1402, db-mvcc 25/25, bigint-contract relate/unrelate 10/10.
This commit is contained in:
parent
b26d3d42b3
commit
0951fa1da0
6 changed files with 195 additions and 26 deletions
|
|
@ -283,6 +283,17 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
* `compactHistory()` and the `Db` value type.
|
||||
*/
|
||||
private generationStore!: GenerationStore
|
||||
/**
|
||||
* Resolves the in-flight write generation as a BigInt, for stamping graph
|
||||
* edges via the {@link GraphIndexProvider} contract. Passed to every
|
||||
* `AddToGraphIndexOperation`/`RemoveFromGraphIndexOperation` and evaluated
|
||||
* when the operation executes — inside a `transact()` batch the generation
|
||||
* store has assigned the batch generation by then; for single-op writes it
|
||||
* reads the post-write watermark. The arrow body reads `generationStore`
|
||||
* lazily, so it is safe to define before `init()` assigns the store.
|
||||
*/
|
||||
private readonly graphWriteGeneration = (): bigint =>
|
||||
BigInt(this.generationStore.generation())
|
||||
/** Lazily built host surface shared by every `Db` value of this brain. */
|
||||
private _dbHost?: DbHost<T>
|
||||
/**
|
||||
|
|
@ -2188,7 +2199,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
// rollback can re-add through the BigInt addVerb contract)
|
||||
const { sourceInt, targetInt } = this.resolveVerbEndpointInts(verb)
|
||||
tx.addOperation(
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt)
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, this.graphWriteGeneration)
|
||||
)
|
||||
// Delete verb metadata
|
||||
tx.addOperation(
|
||||
|
|
@ -2580,6 +2591,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
tx.addOperation(
|
||||
new AddToGraphIndexOperation(
|
||||
this.graphIndex, verb, sourceInt, targetInt,
|
||||
this.graphWriteGeneration,
|
||||
(verbInt) => this.cacheVerbInt(verbInt, id)
|
||||
)
|
||||
)
|
||||
|
|
@ -2618,6 +2630,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
tx.addOperation(
|
||||
new AddToGraphIndexOperation(
|
||||
this.graphIndex, reverseVerb, targetInt, sourceInt,
|
||||
this.graphWriteGeneration,
|
||||
(verbInt) => this.cacheVerbInt(verbInt, reverseId)
|
||||
)
|
||||
)
|
||||
|
|
@ -2660,7 +2673,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
if (verb && endpointInts) {
|
||||
tx.addOperation(
|
||||
new RemoveFromGraphIndexOperation(
|
||||
this.graphIndex, verb, endpointInts.sourceInt, endpointInts.targetInt
|
||||
this.graphIndex, verb, endpointInts.sourceInt, endpointInts.targetInt, this.graphWriteGeneration
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -2785,12 +2798,13 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
if (typeChanged && reindexInts) {
|
||||
tx.addOperation(
|
||||
new RemoveFromGraphIndexOperation(
|
||||
this.graphIndex, existing, reindexInts.sourceInt, reindexInts.targetInt
|
||||
this.graphIndex, existing, reindexInts.sourceInt, reindexInts.targetInt, this.graphWriteGeneration
|
||||
)
|
||||
)
|
||||
tx.addOperation(
|
||||
new AddToGraphIndexOperation(
|
||||
this.graphIndex, verbForIndex, reindexInts.sourceInt, reindexInts.targetInt,
|
||||
this.graphWriteGeneration,
|
||||
(verbInt) => this.cacheVerbInt(verbInt, params.id)
|
||||
)
|
||||
)
|
||||
|
|
@ -4391,7 +4405,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
for (const verb of allVerbs) {
|
||||
const { sourceInt, targetInt } = this.resolveVerbEndpointInts(verb)
|
||||
tx.addOperation(
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt)
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, this.graphWriteGeneration)
|
||||
)
|
||||
tx.addOperation(
|
||||
new DeleteVerbMetadataOperation(this.storage, verb.id)
|
||||
|
|
@ -5977,7 +5991,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
for (const verb of cascade.values()) {
|
||||
const { sourceInt, targetInt } = this.resolveVerbEndpointInts(verb)
|
||||
plan.operations.push(
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt),
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, this.graphWriteGeneration),
|
||||
new DeleteVerbMetadataOperation(this.storage, verb.id)
|
||||
)
|
||||
plan.touchedVerbs.push(verb.id)
|
||||
|
|
@ -6103,7 +6117,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
targetId: params.to
|
||||
}),
|
||||
new SaveVerbMetadataOperation(this.storage, id, verbMetadata),
|
||||
new AddToGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, (verbInt) =>
|
||||
new AddToGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, this.graphWriteGeneration, (verbInt) =>
|
||||
this.cacheVerbInt(verbInt, id)
|
||||
)
|
||||
)
|
||||
|
|
@ -6131,7 +6145,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
targetId: params.from
|
||||
}),
|
||||
new SaveVerbMetadataOperation(this.storage, reverseId, verbMetadata),
|
||||
new AddToGraphIndexOperation(this.graphIndex, reverseVerb, targetInt, sourceInt, (verbInt) =>
|
||||
new AddToGraphIndexOperation(this.graphIndex, reverseVerb, targetInt, sourceInt, this.graphWriteGeneration, (verbInt) =>
|
||||
this.cacheVerbInt(verbInt, reverseId)
|
||||
)
|
||||
)
|
||||
|
|
@ -6161,7 +6175,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
if (verb) {
|
||||
const { sourceInt, targetInt } = this.resolveVerbEndpointInts(verb)
|
||||
plan.operations.push(
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt)
|
||||
new RemoveFromGraphIndexOperation(this.graphIndex, verb, sourceInt, targetInt, this.graphWriteGeneration)
|
||||
)
|
||||
}
|
||||
plan.operations.push(new DeleteVerbMetadataOperation(this.storage, id))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue