@xyo-network/bridge-pub-sub 3.5.2 → 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.
- package/dist/neutral/AsyncQueryBus/AsyncQueryBusBase.d.ts +263 -78
- package/dist/neutral/AsyncQueryBus/AsyncQueryBusBase.d.ts.map +1 -1
- package/dist/neutral/AsyncQueryBus/AsyncQueryBusClient.d.ts.map +1 -1
- package/dist/neutral/AsyncQueryBus/AsyncQueryBusHost.d.ts +75 -20
- package/dist/neutral/AsyncQueryBus/AsyncQueryBusHost.d.ts.map +1 -1
- package/dist/neutral/PubSubBridgeModuleResolver.d.ts +36 -5
- package/dist/neutral/PubSubBridgeModuleResolver.d.ts.map +1 -1
- package/dist/neutral/index.mjs +20 -21
- package/dist/neutral/index.mjs.map +1 -1
- package/package.json +35 -34
- package/src/AsyncQueryBus/AsyncQueryBusBase.ts +8 -9
- package/src/AsyncQueryBus/AsyncQueryBusClient.ts +9 -14
- package/src/AsyncQueryBus/AsyncQueryBusHost.ts +14 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/bridge-pub-sub",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0-rc.10",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -29,45 +29,46 @@
|
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/neutral/index.d.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xylabs/array": "^4.4.
|
|
33
|
-
"@xylabs/assert": "^4.4.
|
|
34
|
-
"@xylabs/delay": "^4.4.
|
|
35
|
-
"@xylabs/exists": "^4.4.
|
|
36
|
-
"@xylabs/forget": "^4.4.
|
|
37
|
-
"@xylabs/hex": "^4.4.
|
|
38
|
-
"@xylabs/object": "^4.4.
|
|
39
|
-
"@xylabs/promise": "^4.4.
|
|
40
|
-
"@xylabs/timer": "^4.4.
|
|
41
|
-
"@xyo-network/account": "^3.
|
|
42
|
-
"@xyo-network/archivist-model": "^3.
|
|
43
|
-
"@xyo-network/boundwitness-model": "^3.
|
|
44
|
-
"@xyo-network/bridge-abstract": "^3.
|
|
45
|
-
"@xyo-network/bridge-model": "^3.
|
|
46
|
-
"@xyo-network/config-payload-plugin": "^3.
|
|
47
|
-
"@xyo-network/diviner-boundwitness-model": "^3.
|
|
48
|
-
"@xyo-network/diviner-model": "^3.
|
|
49
|
-
"@xyo-network/module-model": "^3.
|
|
50
|
-
"@xyo-network/node-model": "^3.
|
|
51
|
-
"@xyo-network/payload-builder": "^3.
|
|
52
|
-
"@xyo-network/payload-model": "^3.
|
|
32
|
+
"@xylabs/array": "^4.4.21",
|
|
33
|
+
"@xylabs/assert": "^4.4.21",
|
|
34
|
+
"@xylabs/delay": "^4.4.21",
|
|
35
|
+
"@xylabs/exists": "^4.4.21",
|
|
36
|
+
"@xylabs/forget": "^4.4.21",
|
|
37
|
+
"@xylabs/hex": "^4.4.21",
|
|
38
|
+
"@xylabs/object": "^4.4.21",
|
|
39
|
+
"@xylabs/promise": "^4.4.21",
|
|
40
|
+
"@xylabs/timer": "^4.4.21",
|
|
41
|
+
"@xyo-network/account": "^3.6.0-rc.10",
|
|
42
|
+
"@xyo-network/archivist-model": "^3.6.0-rc.10",
|
|
43
|
+
"@xyo-network/boundwitness-model": "^3.6.0-rc.10",
|
|
44
|
+
"@xyo-network/bridge-abstract": "^3.6.0-rc.10",
|
|
45
|
+
"@xyo-network/bridge-model": "^3.6.0-rc.10",
|
|
46
|
+
"@xyo-network/config-payload-plugin": "^3.6.0-rc.10",
|
|
47
|
+
"@xyo-network/diviner-boundwitness-model": "^3.6.0-rc.10",
|
|
48
|
+
"@xyo-network/diviner-model": "^3.6.0-rc.10",
|
|
49
|
+
"@xyo-network/module-model": "^3.6.0-rc.10",
|
|
50
|
+
"@xyo-network/node-model": "^3.6.0-rc.10",
|
|
51
|
+
"@xyo-network/payload-builder": "^3.6.0-rc.10",
|
|
52
|
+
"@xyo-network/payload-model": "^3.6.0-rc.10",
|
|
53
53
|
"async-mutex": "^0.5.0",
|
|
54
54
|
"lru-cache": "^11.0.2"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@xylabs/logger": "^4.4.
|
|
58
|
-
"@xylabs/ts-scripts-yarn3": "^4.2.
|
|
59
|
-
"@xylabs/tsconfig": "^4.2.
|
|
60
|
-
"@xylabs/vitest-extended": "^4.4.
|
|
61
|
-
"@xyo-network/archivist-memory": "^3.
|
|
62
|
-
"@xyo-network/diviner-boundwitness-memory": "^3.
|
|
63
|
-
"@xyo-network/module-abstract": "^3.
|
|
64
|
-
"@xyo-network/node-memory": "^3.
|
|
65
|
-
"@xyo-network/node-model": "^3.
|
|
66
|
-
"@xyo-network/payload-wrapper": "^3.
|
|
57
|
+
"@xylabs/logger": "^4.4.21",
|
|
58
|
+
"@xylabs/ts-scripts-yarn3": "^4.2.6",
|
|
59
|
+
"@xylabs/tsconfig": "^4.2.6",
|
|
60
|
+
"@xylabs/vitest-extended": "^4.4.21",
|
|
61
|
+
"@xyo-network/archivist-memory": "^3.6.0-rc.10",
|
|
62
|
+
"@xyo-network/diviner-boundwitness-memory": "^3.6.0-rc.10",
|
|
63
|
+
"@xyo-network/module-abstract": "^3.6.0-rc.10",
|
|
64
|
+
"@xyo-network/node-memory": "^3.6.0-rc.10",
|
|
65
|
+
"@xyo-network/node-model": "^3.6.0-rc.10",
|
|
66
|
+
"@xyo-network/payload-wrapper": "^3.6.0-rc.10",
|
|
67
67
|
"typescript": "^5.7.2",
|
|
68
|
-
"vitest": "^2.1.
|
|
68
|
+
"vitest": "^2.1.8"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
|
-
}
|
|
72
|
+
},
|
|
73
|
+
"stableVersion": "3.5.2"
|
|
73
74
|
}
|
|
@@ -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,
|
|
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,
|
|
61
|
+
protected get lastState(): LRUCache<Address, Hex> {
|
|
61
62
|
const requiredConfig = { max: 1000, ttl: 0 }
|
|
62
|
-
this._lastState = this._lastState ?? new LRUCache<Address,
|
|
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:
|
|
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<
|
|
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
|
-
|
|
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 {
|
|
@@ -4,13 +4,13 @@ import { forget } from '@xylabs/forget'
|
|
|
4
4
|
import type { Address } from '@xylabs/hex'
|
|
5
5
|
import { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'
|
|
6
6
|
import type { QueryBoundWitness } from '@xyo-network/boundwitness-model'
|
|
7
|
-
import {
|
|
7
|
+
import { isBoundWitness } from '@xyo-network/boundwitness-model'
|
|
8
8
|
import type { BoundWitnessDivinerQueryPayload } from '@xyo-network/diviner-boundwitness-model'
|
|
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
12
|
import type {
|
|
13
|
-
ModuleError, Payload,
|
|
13
|
+
ModuleError, Payload, WithSources,
|
|
14
14
|
} from '@xyo-network/payload-model'
|
|
15
15
|
import { LRUCache } from 'lru-cache'
|
|
16
16
|
|
|
@@ -54,8 +54,7 @@ export class AsyncQueryBusClient<TParams extends AsyncQueryBusClientParams = Asy
|
|
|
54
54
|
|
|
55
55
|
async send(address: Address, query: QueryBoundWitness, payloads?: Payload[] | undefined): Promise<ModuleQueryResult> {
|
|
56
56
|
this.logger?.debug(`Begin issuing query to: ${address}`)
|
|
57
|
-
const
|
|
58
|
-
const routedQuery = await PayloadBuilder.build({ ...query, $meta })
|
|
57
|
+
const routedQuery = { ...query, $destination: [address] }
|
|
59
58
|
// console.log('queryArchivist - calling')
|
|
60
59
|
const queryArchivist = assertEx(
|
|
61
60
|
await this.queriesArchivist(),
|
|
@@ -69,11 +68,7 @@ export class AsyncQueryBusClient<TParams extends AsyncQueryBusClientParams = Asy
|
|
|
69
68
|
// they sent us (which might be OK since it reflect the chain of custody)
|
|
70
69
|
// Revisit this once we have proxy module support as they are another
|
|
71
70
|
// intermediary to consider.
|
|
72
|
-
const routedQueryHash
|
|
73
|
-
// Trust the signed hash if it's there
|
|
74
|
-
= (routedQuery as WithMeta<QueryBoundWitness>)?.$hash
|
|
75
|
-
// Calculate the hash otherwise
|
|
76
|
-
?? Object.keys(await PayloadBuilder.dataHash(routedQuery))
|
|
71
|
+
const routedQueryHash = await PayloadBuilder.dataHash(routedQuery)
|
|
77
72
|
this.logger?.debug(`Issuing query: ${routedQueryHash} to: ${address}`)
|
|
78
73
|
// If there was data associated with the query, add it to the insert
|
|
79
74
|
const data = payloads ? [routedQuery, ...payloads] : [routedQuery]
|
|
@@ -110,11 +105,11 @@ export class AsyncQueryBusClient<TParams extends AsyncQueryBusClientParams = Asy
|
|
|
110
105
|
this.logger?.error('Timeout waiting for query response')
|
|
111
106
|
// Resolve with error to match what a local module would do if it were to error
|
|
112
107
|
// TODO: BW Builder/Sign result as this module?
|
|
113
|
-
const error: ModuleError = {
|
|
108
|
+
const error: WithSources<ModuleError> = {
|
|
114
109
|
message: 'Timeout waiting for query response',
|
|
115
110
|
query: 'network.xyo.boundwitness',
|
|
116
111
|
schema: 'network.xyo.error.module',
|
|
117
|
-
sources: [routedQueryHash],
|
|
112
|
+
$sources: [routedQueryHash],
|
|
118
113
|
}
|
|
119
114
|
reject(error)
|
|
120
115
|
return
|
|
@@ -162,11 +157,11 @@ export class AsyncQueryBusClient<TParams extends AsyncQueryBusClientParams = Asy
|
|
|
162
157
|
}
|
|
163
158
|
const result = await responseBoundWitnessDiviner.divine([divinerQuery])
|
|
164
159
|
if (result && result.length > 0) {
|
|
165
|
-
const response = result.find(
|
|
166
|
-
if (response && (response
|
|
160
|
+
const response = result.find(isBoundWitness)
|
|
161
|
+
if (response && (response as unknown as { $sourceQuery: string })?.$sourceQuery === sourceQuery) {
|
|
167
162
|
this.logger?.debug(`Found response to query: ${sourceQuery}`)
|
|
168
163
|
// Get any payloads associated with the response
|
|
169
|
-
const payloads:
|
|
164
|
+
const payloads: Payload[] = response.payload_hashes?.length > 0 ? await responseArchivist.get(response.payload_hashes) : []
|
|
170
165
|
this.queryCache.set(sourceQuery, [response, payloads, []])
|
|
171
166
|
}
|
|
172
167
|
}
|
|
@@ -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 {
|
|
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
|
|
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:
|
|
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
|
|
@@ -144,7 +146,7 @@ export class AsyncQueryBusHost<TParams extends AsyncQueryBusHostParams = AsyncQu
|
|
|
144
146
|
await this.responsesArchivist(),
|
|
145
147
|
() => `Unable to contact responsesArchivist [${this.config?.intersect?.queries?.archivist}]`,
|
|
146
148
|
)
|
|
147
|
-
const queryDestination = (query
|
|
149
|
+
const queryDestination = (query as { $destination?: string[] })?.$destination
|
|
148
150
|
if (queryDestination && queryDestination?.includes(localModule.address)) {
|
|
149
151
|
// Find the query
|
|
150
152
|
const queryIndex = query.payload_hashes.indexOf(query.query)
|
|
@@ -156,7 +158,7 @@ export class AsyncQueryBusHost<TParams extends AsyncQueryBusHostParams = AsyncQu
|
|
|
156
158
|
const queryPayloads = await queryArchivist.get(query.payload_hashes)
|
|
157
159
|
this.params.onQueryFulfillStarted?.({ payloads: queryPayloads, query })
|
|
158
160
|
const queryPayloadsDict = await PayloadBuilder.toAllHashMap(queryPayloads)
|
|
159
|
-
const queryHash =
|
|
161
|
+
const queryHash = await PayloadBuilder.dataHash(query)
|
|
160
162
|
// Check that we have all the arguments for the command
|
|
161
163
|
if (!containsAll(Object.keys(queryPayloadsDict), query.payload_hashes)) {
|
|
162
164
|
this.logger?.error(`Error processing command ${queryHash} for module ${localModuleName}, missing payloads`)
|
|
@@ -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?.
|
|
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.
|
|
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
|
-
|
|
222
|
+
cursor: prevState,
|
|
221
223
|
}
|
|
222
224
|
const result = await queriesBoundWitnessDiviner.divine([divinerQuery])
|
|
223
|
-
const queries = result.filter(
|
|
224
|
-
|
|
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
|