@xyo-network/diviner-temporal-indexing-memory 3.6.0-rc.1 → 3.6.0-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -82,9 +82,9 @@ export class TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner<
82
82
  sourcePathExpression: '$.limit',
83
83
  },
84
84
  {
85
- defaultValue: 0,
86
- destinationField: 'offset',
87
- sourcePathExpression: '$.offset',
85
+ // defaultValue: 0,
86
+ destinationField: 'cursor',
87
+ sourcePathExpression: '$.cursor',
88
88
  },
89
89
  {
90
90
  defaultValue: 'desc',
@@ -111,7 +111,7 @@ export class TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner<
111
111
  // TODO: Make sources not need to be deleted
112
112
  delete fields.sources
113
113
  // TODO: Add support for additional filters
114
- return await new PayloadBuilder<Payload>({ schema: this.indexQuerySchema }).fields(fields).build()
114
+ return new PayloadBuilder<Payload>({ schema: this.indexQuerySchema }).fields(fields).build()
115
115
  }),
116
116
  )
117
117
  }
@@ -104,24 +104,22 @@ export class TemporalIndexingDivinerIndexCandidateToIndexDiviner<
104
104
  }
105
105
 
106
106
  // Create the indexes from the tuples
107
- const indexes = await Promise.all(
108
- validIndexableTuples.map<Promise<TemporalIndexingDivinerResultIndex>>(async ([bwHash, ...sourcePayloadHashes]) => {
109
- const sourcePayloads = sourcePayloadHashes.map(hash => payloadDictionary[hash])
110
- // Use the payload transformers to convert the fields from the source payloads to the destination fields
111
- const indexFields = sourcePayloads.flatMap((payload) => {
112
- // Find the transformers for this payload
113
- const transformers = this.payloadTransformers[payload.schema]
114
- // If transformers exist, apply them to the payload otherwise return an empty array
115
- return transformers ? transformers.map(transform => transform(payload)) : []
116
- })
117
- // Include all the sources for reference
118
- const sources: string[] = [bwHash, ...sourcePayloadHashes]
119
- // Build and return the index
120
- return await new PayloadBuilder<TemporalIndexingDivinerResultIndex>({ schema: TemporalIndexingDivinerResultIndexSchema })
121
- .fields(Object.assign({ sources }, ...indexFields))
122
- .build()
123
- }),
124
- )
107
+ const indexes = validIndexableTuples.map<TemporalIndexingDivinerResultIndex>(([bwHash, ...sourcePayloadHashes]) => {
108
+ const sourcePayloads = sourcePayloadHashes.map(hash => payloadDictionary[hash])
109
+ // Use the payload transformers to convert the fields from the source payloads to the destination fields
110
+ const indexFields = sourcePayloads.flatMap((payload) => {
111
+ // Find the transformers for this payload
112
+ const transformers = this.payloadTransformers[payload.schema]
113
+ // If transformers exist, apply them to the payload otherwise return an empty array
114
+ return transformers ? transformers.map(transform => transform(payload)) : []
115
+ })
116
+ // Include all the sources for reference
117
+ const sources: Hash[] = [bwHash, ...sourcePayloadHashes]
118
+ // Build and return the index
119
+ return new PayloadBuilder<TemporalIndexingDivinerResultIndex>({ schema: TemporalIndexingDivinerResultIndexSchema })
120
+ .fields(Object.assign({ sources }, ...indexFields))
121
+ .build()
122
+ })
125
123
  return indexes.flat()
126
124
  }
127
125
 
@@ -1,13 +1,14 @@
1
+ import { filterAs } from '@xylabs/array'
1
2
  import { assertEx } from '@xylabs/assert'
2
3
  import { exists } from '@xylabs/exists'
3
- import type { ArchivistInstance } from '@xyo-network/archivist-model'
4
+ import type { ArchivistInstance, ArchivistNextOptions } from '@xyo-network/archivist-model'
4
5
  import { ArchivistWrapper } from '@xyo-network/archivist-wrapper'
5
6
  import type { BoundWitness } from '@xyo-network/boundwitness-model'
6
- import { isBoundWitness } from '@xyo-network/boundwitness-model'
7
+ import { asBoundWitness, isBoundWitness } from '@xyo-network/boundwitness-model'
8
+ import { payloadSchemasContainsAll } from '@xyo-network/boundwitness-validator'
7
9
  import { AbstractDiviner } from '@xyo-network/diviner-abstract'
