@xyo-network/bridge-pub-sub 3.6.0-rc.1 → 3.6.0-rc.10

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.
@@ -1,5 +1,5 @@
1
1
  import { assertEx } from '@xylabs/assert'
2
- import type { Address } from '@xylabs/hex'
2
+ import type { Address, Hex } from '@xylabs/hex'
3
3
  import type { TypeCheck } from '@xylabs/object'
4
4
  import { Base } from '@xylabs/object'
5
5
  import type { ArchivistInstance } from '@xyo-network/archivist-model'
@@ -12,6 +12,7 @@ import type {
12
12
  ModuleConfig, ModuleIdentifier, ModuleInstance,
13
13
  } from '@xyo-network/module-model'
14
14
  import { ResolveHelper } from '@xyo-network/module-model'
15
+ import { SequenceConstants } from '@xyo-network/payload-model'
15
16
  import { Mutex } from 'async-mutex'
16
17
  import { LRUCache } from 'lru-cache'
17
18
 
@@ -22,7 +23,7 @@ const POLLING_FREQUENCY_MAX = 60_000 as const
22
23
  const POLLING_FREQUENCY_DEFAULT = 1000 as const
23
24
 
24
25
  export class AsyncQueryBusBase<TParams extends AsyncQueryBusParams = AsyncQueryBusParams> extends Base<TParams> {
25
- protected _lastState?: LRUCache<Address, number>
26
+ protected _lastState?: LRUCache<Address, Hex>
26
27
  protected _targetConfigs: Record<Address, ModuleConfig> = {}
27
28
  protected _targetQueries: Record<Address, string[]> = {}
28
29
 
@@ -57,9 +58,9 @@ export class AsyncQueryBusBase<TParams extends AsyncQueryBusParams = AsyncQueryB
57
58
  /**
58
59
  * A cache of the last offset of the Diviner process per address
59
60
  */
60
- protected get lastState(): LRUCache<Address, number> {
61
+ protected get lastState(): LRUCache<Address, Hex> {
61
62
  const requiredConfig = { max: 1000, ttl: 0 }
62
- this._lastState = this._lastState ?? new LRUCache<Address, number>(requiredConfig)
63
+ this._lastState = this._lastState ?? new LRUCache<Address, Hex>(requiredConfig)
63
64
  return this._lastState
64
65
  }
65
66
 
@@ -119,7 +120,7 @@ export class AsyncQueryBusBase<TParams extends AsyncQueryBusParams = AsyncQueryB
119
120
  * @param address The module address to commit the state for
120
121
  * @param nextState The state to commit
121
122
  */
122
- protected async commitState(address: Address, nextState: number) {
123
+ protected async commitState(address: Address, nextState: Hex) {
123
124
  await Promise.resolve()
124
125
  // TODO: Offload to Archivist/Diviner instead of in-memory
125
126
  const lastState = this.lastState.get(address)
@@ -131,13 +132,11 @@ export class AsyncQueryBusBase<TParams extends AsyncQueryBusParams = AsyncQueryB
131
132
  * Retrieves the last state of the process. Used to recover state after
132
133
  * preemptions, reboots, etc.
133
134
  */
134
- protected async retrieveState(address: Address): Promise<number> {
135
+ protected async retrieveState(address: Address): Promise<Hex> {
135
136
  await Promise.resolve()
136
137
  const state = this.lastState.get(address)
137
138
  if (state === undefined) {
138
- // If this is a boot we can go back a bit in time
139
- // and begin processing recent commands
140
- const newState = Date.now() - 1000
139
+ const newState = SequenceConstants.minLocalSequence
141
140
  this.lastState.set(address, newState)
142
141
  return newState
143
142
  } else {
@@ -9,7 +9,9 @@ import type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-bound
9
9
  import { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'
10
10
  import type { CacheConfig, ModuleQueryResult } from '@xyo-network/module-model'
11
11
  import { PayloadBuilder } from '@xyo-network/payload-builder'
12
- import type { ModuleError, Payload } from '@xyo-network/payload-model'
12
+ import type {
13
+ ModuleError, Payload, WithSources,
14
+ } from '@xyo-network/payload-model'
13
15
  import { LRUCache } from 'lru-cache'
14
16
 
15
17
  import { AsyncQueryBusBase } from './AsyncQueryBusBase.ts'
@@ -103,11 +105,11 @@ export class AsyncQueryBusClient<TParams extends AsyncQueryBusClientParams = Asy
103
105
  this.logger?.error('Timeout waiting for query response')
104
106
  // Resolve with error to match what a local module would do if it were to error
105
107
  // TODO: BW Builder/Sign result as this module?
106
- const error: ModuleError = {
108
+ const error: WithSources<ModuleError> = {
107
109
  message: 'Timeout waiting for query response',
108
110
  query: 'network.xyo.boundwitness',
109
111
  schema: 'network.xyo.error.module',
110
- sources: [routedQueryHash],
112
+ $sources: [routedQueryHash],
111
113
  }
112
114
  reject(error)
113
115
  return
@@ -3,7 +3,7 @@ import { assertEx } from '@xylabs/assert'
3
3
  import type { Address } from '@xylabs/hex'
4
4
  import { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'
5
5
  import type { QueryBoundWitness } from '@xyo-network/boundwitness-model'
6
- import { isQueryBoundWitness } from '@xyo-network/boundwitness-model'
6
+ import { isQueryBoundWitnessWithStorageMeta } from '@xyo-network/boundwitness-model'
7
7
  import { isBridgeInstance } from '@xyo-network/bridge-model'
8
8
  import type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'
9
9
  import { BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'
@@ -18,7 +18,9 @@ import {
18
18
  ResolveHelper,
19
19
  } from '@xyo-network/module-model'
20
20
  import { PayloadBuilder } from '@xyo-network/payload-builder'
21
- import type { Schema } from '@xyo-network/payload-model'
21
+ import {
22
+ type Schema, SequenceConstants, type WithStorageMeta,
23
+ } from '@xyo-network/payload-model'
22
24
 
23
25
  import { AsyncQueryBusBase } from './AsyncQueryBusBase.ts'
24
26
  import type { AsyncQueryBusHostParams } from './model/index.ts'
@@ -132,7 +134,7 @@ export class AsyncQueryBusHost<TParams extends AsyncQueryBusHostParams = AsyncQu
132
134
  }
133
135
 
134
136
  // eslint-disable-next-line complexity
135
- protected callLocalModule = async (localModule: ModuleInstance, query: QueryBoundWitness) => {
137
+ protected callLocalModule = async (localModule: ModuleInstance, query: WithStorageMeta<QueryBoundWitness>) => {
136
138
  this._idle = false
137
139
  this._lastQueryTime = Date.now()
138
140
  const localModuleName = localModule.id
@@ -179,11 +181,11 @@ export class AsyncQueryBusHost<TParams extends AsyncQueryBusHostParams = AsyncQu
179
181
  if (insertResult.length === 0) {
180
182
  this.logger?.error(`Error replying to query ${queryHash} addressed to module: ${localModuleName}`)
181
183
  }
182
- if (query?.timestamp) {
184
+ if (query?._sequence) {
183
185
  // TODO: This needs to be thought through as we can't use a distributed timestamp
184
186
  // because of collisions. We need to ensure we are using the timestamp of the store
185
187
  // so there's no chance of multiple commands at the same time
186
- await this.commitState(localModule.address, query.timestamp)
188
+ await this.commitState(localModule.address, query._sequence)
187
189
  }
188
190
  this.params.onQueryFulfillFinished?.({
189
191
  payloads: queryPayloads, query, result, status: 'success',
@@ -217,11 +219,13 @@ export class AsyncQueryBusHost<TParams extends AsyncQueryBusHostParams = AsyncQu
217
219
  limit,
218
220
  order: 'asc',
219
221
  schema: BoundWitnessDivinerQuerySchema,
220
- timestamp: prevState + 1,
222
+ cursor: prevState,
221
223
  }
222
224
  const result = await queriesBoundWitnessDiviner.divine([divinerQuery])
223
- const queries = result.filter(isQueryBoundWitness)
224
- const nextState = queries.length > 0 ? Math.max(...queries.map(c => c.timestamp ?? prevState)) + 1 : Date.now()
225
+ const queries = result.filter(isQueryBoundWitnessWithStorageMeta)
226
+ // eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-math-min-max
227
+ const highestQuerySequence = queries.reduce((acc, query) => acc = (query._sequence > acc ? query._sequence : acc), SequenceConstants.minLocalSequence)
228
+ const nextState = queries.length > 0 ? highestQuerySequence : SequenceConstants.minLocalSequence
225
229
  // TODO: This needs to be thought through as we can't use a distributed timestamp
226
230
  // because of collisions. We need to use the timestamp of the store so there's no
227
231
  // chance of multiple commands at the same time