@xyo-network/diviner-indexing-memory 2.104.0 → 2.104.1
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/browser/index.cjs +7 -14
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +7 -14
- package/dist/browser/index.js.map +1 -1
- package/dist/neutral/index.cjs +7 -14
- package/dist/neutral/index.cjs.map +1 -1
- package/dist/neutral/index.js +7 -14
- package/dist/neutral/index.js.map +1 -1
- package/dist/node/index.cjs +8 -18
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +8 -18
- package/dist/node/index.js.map +1 -1
- package/package.json +14 -14
package/dist/browser/index.cjs
CHANGED
|
@@ -40,12 +40,8 @@ var import_module_model = require("@xyo-network/module-model");
|
|
|
40
40
|
var import_payload_builder = require("@xyo-network/payload-builder");
|
|
41
41
|
function _ts_decorate(decorators, target, key, desc) {
|
|
42
42
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
43
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
44
|
-
|
|
45
|
-
else
|
|
46
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
47
|
-
if (d = decorators[i])
|
|
48
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
43
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
44
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
49
45
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
50
46
|
}
|
|
51
47
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -72,7 +68,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
72
68
|
* Works via batched iteration of the source archivist to populate the index.
|
|
73
69
|
* @returns A promise that resolves when the background process is complete
|
|
74
70
|
*/
|
|
75
|
-
backgroundDivine = async () => {
|
|
71
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
76
72
|
const lastState = await this.retrieveState();
|
|
77
73
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
78
74
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -87,7 +83,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
87
83
|
if (nextState) {
|
|
88
84
|
await this.commitState(nextState);
|
|
89
85
|
}
|
|
90
|
-
};
|
|
86
|
+
}, "backgroundDivine");
|
|
91
87
|
/**
|
|
92
88
|
* Commit the internal state of the Diviner process. This is similar
|
|
93
89
|
* to a transaction completion in a database and should only be called
|
|
@@ -96,8 +92,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
96
92
|
* @param nextState The state to commit
|
|
97
93
|
*/
|
|
98
94
|
async commitState(nextState) {
|
|
99
|
-
if (nextState.state.offset === this._lastState?.state.offset)
|
|
100
|
-
return;
|
|
95
|
+
if (nextState.state.offset === this._lastState?.state.offset) return;
|
|
101
96
|
this._lastState = nextState;
|
|
102
97
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
103
98
|
const [bw] = await new import_boundwitness_builder.BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -168,8 +163,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
168
163
|
* preemptions, reboots, etc.
|
|
169
164
|
*/
|
|
170
165
|
async retrieveState() {
|
|
171
|
-
if (this._lastState)
|
|
172
|
-
return this._lastState;
|
|
166
|
+
if (this._lastState) return this._lastState;
|
|
173
167
|
let hash = "";
|
|
174
168
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
175
169
|
const query = await new import_payload_builder.PayloadBuilder({
|
|
@@ -230,8 +224,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
230
224
|
} catch (e) {
|
|
231
225
|
console.log(e);
|
|
232
226
|
} finally {
|
|
233
|
-
if (this._pollId)
|
|
234
|
-
(0, import_timer.clearTimeoutEx)(this._pollId);
|
|
227
|
+
if (this._pollId) (0, import_timer.clearTimeoutEx)(this._pollId);
|
|
235
228
|
this._pollId = void 0;
|
|
236
229
|
this.poll();
|
|
237
230
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
package/dist/browser/index.js
CHANGED
|
@@ -16,12 +16,8 @@ import { creatableModule, isModuleState, isModuleStateWithMeta, ModuleStateSchem
|
|
|
16
16
|
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
17
17
|
function _ts_decorate(decorators, target, key, desc) {
|
|
18
18
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
19
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
20
|
-
|
|
21
|
-
else
|
|
22
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
23
|
-
if (d = decorators[i])
|
|
24
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
20
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
21
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
22
|
}
|
|
27
23
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -48,7 +44,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
48
44
|
* Works via batched iteration of the source archivist to populate the index.
|
|
49
45
|
* @returns A promise that resolves when the background process is complete
|
|
50
46
|
*/
|
|
51
|
-
backgroundDivine = async () => {
|
|
47
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
52
48
|
const lastState = await this.retrieveState();
|
|
53
49
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
54
50
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -63,7 +59,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
63
59
|
if (nextState) {
|
|
64
60
|
await this.commitState(nextState);
|
|
65
61
|
}
|
|
66
|
-
};
|
|
62
|
+
}, "backgroundDivine");
|
|
67
63
|
/**
|
|
68
64
|
* Commit the internal state of the Diviner process. This is similar
|
|
69
65
|
* to a transaction completion in a database and should only be called
|
|
@@ -72,8 +68,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
72
68
|
* @param nextState The state to commit
|
|
73
69
|
*/
|
|
74
70
|
async commitState(nextState) {
|
|
75
|
-
if (nextState.state.offset === this._lastState?.state.offset)
|
|
76
|
-
return;
|
|
71
|
+
if (nextState.state.offset === this._lastState?.state.offset) return;
|
|
77
72
|
this._lastState = nextState;
|
|
78
73
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
79
74
|
const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -144,8 +139,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
144
139
|
* preemptions, reboots, etc.
|
|
145
140
|
*/
|
|
146
141
|
async retrieveState() {
|
|
147
|
-
if (this._lastState)
|
|
148
|
-
return this._lastState;
|
|
142
|
+
if (this._lastState) return this._lastState;
|
|
149
143
|
let hash = "";
|
|
150
144
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
151
145
|
const query = await new PayloadBuilder({
|
|
@@ -206,8 +200,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
206
200
|
} catch (e) {
|
|
207
201
|
console.log(e);
|
|
208
202
|
} finally {
|
|
209
|
-
if (this._pollId)
|
|
210
|
-
clearTimeoutEx(this._pollId);
|
|
203
|
+
if (this._pollId) clearTimeoutEx(this._pollId);
|
|
211
204
|
this._pollId = void 0;
|
|
212
205
|
this.poll();
|
|
213
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
package/dist/neutral/index.cjs
CHANGED
|
@@ -40,12 +40,8 @@ var import_module_model = require("@xyo-network/module-model");
|
|
|
40
40
|
var import_payload_builder = require("@xyo-network/payload-builder");
|
|
41
41
|
function _ts_decorate(decorators, target, key, desc) {
|
|
42
42
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
43
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
44
|
-
|
|
45
|
-
else
|
|
46
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
47
|
-
if (d = decorators[i])
|
|
48
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
43
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
44
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
49
45
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
50
46
|
}
|
|
51
47
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -72,7 +68,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
72
68
|
* Works via batched iteration of the source archivist to populate the index.
|
|
73
69
|
* @returns A promise that resolves when the background process is complete
|
|
74
70
|
*/
|
|
75
|
-
backgroundDivine = async () => {
|
|
71
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
76
72
|
const lastState = await this.retrieveState();
|
|
77
73
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
78
74
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -87,7 +83,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
87
83
|
if (nextState) {
|
|
88
84
|
await this.commitState(nextState);
|
|
89
85
|
}
|
|
90
|
-
};
|
|
86
|
+
}, "backgroundDivine");
|
|
91
87
|
/**
|
|
92
88
|
* Commit the internal state of the Diviner process. This is similar
|
|
93
89
|
* to a transaction completion in a database and should only be called
|
|
@@ -96,8 +92,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
96
92
|
* @param nextState The state to commit
|
|
97
93
|
*/
|
|
98
94
|
async commitState(nextState) {
|
|
99
|
-
if (nextState.state.offset === this._lastState?.state.offset)
|
|
100
|
-
return;
|
|
95
|
+
if (nextState.state.offset === this._lastState?.state.offset) return;
|
|
101
96
|
this._lastState = nextState;
|
|
102
97
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
103
98
|
const [bw] = await new import_boundwitness_builder.BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -168,8 +163,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
168
163
|
* preemptions, reboots, etc.
|
|
169
164
|
*/
|
|
170
165
|
async retrieveState() {
|
|
171
|
-
if (this._lastState)
|
|
172
|
-
return this._lastState;
|
|
166
|
+
if (this._lastState) return this._lastState;
|
|
173
167
|
let hash = "";
|
|
174
168
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
175
169
|
const query = await new import_payload_builder.PayloadBuilder({
|
|
@@ -230,8 +224,7 @@ var IndexingDiviner = class extends import_diviner_abstract.AbstractDiviner {
|
|
|
230
224
|
} catch (e) {
|
|
231
225
|
console.log(e);
|
|
232
226
|
} finally {
|
|
233
|
-
if (this._pollId)
|
|
234
|
-
(0, import_timer.clearTimeoutEx)(this._pollId);
|
|
227
|
+
if (this._pollId) (0, import_timer.clearTimeoutEx)(this._pollId);
|
|
235
228
|
this._pollId = void 0;
|
|
236
229
|
this.poll();
|
|
237
230
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
package/dist/neutral/index.js
CHANGED
|
@@ -16,12 +16,8 @@ import { creatableModule, isModuleState, isModuleStateWithMeta, ModuleStateSchem
|
|
|
16
16
|
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
17
17
|
function _ts_decorate(decorators, target, key, desc) {
|
|
18
18
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
19
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
20
|
-
|
|
21
|
-
else
|
|
22
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
23
|
-
if (d = decorators[i])
|
|
24
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
20
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
21
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
22
|
}
|
|
27
23
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -48,7 +44,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
48
44
|
* Works via batched iteration of the source archivist to populate the index.
|
|
49
45
|
* @returns A promise that resolves when the background process is complete
|
|
50
46
|
*/
|
|
51
|
-
backgroundDivine = async () => {
|
|
47
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
52
48
|
const lastState = await this.retrieveState();
|
|
53
49
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
54
50
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -63,7 +59,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
63
59
|
if (nextState) {
|
|
64
60
|
await this.commitState(nextState);
|
|
65
61
|
}
|
|
66
|
-
};
|
|
62
|
+
}, "backgroundDivine");
|
|
67
63
|
/**
|
|
68
64
|
* Commit the internal state of the Diviner process. This is similar
|
|
69
65
|
* to a transaction completion in a database and should only be called
|
|
@@ -72,8 +68,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
72
68
|
* @param nextState The state to commit
|
|
73
69
|
*/
|
|
74
70
|
async commitState(nextState) {
|
|
75
|
-
if (nextState.state.offset === this._lastState?.state.offset)
|
|
76
|
-
return;
|
|
71
|
+
if (nextState.state.offset === this._lastState?.state.offset) return;
|
|
77
72
|
this._lastState = nextState;
|
|
78
73
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
79
74
|
const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -144,8 +139,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
144
139
|
* preemptions, reboots, etc.
|
|
145
140
|
*/
|
|
146
141
|
async retrieveState() {
|
|
147
|
-
if (this._lastState)
|
|
148
|
-
return this._lastState;
|
|
142
|
+
if (this._lastState) return this._lastState;
|
|
149
143
|
let hash = "";
|
|
150
144
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
151
145
|
const query = await new PayloadBuilder({
|
|
@@ -206,8 +200,7 @@ var IndexingDiviner = class extends AbstractDiviner {
|
|
|
206
200
|
} catch (e) {
|
|
207
201
|
console.log(e);
|
|
208
202
|
} finally {
|
|
209
|
-
if (this._pollId)
|
|
210
|
-
clearTimeoutEx(this._pollId);
|
|
203
|
+
if (this._pollId) clearTimeoutEx(this._pollId);
|
|
211
204
|
this._pollId = void 0;
|
|
212
205
|
this.poll();
|
|
213
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","creatableModule"]}
|
package/dist/node/index.cjs
CHANGED
|
@@ -20,10 +20,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
return to;
|
|
21
21
|
};
|
|
22
22
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
23
|
-
var __publicField = (obj, key, value) =>
|
|
24
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
25
|
-
return value;
|
|
26
|
-
};
|
|
23
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
27
24
|
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
28
25
|
|
|
29
26
|
// src/index.ts
|
|
@@ -48,12 +45,8 @@ var import_module_model = require("@xyo-network/module-model");
|
|
|
48
45
|
var import_payload_builder = require("@xyo-network/payload-builder");
|
|
49
46
|
function _ts_decorate(decorators, target, key, desc) {
|
|
50
47
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
51
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
52
|
-
|
|
53
|
-
else
|
|
54
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
55
|
-
if (d = decorators[i])
|
|
56
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
48
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
49
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
57
50
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
58
51
|
}
|
|
59
52
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -71,7 +64,7 @@ var _IndexingDiviner = class _IndexingDiviner extends import_diviner_abstract.Ab
|
|
|
71
64
|
* Works via batched iteration of the source archivist to populate the index.
|
|
72
65
|
* @returns A promise that resolves when the background process is complete
|
|
73
66
|
*/
|
|
74
|
-
backgroundDivine = async () => {
|
|
67
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
75
68
|
const lastState = await this.retrieveState();
|
|
76
69
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
77
70
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -86,7 +79,7 @@ var _IndexingDiviner = class _IndexingDiviner extends import_diviner_abstract.Ab
|
|
|
86
79
|
if (nextState) {
|
|
87
80
|
await this.commitState(nextState);
|
|
88
81
|
}
|
|
89
|
-
};
|
|
82
|
+
}, "backgroundDivine");
|
|
90
83
|
/**
|
|
91
84
|
* Commit the internal state of the Diviner process. This is similar
|
|
92
85
|
* to a transaction completion in a database and should only be called
|
|
@@ -96,8 +89,7 @@ var _IndexingDiviner = class _IndexingDiviner extends import_diviner_abstract.Ab
|
|
|
96
89
|
*/
|
|
97
90
|
async commitState(nextState) {
|
|
98
91
|
var _a;
|
|
99
|
-
if (nextState.state.offset === ((_a = this._lastState) == null ? void 0 : _a.state.offset))
|
|
100
|
-
return;
|
|
92
|
+
if (nextState.state.offset === ((_a = this._lastState) == null ? void 0 : _a.state.offset)) return;
|
|
101
93
|
this._lastState = nextState;
|
|
102
94
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
103
95
|
const [bw] = await new import_boundwitness_builder.BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -172,8 +164,7 @@ var _IndexingDiviner = class _IndexingDiviner extends import_diviner_abstract.Ab
|
|
|
172
164
|
* preemptions, reboots, etc.
|
|
173
165
|
*/
|
|
174
166
|
async retrieveState() {
|
|
175
|
-
if (this._lastState)
|
|
176
|
-
return this._lastState;
|
|
167
|
+
if (this._lastState) return this._lastState;
|
|
177
168
|
let hash = "";
|
|
178
169
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
179
170
|
const query = await new import_payload_builder.PayloadBuilder({
|
|
@@ -237,8 +228,7 @@ var _IndexingDiviner = class _IndexingDiviner extends import_diviner_abstract.Ab
|
|
|
237
228
|
} catch (e) {
|
|
238
229
|
console.log(e);
|
|
239
230
|
} finally {
|
|
240
|
-
if (this._pollId)
|
|
241
|
-
(0, import_timer.clearTimeoutEx)(this._pollId);
|
|
231
|
+
if (this._pollId) (0, import_timer.clearTimeoutEx)(this._pollId);
|
|
242
232
|
this._pollId = void 0;
|
|
243
233
|
this.poll();
|
|
244
234
|
}
|
package/dist/node/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["moduleName","IndexingDiviner","AbstractDiviner","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","creatableModule"]}
|
package/dist/node/index.js
CHANGED
|
@@ -3,10 +3,7 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
3
3
|
var __reflectGet = Reflect.get;
|
|
4
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
5
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
-
var __publicField = (obj, key, value) =>
|
|
7
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
-
return value;
|
|
9
|
-
};
|
|
6
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
10
7
|
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
11
8
|
|
|
12
9
|
// src/Diviner.ts
|
|
@@ -24,12 +21,8 @@ import { creatableModule, isModuleState, isModuleStateWithMeta, ModuleStateSchem
|
|
|
24
21
|
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
25
22
|
function _ts_decorate(decorators, target, key, desc) {
|
|
26
23
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
27
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
28
|
-
|
|
29
|
-
else
|
|
30
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
31
|
-
if (d = decorators[i])
|
|
32
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
24
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
25
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
33
26
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
34
27
|
}
|
|
35
28
|
__name(_ts_decorate, "_ts_decorate");
|
|
@@ -47,7 +40,7 @@ var _IndexingDiviner = class _IndexingDiviner extends AbstractDiviner {
|
|
|
47
40
|
* Works via batched iteration of the source archivist to populate the index.
|
|
48
41
|
* @returns A promise that resolves when the background process is complete
|
|
49
42
|
*/
|
|
50
|
-
backgroundDivine = async () => {
|
|
43
|
+
backgroundDivine = /* @__PURE__ */ __name(async () => {
|
|
51
44
|
const lastState = await this.retrieveState();
|
|
52
45
|
const indexCandidateDiviner = await this.getIndexingDivinerStage("stateToIndexCandidateDiviner");
|
|
53
46
|
const results = lastState ? await indexCandidateDiviner.divine([
|
|
@@ -62,7 +55,7 @@ var _IndexingDiviner = class _IndexingDiviner extends AbstractDiviner {
|
|
|
62
55
|
if (nextState) {
|
|
63
56
|
await this.commitState(nextState);
|
|
64
57
|
}
|
|
65
|
-
};
|
|
58
|
+
}, "backgroundDivine");
|
|
66
59
|
/**
|
|
67
60
|
* Commit the internal state of the Diviner process. This is similar
|
|
68
61
|
* to a transaction completion in a database and should only be called
|
|
@@ -72,8 +65,7 @@ var _IndexingDiviner = class _IndexingDiviner extends AbstractDiviner {
|
|
|
72
65
|
*/
|
|
73
66
|
async commitState(nextState) {
|
|
74
67
|
var _a;
|
|
75
|
-
if (nextState.state.offset === ((_a = this._lastState) == null ? void 0 : _a.state.offset))
|
|
76
|
-
return;
|
|
68
|
+
if (nextState.state.offset === ((_a = this._lastState) == null ? void 0 : _a.state.offset)) return;
|
|
77
69
|
this._lastState = nextState;
|
|
78
70
|
const archivist = await this.getArchivistForStore("stateStore");
|
|
79
71
|
const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build();
|
|
@@ -148,8 +140,7 @@ var _IndexingDiviner = class _IndexingDiviner extends AbstractDiviner {
|
|
|
148
140
|
* preemptions, reboots, etc.
|
|
149
141
|
*/
|
|
150
142
|
async retrieveState() {
|
|
151
|
-
if (this._lastState)
|
|
152
|
-
return this._lastState;
|
|
143
|
+
if (this._lastState) return this._lastState;
|
|
153
144
|
let hash = "";
|
|
154
145
|
const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
|
|
155
146
|
const query = await new PayloadBuilder({
|
|
@@ -213,8 +204,7 @@ var _IndexingDiviner = class _IndexingDiviner extends AbstractDiviner {
|
|
|
213
204
|
} catch (e) {
|
|
214
205
|
console.log(e);
|
|
215
206
|
} finally {
|
|
216
|
-
if (this._pollId)
|
|
217
|
-
clearTimeoutEx(this._pollId);
|
|
207
|
+
if (this._pollId) clearTimeoutEx(this._pollId);
|
|
218
208
|
this._pollId = void 0;
|
|
219
209
|
this.poll();
|
|
220
210
|
}
|
package/dist/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAASA,gBAAgB;AAEzB,SAASC,gBAAgBC,oBAAoB;AAC7C,SAASC,wBAAwB;AACjC,SAASC,2BAA2B;AACpC,SAASC,sBAAsB;AAC/B,SAASC,uBAAuB;AAChC,SAA0CC,sCAAsC;AAChF,SAEEC,mCAIK;AACP,SAASC,yBAAkE;AAC3E,SAASC,sBAAsB;AAC/B,SAASC,iBAAiBC,eAAeC,uBAAoCC,yBAAyB;AACtG,SAASC,sBAAsB;;;;;;;;;;;;AAO/B,IAAMC,aAAa;AAGZ,IAAMC,mBAAN,MAAMA,yBASHC,gBAAAA;EAKAC;EACAC;EAER,IAAIC,sBAAsB;AACxB,WAAO,KAAKC,OAAOD,uBAAuB;EAC5C;EAEA,IAAIE,gBAAgB;AAClB,WAAO,KAAKD,OAAOC,iBAAiB;EACtC;;;;;EAMUC,mBAAmB,YAAA;AAE3B,UAAMC,YAAY,MAAM,KAAKC,cAAa;AAE1C,UAAMC,wBAAwB,MAAM,KAAKC,wBAAwB,8BAAA;AACjE,UAAMC,UAAUJ,YAAY,MAAME,sBAAsBG,OAAO;MAACL;KAAU,IAAI,MAAME,sBAAsBG,OAAM;AAEhH,UAAMC,YAAYF,QAAQG,KAAKC,qBAAAA;AAC/B,UAAMC,kBAAkBL,QAAQM,OAAO,CAACC,MAAM,CAACH,sBAAsBG,CAAAA,CAAAA;AAErE,UAAMC,0BAA0B,MAAM,KAAKT,wBAAwB,8BAAA;AACnE,UAAMU,UAAU,MAAMD,wBAAwBP,OAAOI,eAAAA;AAErD,UAAMK,iBAAiB,MAAM,KAAKC,qBAAqB,YAAA;AACvD,UAAMD,eAAeE,OAAOH,OAAAA;AAE5B,QAAIP,WAAW;AACb,YAAM,KAAKW,YAAYX,SAAAA;IACzB;EACF;;;;;;;;EASA,MAAgBW,YAAYX,WAA8C;;AAExE,QAAIA,UAAUY,MAAMC,aAAW,UAAKzB,eAAL,mBAAiBwB,MAAMC;AAAQ;AAC9D,SAAKzB,aAAaY;AAClB,UAAMc,YAAY,MAAM,KAAKL,qBAAqB,YAAA;AAClD,UAAM,CAACM,EAAAA,IAAM,MAAM,IAAIC,oBAAAA,EAAsBC,QAAQjB,SAAAA,EAAWkB,OAAO,KAAKC,OAAO,EAAEC,MAAK;AAC1F,UAAMN,UAAUJ,OAAO;MAACK;MAAIf;KAAU;EACxC;EAEA,MAAyBqB,cAAcC,WAAkB,CAAA,GAA+B;AACtF,UAAMC,sBAAsB,MAAM,KAAKC,0BAA0B,YAAA;AACjE,UAAMC,kCAAkC,MAAM,KAAK5B,wBAAwB,iCAAA;AAC3E,UAAM6B,kDAAkD,MAAM,KAAK7B,wBAAwB,iDAAA;AAC3F,UAAMC,WACJ,MAAM6B,QAAQC,IACZN,SAASO,IAAI,OAAOZ,YAAAA;AAClB,YAAMa,aAAa,MAAML,gCAAgC1B,OAAO;QAACkB;OAAQ;AAEzE,YAAMc,iBAAiB,MAAMR,oBAAoBxB,OAAO+B,UAAAA;AAExD,YAAME,WAAW,MAAML,QAAQC,IAC7BG,eAAeE,KAAI,EAAGJ,IAAI,CAACK,kBAAkBR,gDAAgD3B,OAAO;QAACkB;QAASiB;OAAc,CAAA,CAAA;AAE9H,aAAOF,SAASC,KAAI;IACtB,CAAA,CAAA,GAEFA,KAAI;AAEN,WAAQ,MAAMN,QAAQC,IAAI9B,QAAQ+B,IAAI,CAACM,WAAWC,eAAehB,MAAMe,MAAAA,CAAAA,CAAAA;EACzE;;;;;;EAOA,MAAgB1B,qBAAqB4B,OAAoB;;AACvD,UAAMC,OAAOC,UAAS,gBAAKhD,WAAL,mBAAc8C,WAAd,mBAAsBvB,WAAW,MAAM,GAAG7B,UAAAA,gBAA0BoD,KAAAA,0BAA+B;AACzH,UAAMG,MAAMD,SAAS,MAAM,KAAKE,QAAQH,IAAAA,GAAO,MAAM,GAAGrD,UAAAA,uBAAiCoD,KAAAA,eAAoBC,IAAAA,GAAO;AACpH,WAAOI,iBAAiBC,KAAKH,KAAK,KAAKrB,OAAO;EAChD;;;;;;EAOA,MAAgByB,+BAA+BP,OAAoB;;AACjE,UAAMC,OAAOC,UAAS,gBAAKhD,WAAL,mBAAc8C,WAAd,mBAAsBQ,qBAAqB,MAAM,GAAG5D,UAAAA,gBAA0BoD,KAAAA,oCAAyC;AAC7I,UAAMG,MAAMD,SAAS,MAAM,KAAKE,QAAQH,IAAAA,GAAO,MAAM,GAAGrD,UAAAA,uBAAiCoD,KAAAA,yBAA8BC,IAAAA,GAAO;AAC9H,WAAOQ,eAAeH,KAAKH,KAAK,KAAKrB,OAAO;EAC9C;;;;;;EAOA,MAAgBtB,wBAAwBkD,WAAiC;;AACvE,UAAMC,gBAAgBT,UACpB,gBAAKhD,WAAL,mBAAa0D,0BAAb,mBAAqCF,YACrC,MAAM,GAAG9D,UAAAA,sCAAgD8D,SAAAA,gBAAyB;AAEpF,UAAMP,MAAM,MAAM,KAAKC,QAAQO,aAAAA;AAC/B,WAAOT,SAASW,kBAAkBV,GAAAA,GAAM,MAAM,GAAGvD,UAAAA,kDAA4D8D,SAAAA,EAAW;EAC1H;;;;;;EAOA,MAAgBvB,0BAA0Ba,OAAoB;;AAC5D,UAAMC,OAAOC,UAAS,gBAAKhD,WAAL,mBAAc8C,WAAd,mBAAsBc,gBAAgB,MAAM,GAAGlE,UAAAA,gBAA0BoD,KAAAA,+BAAoC;AACnI,UAAMG,MAAMD,SAAS,MAAM,KAAKE,QAAQH,IAAAA,GAAO,MAAM,GAAGrD,UAAAA,uBAAiCoD,KAAAA,oBAAyBC,IAAAA,GAAO;AACzH,WAAOQ,eAAeH,KAAKH,KAAK,KAAKrB,OAAO;EAC9C;;;;;EAMA,MAAgBxB,gBAAwE;AACtF,QAAI,KAAKP;AAAY,aAAO,KAAKA;AACjC,QAAIgE,OAAa;AACjB,UAAMC,UAAU,MAAM,KAAKT,+BAA+B,YAAA;AAC1D,UAAMU,QAAQ,MAAM,IAAIlB,eAAgD;MAAEmB,QAAQC;IAA+B,CAAA,EAC9GC,OAAO;MACNC,SAAS,KAAKvC,QAAQuC;MACtBC,OAAO;MACP9C,QAAQ;MACR+C,OAAO;MACPC,iBAAiB;QAACC;;IACpB,CAAA,EACC1C,MAAK;AACR,UAAM2C,iBAAiB,MAAMV,QAAQtD,OAAO;MAACuD;KAAM;AACnD,QAAIS,eAAeC,SAAS,GAAG;AAC7B,YAAMC,eAAeF,eAAe,CAAA;AACpC,UAAIG,eAAeD,YAAAA,GAAe;AAEhCb,eAAOa,aAAaE,UACjBtC,IAAI,CAAC6B,SAASU,WAAW;UAAEV;UAASU;QAAM,EAAA,EAC1ChE,OAAO,CAAC,EAAEsD,QAAO,MAAOA,YAAY,KAAKvC,QAAQuC,OAAO,EAExDW,OACC,CAACC,MAAMC,SAAAA;;AAAUN,qCAAaJ,oBAAbI,mBAA+BM,6BAAMH,YAAWN,oBAAoBG,aAAaO,eAAeD,6BAAMH,KAAAA,IAASE;WAChI,EAAA;MAEN;IACF;AAGA,QAAIlB,SAAS,IAAI;AAEf,YAAMtC,YAAY,MAAM,KAAKL,qBAAqB,YAAA;AAClD,YAAMQ,WAAW,MAAMH,UAAU2D,IAAI;QAACrB;OAAK,GAAGnD,KAAKyE,aAAAA;AACnD,UAAIzD,SAAS;AACX,eAAOA;MACT;IACF;AACA,WAAO0D;EACT;EAEA,MAAyBC,eAAiC;AACxD,UAAM,MAAMA,aAAAA;AACZ,SAAKC,KAAI;AACT,WAAO;EACT;EAEA,MAAyBC,YAAYC,UAAiD;AACpF,QAAI,KAAK1F,SAAS;AAChB2F,mBAAa,KAAK3F,OAAO;AACzB,WAAKA,UAAUsF;IACjB;AACA,WAAO,MAAM,MAAMG,YAAAA;EACrB;;;;;EAMQD,OAAO;AACb,SAAKxF,UAAU4F,aAAa,YAAA;AAC1B,UAAI;AACF,cAAMtD,QAAQc,QAAO;AACrB,cAAM,KAAKhD,iBAAgB;MAC7B,SAASyF,GAAG;AACVC,gBAAQC,IAAIF,CAAAA;MACd,UAAA;AACE,YAAI,KAAK7F;AAASgG,yBAAe,KAAKhG,OAAO;AAC7C,aAAKA,UAAUsF;AACf,aAAKE,KAAI;MACX;IACF,GAAG,KAAKrF,aAAa;EACvB;AACF;AA3MUL;AACR,cAVWD,kBAUcoG,sBAAqB;AAC9C,cAXWpG,kBAWcqG,iBAA0B;KAAI,+CAAMA;EAAeC;;AAC5E,cAZWtG,kBAYcuG,uBAA8BD;AAZlD,IAAMtG,kBAAN;AAAMA,kBAAAA,aAAAA;EADZwG,gBAAAA;GACYxG,eAAAA;","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","creatableModule"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { Hash } from '@xylabs/hex'\nimport { clearTimeoutEx, setTimeoutEx } from '@xylabs/timer'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { BoundWitnessBuilder } from '@xyo-network/boundwitness-builder'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport {\n IndexingDivinerConfig,\n IndexingDivinerConfigSchema,\n IndexingDivinerParams,\n IndexingDivinerStage,\n IndexingDivinerState,\n} from '@xyo-network/diviner-indexing-model'\nimport { asDivinerInstance, DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { creatableModule, isModuleState, isModuleStateWithMeta, ModuleState, ModuleStateSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema, WithMeta } from '@xyo-network/payload-model'\n\nexport type ConfigStoreKey = 'indexStore' | 'stateStore'\n\nexport type ConfigStore = Extract<keyof IndexingDivinerConfig, ConfigStoreKey>\n\nconst moduleName = 'IndexingDiviner'\n\n@creatableModule<IndexingDiviner>()\nexport class IndexingDiviner<\n TParams extends IndexingDivinerParams = IndexingDivinerParams,\n TIn extends Payload = Payload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly allowRandomAccount = false\n static override readonly configSchemas: Schema[] = [...super.configSchemas, IndexingDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = IndexingDivinerConfigSchema\n\n private _lastState?: ModuleState<IndexingDivinerState>\n private _pollId?: string\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n /**\n * Works via batched iteration of the source archivist to populate the index.\n * @returns A promise that resolves when the background process is complete\n */\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = await this.retrieveState()\n // Get next batch of results\n const indexCandidateDiviner = await this.getIndexingDivinerStage('stateToIndexCandidateDiviner')\n const results = lastState ? await indexCandidateDiviner.divine([lastState]) : await indexCandidateDiviner.divine()\n // Filter next state out from results\n const nextState = results.find(isModuleStateWithMeta<IndexingDivinerState>)\n const indexCandidates = results.filter((x) => !isModuleStateWithMeta(x))\n // Transform candidates to indexes\n const toIndexTransformDiviner = await this.getIndexingDivinerStage('indexCandidateToIndexDiviner')\n const indexes = await toIndexTransformDiviner.divine(indexCandidates)\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexes)\n // Update state\n if (nextState) {\n await this.commitState(nextState)\n }\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n * @param nextState The state to commit\n */\n protected async commitState(nextState: ModuleState<IndexingDivinerState>) {\n // Don't commit state if no state has changed\n if (nextState.state.offset === this._lastState?.state.offset) return\n this._lastState = nextState\n const archivist = await this.getArchivistForStore('stateStore')\n const [bw] = await new BoundWitnessBuilder().payload(nextState).signer(this.account).build()\n await archivist.insert([bw, nextState])\n }\n\n protected override async divineHandler(payloads: TIn[] = []): Promise<WithMeta<TOut>[]> {\n const indexPayloadDiviner = await this.getPayloadDivinerForStore('indexStore')\n const divinerQueryToIndexQueryDiviner = await this.getIndexingDivinerStage('divinerQueryToIndexQueryDiviner')\n const indexQueryResponseToDivinerQueryResponseDiviner = await this.getIndexingDivinerStage('indexQueryResponseToDivinerQueryResponseDiviner')\n const results = (\n await Promise.all(\n payloads.map(async (payload) => {\n const indexQuery = await divinerQueryToIndexQueryDiviner.divine([payload])\n // Divine the results\n const indexedResults = await indexPayloadDiviner.divine(indexQuery)\n // Transform the results to the response shape\n const response = await Promise.all(\n indexedResults.flat().map((indexedResult) => indexQueryResponseToDivinerQueryResponseDiviner.divine([payload, indexedResult])),\n )\n return response.flat()\n }),\n )\n ).flat()\n // TODO: Infer this type over casting to this type\n return (await Promise.all(results.map((result) => PayloadBuilder.build(result)))) as WithMeta<TOut>[]\n }\n\n /**\n * Retrieves the archivist for the specified store\n * @param store The store to retrieve the archivist for\n * @returns The archivist for the specified store\n */\n protected async getArchivistForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist [${name}]`)\n return ArchivistWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the BoundWitness Diviner for the specified store\n * @param store The store to retrieve the BoundWitness Diviner for\n * @returns The BoundWitness Diviner for the specified store\n */\n protected async getBoundWitnessDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Gets the Diviner for the supplied Indexing Diviner stage\n * @param transform The Indexing Diviner stage\n * @returns The diviner corresponding to the Indexing Diviner stage\n */\n protected async getIndexingDivinerStage(transform: IndexingDivinerStage) {\n const nameOrAddress = assertEx(\n this.config?.indexingDivinerStages?.[transform],\n () => `${moduleName}: Config for indexingDivinerStages.${transform} not specified`,\n )\n const mod = await this.resolve(nameOrAddress)\n return assertEx(asDivinerInstance(mod), () => `${moduleName}: Failed to resolve indexing diviner stage for ${transform}`) as DivinerInstance\n }\n\n /**\n * Retrieves the Payload Diviner for the specified store\n * @param store The store to retrieve the Payload Diviner for\n * @returns The Payload Diviner for the specified store\n */\n protected async getPayloadDivinerForStore(store: ConfigStore) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner [${name}]`)\n return DivinerWrapper.wrap(mod, this.account)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ModuleState<IndexingDivinerState> | undefined> {\n if (this._lastState) return this._lastState\n let hash: Hash = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = await new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema })\n .fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n .build()\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n // eslint-disable-next-line unicorn/no-array-reduce\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '' as Hash,\n )\n }\n }\n\n // If we able to located the last state\n if (hash !== '') {\n // Get last state\n const archivist = await this.getArchivistForStore('stateStore')\n const payload = (await archivist.get([hash])).find(isModuleState<IndexingDivinerState>)\n if (payload) {\n return payload as WithMeta<ModuleState<IndexingDivinerState>>\n }\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n /**\n * Runs the background divine process on a loop with a delay\n * specified by the `config.pollFrequency`\n */\n private poll() {\n this._pollId = setTimeoutEx(async () => {\n try {\n await Promise.resolve()\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeoutEx(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n"],"mappings":"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","names":["assertEx","clearTimeoutEx","setTimeoutEx","ArchivistWrapper","BoundWitnessBuilder","isBoundWitness","AbstractDiviner","BoundWitnessDivinerQuerySchema","IndexingDivinerConfigSchema","asDivinerInstance","DivinerWrapper","creatableModule","isModuleState","isModuleStateWithMeta","ModuleStateSchema","PayloadBuilder","moduleName","IndexingDiviner","AbstractDiviner","_lastState","_pollId","payloadDivinerLimit","config","pollFrequency","backgroundDivine","lastState","retrieveState","indexCandidateDiviner","getIndexingDivinerStage","results","divine","nextState","find","isModuleStateWithMeta","indexCandidates","filter","x","toIndexTransformDiviner","indexes","indexArchivist","getArchivistForStore","insert","commitState","state","offset","archivist","bw","BoundWitnessBuilder","payload","signer","account","build","divineHandler","payloads","indexPayloadDiviner","getPayloadDivinerForStore","divinerQueryToIndexQueryDiviner","indexQueryResponseToDivinerQueryResponseDiviner","Promise","all","map","indexQuery","indexedResults","response","flat","indexedResult","result","PayloadBuilder","store","name","assertEx","mod","resolve","ArchivistWrapper","wrap","getBoundWitnessDivinerForStore","boundWitnessDiviner","DivinerWrapper","transform","nameOrAddress","indexingDivinerStages","asDivinerInstance","payloadDiviner","hash","diviner","query","schema","BoundWitnessDivinerQuerySchema","fields","address","limit","order","payload_schemas","ModuleStateSchema","boundWitnesses","length","boundWitness","isBoundWitness","addresses","index","reduce","prev","curr","payload_hashes","get","isModuleState","undefined","startHandler","poll","stopHandler","_timeout","clearTimeout","setTimeoutEx","e","console","log","clearTimeoutEx","allowRandomAccount","configSchemas","IndexingDivinerConfigSchema","defaultConfigSchema","creatableModule"]}
|
package/package.json
CHANGED
|
@@ -13,21 +13,21 @@
|
|
|
13
13
|
"@xylabs/assert": "^3.5.1",
|
|
14
14
|
"@xylabs/hex": "^3.5.1",
|
|
15
15
|
"@xylabs/timer": "^3.5.1",
|
|
16
|
-
"@xyo-network/archivist-wrapper": "~2.104.
|
|
17
|
-
"@xyo-network/boundwitness-builder": "~2.104.
|
|
18
|
-
"@xyo-network/boundwitness-model": "~2.104.
|
|
19
|
-
"@xyo-network/diviner-abstract": "~2.104.
|
|
20
|
-
"@xyo-network/diviner-boundwitness-model": "~2.104.
|
|
21
|
-
"@xyo-network/diviner-indexing-model": "~2.104.
|
|
22
|
-
"@xyo-network/diviner-model": "~2.104.
|
|
23
|
-
"@xyo-network/diviner-wrapper": "~2.104.
|
|
24
|
-
"@xyo-network/module-model": "~2.104.
|
|
25
|
-
"@xyo-network/payload-builder": "~2.104.
|
|
26
|
-
"@xyo-network/payload-model": "~2.104.
|
|
16
|
+
"@xyo-network/archivist-wrapper": "~2.104.1",
|
|
17
|
+
"@xyo-network/boundwitness-builder": "~2.104.1",
|
|
18
|
+
"@xyo-network/boundwitness-model": "~2.104.1",
|
|
19
|
+
"@xyo-network/diviner-abstract": "~2.104.1",
|
|
20
|
+
"@xyo-network/diviner-boundwitness-model": "~2.104.1",
|
|
21
|
+
"@xyo-network/diviner-indexing-model": "~2.104.1",
|
|
22
|
+
"@xyo-network/diviner-model": "~2.104.1",
|
|
23
|
+
"@xyo-network/diviner-wrapper": "~2.104.1",
|
|
24
|
+
"@xyo-network/module-model": "~2.104.1",
|
|
25
|
+
"@xyo-network/payload-builder": "~2.104.1",
|
|
26
|
+
"@xyo-network/payload-model": "~2.104.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@xylabs/ts-scripts-yarn3": "^3.
|
|
30
|
-
"@xylabs/tsconfig": "^3.
|
|
29
|
+
"@xylabs/ts-scripts-yarn3": "^3.11.2",
|
|
30
|
+
"@xylabs/tsconfig": "^3.11.2",
|
|
31
31
|
"typescript": "^5.4.5"
|
|
32
32
|
},
|
|
33
33
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
@@ -69,6 +69,6 @@
|
|
|
69
69
|
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
|
|
70
70
|
},
|
|
71
71
|
"sideEffects": false,
|
|
72
|
-
"version": "2.104.
|
|
72
|
+
"version": "2.104.1",
|
|
73
73
|
"type": "module"
|
|
74
74
|
}
|