8
10
  import type { BoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-abstract'
9
11
  import type { BoundWitnessDivinerParams, BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'
10
- import { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'
11
12
  import type { IndexingDivinerState } from '@xyo-network/diviner-indexing-model'
12
13
  import type { TemporalIndexingDivinerStateToIndexCandidateDivinerParams } from '@xyo-network/diviner-temporal-indexing-model'
13
14
  import { TemporalIndexingDivinerStateToIndexCandidateDivinerConfigSchema } from '@xyo-network/diviner-temporal-indexing-model'
@@ -16,8 +17,11 @@ import type {
16
17
  Labels, ModuleIdentifier, ModuleState,
17
18
  } from '@xyo-network/module-model'
18
19
  import { isModuleState, ModuleStateSchema } from '@xyo-network/module-model'
19
- import { PayloadBuilder } from '@xyo-network/payload-builder'
20
- import type { Payload, Schema } from '@xyo-network/payload-model'
20
+ import type {
21
+ Payload, Schema,
22
+ WithStorageMeta,
23
+ } from '@xyo-network/payload-model'
24
+ import { SequenceConstants } from '@xyo-network/payload-model'
21
25
  import { intraBoundwitnessSchemaCombinations } from '@xyo-network/payload-utils'
22
26
  import type { TimeStamp } from '@xyo-network/witness-timestamp'
23
27
  import { TimestampSchema } from '@xyo-network/witness-timestamp'
@@ -76,31 +80,35 @@ export class TemporalIndexingDivinerStateToIndexCandidateDiviner<
76
80
  return [TimestampSchema, ...(schemas ?? [])]
77
81
  }
78
82
 
79
- protected override async divineHandler(payloads: Payload[] = []): Promise<[ModuleState, ...IndexCandidate[]]> {
83
+ protected override async divineHandler(payloads: Payload[] = []): Promise<TemporalStateToIndexCandidateDivinerResponse> {
80
84
  // Retrieve the last state from what was passed in
81
85
  const lastState = payloads.find(isModuleState<IndexingDivinerState>)
82
86
  // If there is no last state, start from the beginning
83
- if (!lastState) return [{ schema: ModuleStateSchema, state: { offset: 0 } }]
84
- // Otherwise, get the last offset
85
- const { offset } = lastState.state
86
- // Get next batch of results starting from the offset
87
- const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore()
88
- if (!boundWitnessDiviner) return [lastState]
89
- const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })
90
- .fields({
91
- limit: this.payloadDivinerLimit, offset, order, payload_schemas: this.payload_schemas,
92
- })
93
- .build()
94
- const batch = await boundWitnessDiviner.divine([query])
95
- if (batch.length === 0) return [lastState]
96
- // Get source data
87
+ ?? { schema: ModuleStateSchema, state: { cursor: SequenceConstants.minLocalSequence } }
88
+
89
+ // Get the last cursor
90
+ const cursor = lastState?.state?.cursor
91
+ // Get the archivist for the store
97
92
  const sourceArchivist = await this.getArchivistForStore()
98
93
  if (!sourceArchivist) return [lastState]
94
+
95
+ // Get the next batch of results
96
+ const nextOffset: ArchivistNextOptions = { limit: this.payloadDivinerLimit, order }
97
+ // Only use the cursor if it's a valid offset
98
+ if (cursor !== SequenceConstants.minLocalSequence) nextOffset.cursor = cursor
99
+ // Get next batch of results starting from the offset
100
+ const next = await sourceArchivist.next(nextOffset)
101
+ if (next.length === 0) return [lastState]
102
+ const batch = filterAs(next, asBoundWitness)
103
+ .filter(exists)
104
+ .filter(bw => payloadSchemasContainsAll(bw, this.payload_schemas))
105
+ // Get source data
99
106
  const bws = batch.filter(isBoundWitness)
100
107
  const indexCandidates: IndexCandidate[] = (await Promise.all(bws.map(bw => this.getPayloadsInBoundWitness(bw, sourceArchivist))))
101
108
  .filter(exists)
102
109
  .flat()
103
- const nextState = { schema: ModuleStateSchema, state: { ...lastState.state, offset: offset + batch.length } }
110
+ const nextCursor = assertEx(next.at(-1)?._sequence, () => `${moduleName}: Expected next to have a sequence`)
111
+ const nextState: ModuleState<IndexingDivinerState> = { schema: ModuleStateSchema, state: { ...lastState.state, cursor: nextCursor } }
104
112
  return [nextState, ...indexCandidates]
105
113
  }
106
114
 
@@ -139,7 +147,7 @@ export class TemporalIndexingDivinerStateToIndexCandidateDiviner<
139
147
  DivinerWrapper<
140
148
  BoundWitnessDiviner<BoundWitnessDivinerParams, BoundWitnessDivinerQueryPayload, BoundWitness>,
141
149
  BoundWitnessDivinerQueryPayload,
142
- BoundWitness
150
+ WithStorageMeta<BoundWitness>
143
151
  >
144
152
  >(mod, this.account)
145
153
  }