@xyo-network/archivist-memory 3.18.10 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/neutral/index.mjs +55 -70
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/types/Archivist.d.ts +7 -31
- package/dist/types/Archivist.d.ts.map +1 -1
- package/dist/types/MemoryDriver.d.ts +35 -0
- package/dist/types/MemoryDriver.d.ts.map +1 -0
- package/package.json +26 -24
- package/src/Archivist.ts +13 -165
- package/src/MemoryDriver.ts +140 -0
package/dist/neutral/index.mjs
CHANGED
|
@@ -15,55 +15,45 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
15
15
|
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
16
16
|
|
|
17
17
|
// src/Archivist.ts
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
hexToBigInt
|
|
22
|
-
} from "@xylabs/hex";
|
|
23
|
-
import {
|
|
24
|
-
fulfilled
|
|
25
|
-
} from "@xylabs/promise";
|
|
26
|
-
import { isDefined } from "@xylabs/typeof";
|
|
27
|
-
import { Account } from "@xyo-network/account";
|
|
28
|
-
import { AbstractArchivist, StorageClassLabel } from "@xyo-network/archivist-abstract";
|
|
18
|
+
import { StorageClassLabel } from "@xyo-network/archivist-abstract";
|
|
19
|
+
import { GenericArchivist } from "@xyo-network/archivist-generic";
|
|
29
20
|
import {
|
|
30
21
|
ArchivistAllQuerySchema,
|
|
31
22
|
ArchivistClearQuerySchema,
|
|
32
23
|
ArchivistCommitQuerySchema,
|
|
33
24
|
ArchivistDeleteQuerySchema,
|
|
34
25
|
ArchivistInsertQuerySchema,
|
|
35
|
-
ArchivistNextQuerySchema
|
|
36
|
-
ArchivistSnapshotPayloadSchema
|
|
26
|
+
ArchivistNextQuerySchema
|
|
37
27
|
} from "@xyo-network/archivist-model";
|
|
38
28
|
import {
|
|
39
29
|
creatableModule
|
|
40
30
|
} from "@xyo-network/module-model";
|
|
41
|
-
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
42
|
-
import { LRUCache } from "lru-cache";
|
|
43
31
|
|
|
44
32
|
// src/Config.ts
|
|
45
33
|
var MemoryArchivistConfigSchema = "network.xyo.archivist.memory.config";
|
|
46
34
|
|
|
47
|
-
// src/
|
|
48
|
-
|
|
35
|
+
// src/MemoryDriver.ts
|
|
36
|
+
import { assertEx } from "@xylabs/assert";
|
|
37
|
+
import {
|
|
38
|
+
AbstractCreatable,
|
|
39
|
+
creatable
|
|
40
|
+
} from "@xylabs/creatable";
|
|
41
|
+
import { exists } from "@xylabs/exists";
|
|
42
|
+
import { isDefined } from "@xylabs/typeof";
|
|
43
|
+
import { PayloadBuilder } from "@xyo-network/payload-builder";
|
|
44
|
+
import { LRUCache } from "lru-cache";
|
|
45
|
+
var MemoryDriver = class extends AbstractCreatable {
|
|
49
46
|
_cache;
|
|
47
|
+
_config;
|
|
50
48
|
_dataHashIndex;
|
|
51
49
|
_sequenceIndex = [];
|
|
52
|
-
get queries() {
|
|
53
|
-
return [
|
|
54
|
-
ArchivistAllQuerySchema,
|
|
55
|
-
ArchivistDeleteQuerySchema,
|
|
56
|
-
ArchivistClearQuerySchema,
|
|
57
|
-
ArchivistInsertQuerySchema,
|
|
58
|
-
ArchivistCommitQuerySchema,
|
|
59
|
-
ArchivistNextQuerySchema,
|
|
60
|
-
...super.queries
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
50
|
get cache() {
|
|
64
51
|
this._cache = this._cache ?? new LRUCache({ max: this.max });
|
|
65
52
|
return this._cache;
|
|
66
53
|
}
|
|
54
|
+
get config() {
|
|
55
|
+
return assertEx(this._config, () => "Driver config is not set");
|
|
56
|
+
}
|
|
67
57
|
get dataHashIndex() {
|
|
68
58
|
this._dataHashIndex = this._dataHashIndex ?? new LRUCache({ max: this.max });
|
|
69
59
|
return this._dataHashIndex;
|
|
@@ -78,33 +68,21 @@ var MemoryArchivist = class extends AbstractArchivist {
|
|
|
78
68
|
}
|
|
79
69
|
return index;
|
|
80
70
|
}
|
|
81
|
-
|
|
82
|
-
const archivist = await MemoryArchivist.create({ account: account ?? await Account.random() });
|
|
83
|
-
await archivist.insert(payloads);
|
|
84
|
-
return archivist;
|
|
85
|
-
}
|
|
86
|
-
allHandler() {
|
|
71
|
+
all() {
|
|
87
72
|
return [...this.cache.values()].filter(exists).toSorted(PayloadBuilder.compareStorageMeta);
|
|
88
73
|
}
|
|
89
|
-
|
|
74
|
+
clear() {
|
|
90
75
|
this.cache.clear();
|
|
91
76
|
this.rebuildDataHashIndex();
|
|
92
77
|
this.rebuildDataHashIndex();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return (await parent?.query(query[0], query[1]))?.[0];
|
|
102
|
-
}).filter(exists)
|
|
103
|
-
);
|
|
104
|
-
await this.clearHandler();
|
|
105
|
-
return settled.filter(fulfilled).map((result) => result.value).filter(exists);
|
|
106
|
-
}
|
|
107
|
-
async deleteHandler(hashes) {
|
|
78
|
+
}
|
|
79
|
+
count() {
|
|
80
|
+
return this.cache.size;
|
|
81
|
+
}
|
|
82
|
+
createHandler() {
|
|
83
|
+
this._config = this.params.config ?? {};
|
|
84
|
+
}
|
|
85
|
+
async delete(hashes) {
|
|
108
86
|
const deletedPayloads = (await Promise.all(this.cache.dump().map(async ([key, item]) => {
|
|
109
87
|
const itemValueDataHash = await PayloadBuilder.dataHash(item.value);
|
|
110
88
|
if (hashes.includes(key) || hashes.includes(itemValueDataHash)) {
|
|
@@ -116,7 +94,7 @@ var MemoryArchivist = class extends AbstractArchivist {
|
|
|
116
94
|
await this.rebuildSequenceIndex();
|
|
117
95
|
return deletedPayloads;
|
|
118
96
|
}
|
|
119
|
-
|
|
97
|
+
get(hashes) {
|
|
120
98
|
return hashes.map((hash) => {
|
|
121
99
|
const resolvedHash = this.dataHashIndex.get(hash) ?? hash;
|
|
122
100
|
const result = this.cache.get(resolvedHash);
|
|
@@ -126,14 +104,14 @@ var MemoryArchivist = class extends AbstractArchivist {
|
|
|
126
104
|
return result;
|
|
127
105
|
}).filter(exists);
|
|
128
106
|
}
|
|
129
|
-
|
|
107
|
+
insert(payloads) {
|
|
130
108
|
const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta);
|
|
131
109
|
this._sequenceIndex.push(...payloadsWithMeta);
|
|
132
110
|
return payloadsWithMeta.map((payload) => {
|
|
133
111
|
return this.insertPayloadIntoCache(payload);
|
|
134
112
|
});
|
|
135
113
|
}
|
|
136
|
-
|
|
114
|
+
next(options) {
|
|
137
115
|
const {
|
|
138
116
|
limit = 100,
|
|
139
117
|
cursor,
|
|
@@ -144,24 +122,9 @@ var MemoryArchivist = class extends AbstractArchivist {
|
|
|
144
122
|
if (order === "desc") {
|
|
145
123
|
all = all.toReversed();
|
|
146
124
|
}
|
|
147
|
-
const startIndex = isDefined(cursor) ?
|
|
125
|
+
const startIndex = isDefined(cursor) ? MemoryDriver.findIndexFromCursor(all, cursor) + (open ? 1 : 0) : 0;
|
|
148
126
|
return all.slice(startIndex, startIndex + limit);
|
|
149
127
|
}
|
|
150
|
-
payloadCountHandler() {
|
|
151
|
-
return this.cache.size;
|
|
152
|
-
}
|
|
153
|
-
snapshotHandler() {
|
|
154
|
-
return [{
|
|
155
|
-
hash: Object.fromEntries(
|
|
156
|
-
[...this.cache.entries()].toSorted(([, payloadA], [, payloadB]) => {
|
|
157
|
-
const diff = hexToBigInt(payloadA._sequence) - hexToBigInt(payloadB._sequence);
|
|
158
|
-
return diff > 0n ? 1 : diff < 0n ? -1 : 0;
|
|
159
|
-
})
|
|
160
|
-
),
|
|
161
|
-
dataHash: Object.fromEntries(this.dataHashIndex.entries()),
|
|
162
|
-
schema: ArchivistSnapshotPayloadSchema
|
|
163
|
-
}];
|
|
164
|
-
}
|
|
165
128
|
insertPayloadIntoCache(payload) {
|
|
166
129
|
this.cache.set(payload._hash, payload);
|
|
167
130
|
this.dataHashIndex.set(payload._dataHash, payload._hash);
|
|
@@ -175,7 +138,29 @@ var MemoryArchivist = class extends AbstractArchivist {
|
|
|
175
138
|
}
|
|
176
139
|
}
|
|
177
140
|
async rebuildSequenceIndex() {
|
|
178
|
-
this._sequenceIndex = (await this.
|
|
141
|
+
this._sequenceIndex = (await this.all()).toSorted(PayloadBuilder.compareStorageMeta);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
MemoryDriver = __decorateClass([
|
|
145
|
+
creatable()
|
|
146
|
+
], MemoryDriver);
|
|
147
|
+
|
|
148
|
+
// src/Archivist.ts
|
|
149
|
+
var MemoryArchivist = class extends GenericArchivist {
|
|
150
|
+
get queries() {
|
|
151
|
+
return [
|
|
152
|
+
ArchivistAllQuerySchema,
|
|
153
|
+
ArchivistDeleteQuerySchema,
|
|
154
|
+
ArchivistClearQuerySchema,
|
|
155
|
+
ArchivistInsertQuerySchema,
|
|
156
|
+
ArchivistCommitQuerySchema,
|
|
157
|
+
ArchivistNextQuerySchema,
|
|
158
|
+
...super.queries
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
static async paramsHandler(inParams) {
|
|
162
|
+
const superParams = await super.paramsHandler(inParams);
|
|
163
|
+
return { ...superParams, driver: superParams.driver ?? await MemoryDriver.create(superParams) };
|
|
179
164
|
}
|
|
180
165
|
};
|
|
181
166
|
__publicField(MemoryArchivist, "configSchemas", [...__superGet(MemoryArchivist, MemoryArchivist, "configSchemas"), MemoryArchivistConfigSchema]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Archivist.ts","../../src/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport {\n Hash, Hex, hexToBigInt,\n} from '@xylabs/hex'\nimport {\n fulfilled, Promisable, PromisableArray,\n} from '@xylabs/promise'\nimport { isDefined } from '@xylabs/typeof'\nimport { Account } from '@xyo-network/account'\nimport { AccountInstance } from '@xyo-network/account-model'\nimport { AbstractArchivist, StorageClassLabel } from '@xyo-network/archivist-abstract'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistCommitQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuery,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n ArchivistNextOptions,\n ArchivistNextQuerySchema,\n ArchivistParams,\n ArchivistSnapshotPayload,\n ArchivistSnapshotPayloadSchema,\n AttachableArchivistInstance,\n} from '@xyo-network/archivist-model'\nimport { BoundWitness } from '@xyo-network/boundwitness-model'\nimport {\n AnyConfigSchema, creatableModule, ModuleInstance,\n} from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport {\n Payload, Schema, WithStorageMeta,\n} from '@xyo-network/payload-model'\nimport { LRUCache } from 'lru-cache'\n\nimport { MemoryArchivistConfig, MemoryArchivistConfigSchema } from './Config.ts'\n\nexport type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>> =\n ArchivistParams<TConfig>\n@creatableModule()\nexport class MemoryArchivist<\n TParams extends MemoryArchivistParams<AnyConfigSchema<MemoryArchivistConfig>> = MemoryArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n>\n extends AbstractArchivist<TParams, TEventData>\n implements AttachableArchivistInstance, ModuleInstance {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, MemoryArchivistConfigSchema]\n static override readonly defaultConfigSchema: Schema = MemoryArchivistConfigSchema\n static override readonly labels = { ...super.labels, [StorageClassLabel]: 'memory' }\n\n private _cache?: LRUCache<Hash, WithStorageMeta<Payload>>\n private _dataHashIndex?: LRUCache<Hash, Hash>\n private _sequenceIndex: WithStorageMeta<Payload>[] = []\n\n override get queries() {\n return [\n ArchivistAllQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistCommitQuerySchema,\n ArchivistNextQuerySchema,\n ...super.queries,\n ]\n }\n\n protected get cache() {\n this._cache = this._cache ?? new LRUCache<Hash, WithStorageMeta<Payload>>({ max: this.max })\n return this._cache\n }\n\n protected get dataHashIndex() {\n this._dataHashIndex = this._dataHashIndex ?? new LRUCache<Hash, Hash>({ max: this.max })\n return this._dataHashIndex\n }\n\n protected get max() {\n return this.config?.max ?? 10_000\n }\n\n private static findIndexFromCursor(payloads: WithStorageMeta[], cursor: Hex) {\n const index = payloads.findIndex(({ _sequence }) => _sequence === cursor)\n if (index === -1) {\n return Infinity // move to the end\n }\n return index\n }\n\n async from(payloads: Payload[], account?: AccountInstance): Promise<MemoryArchivist> {\n const archivist = await MemoryArchivist.create({ account: account ?? await Account.random() })\n await archivist.insert(payloads)\n return archivist\n }\n\n protected override allHandler(): Promisable<WithStorageMeta<Payload>[]> {\n return [...this.cache.values()].filter(exists).toSorted(PayloadBuilder.compareStorageMeta)\n }\n\n protected override clearHandler(): void | Promise<void> {\n this.cache.clear()\n this.rebuildDataHashIndex()\n this.rebuildDataHashIndex()\n return this.emit('cleared', { mod: this })\n }\n\n protected override async commitHandler(): Promise<BoundWitness[]> {\n const payloads = assertEx(await this.allHandler(), () => 'Nothing to commit')\n const settled = await Promise.allSettled(\n Object.values((await this.parentArchivists()).commit ?? [])?.map(async (parent) => {\n const queryPayload: ArchivistInsertQuery = { schema: ArchivistInsertQuerySchema }\n const query = await this.bindQuery(queryPayload, payloads)\n return (await parent?.query(query[0], query[1]))?.[0]\n }).filter(exists),\n )\n await this.clearHandler()\n return settled.filter(fulfilled).map(result => result.value).filter(exists)\n }\n\n protected override async deleteHandler(hashes: Hash[]): Promise<WithStorageMeta[]> {\n const deletedPayloads: WithStorageMeta<Payload>[] = (await Promise.all(this.cache\n .dump()\n .map(async ([key, item]) => {\n const itemValueDataHash = await PayloadBuilder.dataHash(item.value)\n if (hashes.includes(key) || hashes.includes(itemValueDataHash)) {\n this.cache.delete(key)\n return item.value\n }\n })))\n .filter(exists)\n this.rebuildDataHashIndex()\n await this.rebuildSequenceIndex()\n return deletedPayloads\n }\n\n protected override getHandler(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]> {\n return hashes.map((hash) => {\n const resolvedHash = this.dataHashIndex.get(hash) ?? hash\n const result = this.cache.get(resolvedHash)\n if (resolvedHash !== hash && !result) {\n throw new Error('Missing referenced payload')\n }\n return result\n }).filter(exists)\n }\n\n protected override insertHandler(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[] {\n const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta)\n this._sequenceIndex.push(...payloadsWithMeta)\n return payloadsWithMeta.map((payload) => {\n return this.insertPayloadIntoCache(payload)\n })\n }\n\n protected override nextHandler(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]> {\n const {\n limit = 100, cursor, order, open = true,\n } = options ?? {}\n let all = this._sequenceIndex.toSorted(PayloadBuilder.compareStorageMeta)\n if (order === 'desc') {\n all = all.toReversed()\n }\n const startIndex = isDefined(cursor)\n ? MemoryArchivist.findIndexFromCursor(all, cursor) + (open ? 1 : 0)\n : 0\n return all.slice(startIndex, startIndex + limit)\n }\n\n protected override payloadCountHandler() {\n return this.cache.size\n }\n\n protected override snapshotHandler(): PromisableArray<ArchivistSnapshotPayload<WithStorageMeta<Payload>, Hash>> {\n return [{\n hash: Object.fromEntries(\n [...this.cache.entries()].toSorted(([, payloadA], [, payloadB]) => {\n const diff = hexToBigInt(payloadA._sequence) - hexToBigInt(payloadB._sequence)\n return diff > 0n ? 1 : diff < 0n ? -1 : 0\n }),\n ),\n dataHash: Object.fromEntries(this.dataHashIndex.entries()),\n schema: ArchivistSnapshotPayloadSchema,\n }]\n }\n\n private insertPayloadIntoCache(payload: WithStorageMeta<Payload>): WithStorageMeta<Payload> {\n this.cache.set(payload._hash, payload)\n this.dataHashIndex.set(payload._dataHash, payload._hash)\n return payload\n }\n\n private rebuildDataHashIndex() {\n this._dataHashIndex = new LRUCache<Hash, Hash>({ max: this.max })\n const payloads = this.cache.dump().map(([, item]) => item.value)\n for (const payload of payloads) {\n this.dataHashIndex.set(payload._dataHash, payload._hash)\n }\n }\n\n private async rebuildSequenceIndex() {\n this._sequenceIndex = (await this.allHandler()).toSorted(PayloadBuilder.compareStorageMeta)\n }\n}\n","import type { EmptyObject, WithAdditional } from '@xylabs/object'\nimport type { ArchivistConfig } from '@xyo-network/archivist-model'\nimport type { Payload, Schema } from '@xyo-network/payload-model'\n\nexport const MemoryArchivistConfigSchema = 'network.xyo.archivist.memory.config' as const\nexport type MemoryArchivistConfigSchema = typeof MemoryArchivistConfigSchema\n\nexport type MemoryArchivistConfig<TConfig extends Payload | EmptyObject | void = void, TSchema extends Schema | void = void> = ArchivistConfig<\n WithAdditional<\n {\n max?: number\n },\n TConfig\n >,\n TSchema extends Schema ? TSchema : MemoryArchivistConfigSchema | ArchivistConfig['schema']\n>\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/Archivist.ts","../../src/Config.ts","../../src/MemoryDriver.ts"],"sourcesContent":["import { StorageClassLabel } from '@xyo-network/archivist-abstract'\nimport { GenericArchivist, GenericArchivistParams } from '@xyo-network/archivist-generic'\nimport {\n ArchivistAllQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistCommitQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistModuleEventData,\n ArchivistNextQuerySchema,\n AttachableArchivistInstance,\n} from '@xyo-network/archivist-model'\nimport {\n AnyConfigSchema, AttachableModuleInstance, creatableModule, ModuleInstance,\n} from '@xyo-network/module-model'\nimport { Schema } from '@xyo-network/payload-model'\n\nimport { MemoryArchivistConfig, MemoryArchivistConfigSchema } from './Config.ts'\nimport { MemoryDriver } from './MemoryDriver.ts'\n\nexport type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>>\n = GenericArchivistParams<TConfig>\n@creatableModule()\nexport class MemoryArchivist<\n TParams extends MemoryArchivistParams<AnyConfigSchema<MemoryArchivistConfig>> = MemoryArchivistParams,\n TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,\n>\n extends GenericArchivist<TParams, TEventData>\n implements AttachableArchivistInstance, ModuleInstance {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, MemoryArchivistConfigSchema]\n static override readonly defaultConfigSchema: Schema = MemoryArchivistConfigSchema\n static override readonly labels = { ...super.labels, [StorageClassLabel]: 'memory' }\n\n override get queries() {\n return [\n ArchivistAllQuerySchema,\n ArchivistDeleteQuerySchema,\n ArchivistClearQuerySchema,\n ArchivistInsertQuerySchema,\n ArchivistCommitQuerySchema,\n ArchivistNextQuerySchema,\n ...super.queries,\n ]\n }\n\n static override async paramsHandler<T extends AttachableModuleInstance<MemoryArchivistParams, ArchivistModuleEventData>>(\n inParams?: Partial<T['params']>,\n ): Promise<T['params']> {\n const superParams = await super.paramsHandler(inParams)\n return { ...superParams, driver: superParams.driver ?? await MemoryDriver.create(superParams) }\n }\n}\n","import type { EmptyObject, WithAdditional } from '@xylabs/object'\nimport type { ArchivistConfig } from '@xyo-network/archivist-model'\nimport type { Payload, Schema } from '@xyo-network/payload-model'\n\nexport const MemoryArchivistConfigSchema = 'network.xyo.archivist.memory.config' as const\nexport type MemoryArchivistConfigSchema = typeof MemoryArchivistConfigSchema\n\nexport type MemoryArchivistConfig<TConfig extends Payload | EmptyObject | void = void, TSchema extends Schema | void = void> = ArchivistConfig<\n WithAdditional<\n {\n max?: number\n },\n TConfig\n >,\n TSchema extends Schema ? TSchema : MemoryArchivistConfigSchema | ArchivistConfig['schema']\n>\n","import { assertEx } from '@xylabs/assert'\nimport {\n AbstractCreatable, creatable, CreatableParams,\n} from '@xylabs/creatable'\nimport { exists } from '@xylabs/exists'\nimport type { Hash, Hex } from '@xylabs/hex'\nimport type { Promisable } from '@xylabs/promise'\nimport { isDefined } from '@xylabs/typeof'\nimport type { ArchivistDriver, ArchivistNextOptions } from '@xyo-network/archivist-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport type { Payload, WithStorageMeta } from '@xyo-network/payload-model'\nimport { LRUCache } from 'lru-cache'\n\nexport interface MemoryDriverConfig {\n max?: number\n}\n\nexport interface MemoryDriverParams extends CreatableParams {\n config: MemoryDriverConfig\n}\n\n@creatable()\nexport class MemoryDriver extends AbstractCreatable<MemoryDriverParams>\n implements ArchivistDriver<Hash, Payload, WithStorageMeta<Payload>> {\n private _cache?: LRUCache<Hash, WithStorageMeta<Payload>>\n private _config?: MemoryDriverConfig\n private _dataHashIndex?: LRUCache<Hash, Hash>\n private _sequenceIndex: WithStorageMeta<Payload>[] = []\n\n protected get cache() {\n this._cache = this._cache ?? new LRUCache<Hash, WithStorageMeta<Payload>>({ max: this.max })\n return this._cache\n }\n\n protected get config() {\n return assertEx(this._config, () => 'Driver config is not set')\n }\n\n protected get dataHashIndex() {\n this._dataHashIndex = this._dataHashIndex ?? new LRUCache<Hash, Hash>({ max: this.max })\n return this._dataHashIndex\n }\n\n protected get max() {\n return this.config?.max ?? 10_000\n }\n\n private static findIndexFromCursor(payloads: WithStorageMeta[], cursor: Hex) {\n const index = payloads.findIndex(({ _sequence }) => _sequence === cursor)\n if (index === -1) {\n return Infinity // move to the end\n }\n return index\n }\n\n all(): Promisable<WithStorageMeta<Payload>[]> {\n return [...this.cache.values()].filter(exists).toSorted(PayloadBuilder.compareStorageMeta)\n }\n\n clear(): void | Promise<void> {\n this.cache.clear()\n this.rebuildDataHashIndex()\n this.rebuildDataHashIndex()\n }\n\n count() {\n return this.cache.size\n }\n\n override createHandler(): Promisable<void> {\n this._config = this.params.config ?? {}\n }\n\n async delete(hashes: Hash[]): Promise<WithStorageMeta[]> {\n const deletedPayloads: WithStorageMeta<Payload>[] = (await Promise.all(this.cache\n .dump()\n .map(async ([key, item]) => {\n const itemValueDataHash = await PayloadBuilder.dataHash(item.value)\n if (hashes.includes(key) || hashes.includes(itemValueDataHash)) {\n this.cache.delete(key)\n return item.value\n }\n })))\n .filter(exists)\n this.rebuildDataHashIndex()\n await this.rebuildSequenceIndex()\n return deletedPayloads\n }\n\n get(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]> {\n return hashes.map((hash) => {\n const resolvedHash = this.dataHashIndex.get(hash) ?? hash\n const result = this.cache.get(resolvedHash)\n if (resolvedHash !== hash && !result) {\n throw new Error('Missing referenced payload')\n }\n return result\n }).filter(exists)\n }\n\n insert(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[] {\n const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta)\n this._sequenceIndex.push(...payloadsWithMeta)\n return payloadsWithMeta.map((payload) => {\n return this.insertPayloadIntoCache(payload)\n })\n }\n\n next(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]> {\n const {\n limit = 100, cursor, order, open = true,\n } = options ?? {}\n let all = this._sequenceIndex.toSorted(PayloadBuilder.compareStorageMeta)\n if (order === 'desc') {\n all = all.toReversed()\n }\n const startIndex = isDefined(cursor)\n ? MemoryDriver.findIndexFromCursor(all, cursor) + (open ? 1 : 0)\n : 0\n return all.slice(startIndex, startIndex + limit)\n }\n\n private insertPayloadIntoCache(payload: WithStorageMeta<Payload>): WithStorageMeta<Payload> {\n this.cache.set(payload._hash, payload)\n this.dataHashIndex.set(payload._dataHash, payload._hash)\n return payload\n }\n\n private rebuildDataHashIndex() {\n this._dataHashIndex = new LRUCache<Hash, Hash>({ max: this.max })\n const payloads = this.cache.dump().map(([, item]) => item.value)\n for (const payload of payloads) {\n this.dataHashIndex.set(payload._dataHash, payload._hash)\n }\n }\n\n private async rebuildSequenceIndex() {\n this._sequenceIndex = (await this.all()).toSorted(PayloadBuilder.compareStorageMeta)\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,40 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { ArchivistModuleEventData, ArchivistNextOptions, ArchivistParams, ArchivistSnapshotPayload, AttachableArchivistInstance } from '@xyo-network/archivist-model';
|
|
6
|
-
import { BoundWitness } from '@xyo-network/boundwitness-model';
|
|
7
|
-
import { AnyConfigSchema, ModuleInstance } from '@xyo-network/module-model';
|
|
8
|
-
import { Payload, Schema, WithStorageMeta } from '@xyo-network/payload-model';
|
|
9
|
-
import { LRUCache } from 'lru-cache';
|
|
1
|
+
import { GenericArchivist, GenericArchivistParams } from '@xyo-network/archivist-generic';
|
|
2
|
+
import { ArchivistModuleEventData, AttachableArchivistInstance } from '@xyo-network/archivist-model';
|
|
3
|
+
import { AnyConfigSchema, AttachableModuleInstance, ModuleInstance } from '@xyo-network/module-model';
|
|
4
|
+
import { Schema } from '@xyo-network/payload-model';
|
|
10
5
|
import { MemoryArchivistConfig } from './Config.ts';
|
|
11
|
-
export type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>> =
|
|
12
|
-
export declare class MemoryArchivist<TParams extends MemoryArchivistParams<AnyConfigSchema<MemoryArchivistConfig>> = MemoryArchivistParams, TEventData extends ArchivistModuleEventData = ArchivistModuleEventData> extends
|
|
6
|
+
export type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>> = GenericArchivistParams<TConfig>;
|
|
7
|
+
export declare class MemoryArchivist<TParams extends MemoryArchivistParams<AnyConfigSchema<MemoryArchivistConfig>> = MemoryArchivistParams, TEventData extends ArchivistModuleEventData = ArchivistModuleEventData> extends GenericArchivist<TParams, TEventData> implements AttachableArchivistInstance, ModuleInstance {
|
|
13
8
|
static readonly configSchemas: Schema[];
|
|
14
9
|
static readonly defaultConfigSchema: Schema;
|
|
15
10
|
static readonly labels: {
|
|
16
11
|
"network.xyo.storage.class": string;
|
|
17
12
|
};
|
|
18
|
-
private _cache?;
|
|
19
|
-
private _dataHashIndex?;
|
|
20
|
-
private _sequenceIndex;
|
|
21
13
|
get queries(): string[];
|
|
22
|
-
|
|
23
|
-
protected get dataHashIndex(): LRUCache<Lowercase<string>, Lowercase<string>, unknown>;
|
|
24
|
-
protected get max(): number;
|
|
25
|
-
private static findIndexFromCursor;
|
|
26
|
-
from(payloads: Payload[], account?: AccountInstance): Promise<MemoryArchivist>;
|
|
27
|
-
protected allHandler(): Promisable<WithStorageMeta<Payload>[]>;
|
|
28
|
-
protected clearHandler(): void | Promise<void>;
|
|
29
|
-
protected commitHandler(): Promise<BoundWitness[]>;
|
|
30
|
-
protected deleteHandler(hashes: Hash[]): Promise<WithStorageMeta[]>;
|
|
31
|
-
protected getHandler(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]>;
|
|
32
|
-
protected insertHandler(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[];
|
|
33
|
-
protected nextHandler(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]>;
|
|
34
|
-
protected payloadCountHandler(): number;
|
|
35
|
-
protected snapshotHandler(): PromisableArray<ArchivistSnapshotPayload<WithStorageMeta<Payload>, Hash>>;
|
|
36
|
-
private insertPayloadIntoCache;
|
|
37
|
-
private rebuildDataHashIndex;
|
|
38
|
-
private rebuildSequenceIndex;
|
|
14
|
+
static paramsHandler<T extends AttachableModuleInstance<MemoryArchivistParams, ArchivistModuleEventData>>(inParams?: Partial<T['params']>): Promise<T['params']>;
|
|
39
15
|
}
|
|
40
16
|
//# sourceMappingURL=Archivist.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Archivist.d.ts","sourceRoot":"","sources":["../../src/Archivist.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACzF,OAAO,EAML,wBAAwB,EAExB,2BAA2B,EAC5B,MAAM,8BAA8B,CAAA;AACrC,OAAO,EACL,eAAe,EAAE,wBAAwB,EAAmB,cAAc,EAC3E,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAEnD,OAAO,EAAE,qBAAqB,EAA+B,MAAM,aAAa,CAAA;AAGhF,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,eAAe,CAAC,qBAAqB,CAAC,GAAG,eAAe,CAAC,qBAAqB,CAAC,IAC7H,sBAAsB,CAAC,OAAO,CAAC,CAAA;AACnC,qBACa,eAAe,CAC1B,OAAO,SAAS,qBAAqB,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC,GAAG,qBAAqB,EACrG,UAAU,SAAS,wBAAwB,GAAG,wBAAwB,CAEtE,SAAQ,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAC5C,YAAW,2BAA2B,EAAE,cAAc;IACtD,gBAAyB,aAAa,EAAE,MAAM,EAAE,CAAwD;IACxG,gBAAyB,mBAAmB,EAAE,MAAM,CAA8B;IAClF,gBAAyB,MAAM;;MAAqD;IAEpF,IAAa,OAAO,aAUnB;WAEqB,aAAa,CAAC,CAAC,SAAS,wBAAwB,CAAC,qBAAqB,EAAE,wBAAwB,CAAC,EACrH,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAC9B,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CAIxB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AbstractCreatable, CreatableParams } from '@xylabs/creatable';
|
|
2
|
+
import type { Hash } from '@xylabs/hex';
|
|
3
|
+
import type { Promisable } from '@xylabs/promise';
|
|
4
|
+
import type { ArchivistDriver, ArchivistNextOptions } from '@xyo-network/archivist-model';
|
|
5
|
+
import type { Payload, WithStorageMeta } from '@xyo-network/payload-model';
|
|
6
|
+
import { LRUCache } from 'lru-cache';
|
|
7
|
+
export interface MemoryDriverConfig {
|
|
8
|
+
max?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface MemoryDriverParams extends CreatableParams {
|
|
11
|
+
config: MemoryDriverConfig;
|
|
12
|
+
}
|
|
13
|
+
export declare class MemoryDriver extends AbstractCreatable<MemoryDriverParams> implements ArchivistDriver<Hash, Payload, WithStorageMeta<Payload>> {
|
|
14
|
+
private _cache?;
|
|
15
|
+
private _config?;
|
|
16
|
+
private _dataHashIndex?;
|
|
17
|
+
private _sequenceIndex;
|
|
18
|
+
protected get cache(): LRUCache<Lowercase<string>, WithStorageMeta<Payload>, unknown>;
|
|
19
|
+
protected get config(): MemoryDriverConfig;
|
|
20
|
+
protected get dataHashIndex(): LRUCache<Lowercase<string>, Lowercase<string>, unknown>;
|
|
21
|
+
protected get max(): number;
|
|
22
|
+
private static findIndexFromCursor;
|
|
23
|
+
all(): Promisable<WithStorageMeta<Payload>[]>;
|
|
24
|
+
clear(): void | Promise<void>;
|
|
25
|
+
count(): number;
|
|
26
|
+
createHandler(): Promisable<void>;
|
|
27
|
+
delete(hashes: Hash[]): Promise<WithStorageMeta[]>;
|
|
28
|
+
get(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]>;
|
|
29
|
+
insert(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[];
|
|
30
|
+
next(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]>;
|
|
31
|
+
private insertPayloadIntoCache;
|
|
32
|
+
private rebuildDataHashIndex;
|
|
33
|
+
private rebuildSequenceIndex;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=MemoryDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryDriver.d.ts","sourceRoot":"","sources":["../../src/MemoryDriver.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAAa,eAAe,EAC9C,MAAM,mBAAmB,CAAA;AAE1B,OAAO,KAAK,EAAE,IAAI,EAAO,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAEzF,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,MAAM,EAAE,kBAAkB,CAAA;CAC3B;AAED,qBACa,YAAa,SAAQ,iBAAiB,CAAC,kBAAkB,CACpE,YAAW,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACnE,OAAO,CAAC,MAAM,CAAC,CAA0C;IACzD,OAAO,CAAC,OAAO,CAAC,CAAoB;IACpC,OAAO,CAAC,cAAc,CAAC,CAAsB;IAC7C,OAAO,CAAC,cAAc,CAAiC;IAEvD,SAAS,KAAK,KAAK,mEAGlB;IAED,SAAS,KAAK,MAAM,uBAEnB;IAED,SAAS,KAAK,aAAa,4DAG1B;IAED,SAAS,KAAK,GAAG,WAEhB;IAED,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAQlC,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IAI7C,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7B,KAAK;IAII,aAAa,IAAI,UAAU,CAAC,IAAI,CAAC;IAIpC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAgBxD,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IAW3D,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,EAAE;IAQxE,IAAI,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,UAAU,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;IAc5E,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,oBAAoB;YAQd,oBAAoB;CAGnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/archivist-memory",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -29,33 +29,35 @@
|
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/types/index.d.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@xylabs/assert": "^4.
|
|
33
|
-
"@xylabs/
|
|
34
|
-
"@xylabs/
|
|
35
|
-
"@xylabs/
|
|
36
|
-
"@xylabs/
|
|
37
|
-
"@xylabs/
|
|
38
|
-
"@
|
|
39
|
-
"@xyo-network/account
|
|
40
|
-
"@xyo-network/
|
|
41
|
-
"@xyo-network/archivist-
|
|
42
|
-
"@xyo-network/
|
|
43
|
-
"@xyo-network/
|
|
44
|
-
"@xyo-network/
|
|
45
|
-
"@xyo-network/
|
|
32
|
+
"@xylabs/assert": "^4.12.30",
|
|
33
|
+
"@xylabs/creatable": "^4.12.30",
|
|
34
|
+
"@xylabs/exists": "^4.12.30",
|
|
35
|
+
"@xylabs/hex": "^4.12.30",
|
|
36
|
+
"@xylabs/object": "^4.12.30",
|
|
37
|
+
"@xylabs/promise": "^4.12.30",
|
|
38
|
+
"@xylabs/typeof": "^4.12.30",
|
|
39
|
+
"@xyo-network/account": "^4.0.0",
|
|
40
|
+
"@xyo-network/account-model": "^4.0.0",
|
|
41
|
+
"@xyo-network/archivist-abstract": "^4.0.0",
|
|
42
|
+
"@xyo-network/archivist-generic": "^4.0.0",
|
|
43
|
+
"@xyo-network/archivist-model": "^4.0.0",
|
|
44
|
+
"@xyo-network/boundwitness-model": "^4.0.0",
|
|
45
|
+
"@xyo-network/module-model": "^4.0.0",
|
|
46
|
+
"@xyo-network/payload-builder": "^4.0.0",
|
|
47
|
+
"@xyo-network/payload-model": "^4.0.0",
|
|
46
48
|
"lru-cache": "^11.1.0"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {
|
|
49
|
-
"@xylabs/delay": "^4.
|
|
50
|
-
"@xylabs/ts-scripts-yarn3": "^6.5.
|
|
51
|
-
"@xylabs/tsconfig": "^6.5.
|
|
52
|
-
"@xylabs/vitest-extended": "^4.
|
|
53
|
-
"@xyo-network/archivist-acceptance-tests": "^
|
|
54
|
-
"@xyo-network/id-payload-plugin": "^
|
|
55
|
-
"@xyo-network/payload-wrapper": "^
|
|
56
|
-
"@xyo-network/wallet": "^
|
|
51
|
+
"@xylabs/delay": "^4.12.30",
|
|
52
|
+
"@xylabs/ts-scripts-yarn3": "^6.5.12",
|
|
53
|
+
"@xylabs/tsconfig": "^6.5.12",
|
|
54
|
+
"@xylabs/vitest-extended": "^4.12.30",
|
|
55
|
+
"@xyo-network/archivist-acceptance-tests": "^4.0.0",
|
|
56
|
+
"@xyo-network/id-payload-plugin": "^4.0.0",
|
|
57
|
+
"@xyo-network/payload-wrapper": "^4.0.0",
|
|
58
|
+
"@xyo-network/wallet": "^4.0.0",
|
|
57
59
|
"typescript": "^5.8.3",
|
|
58
|
-
"vitest": "^3.2.
|
|
60
|
+
"vitest": "^3.2.4"
|
|
59
61
|
},
|
|
60
62
|
"publishConfig": {
|
|
61
63
|
"access": "public"
|
package/src/Archivist.ts
CHANGED
|
@@ -1,59 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
Hash, Hex, hexToBigInt,
|
|
5
|
-
} from '@xylabs/hex'
|
|
6
|
-
import {
|
|
7
|
-
fulfilled, Promisable, PromisableArray,
|
|
8
|
-
} from '@xylabs/promise'
|
|
9
|
-
import { isDefined } from '@xylabs/typeof'
|
|
10
|
-
import { Account } from '@xyo-network/account'
|
|
11
|
-
import { AccountInstance } from '@xyo-network/account-model'
|
|
12
|
-
import { AbstractArchivist, StorageClassLabel } from '@xyo-network/archivist-abstract'
|
|
1
|
+
import { StorageClassLabel } from '@xyo-network/archivist-abstract'
|
|
2
|
+
import { GenericArchivist, GenericArchivistParams } from '@xyo-network/archivist-generic'
|
|
13
3
|
import {
|
|
14
4
|
ArchivistAllQuerySchema,
|
|
15
5
|
ArchivistClearQuerySchema,
|
|
16
6
|
ArchivistCommitQuerySchema,
|
|
17
7
|
ArchivistDeleteQuerySchema,
|
|
18
|
-
ArchivistInsertQuery,
|
|
19
8
|
ArchivistInsertQuerySchema,
|
|
20
9
|
ArchivistModuleEventData,
|
|
21
|
-
ArchivistNextOptions,
|
|
22
10
|
ArchivistNextQuerySchema,
|
|
23
|
-
ArchivistParams,
|
|
24
|
-
ArchivistSnapshotPayload,
|
|
25
|
-
ArchivistSnapshotPayloadSchema,
|
|
26
11
|
AttachableArchivistInstance,
|
|
27
12
|
} from '@xyo-network/archivist-model'
|
|
28
|
-
import { BoundWitness } from '@xyo-network/boundwitness-model'
|
|
29
13
|
import {
|
|
30
|
-
AnyConfigSchema, creatableModule, ModuleInstance,
|
|
14
|
+
AnyConfigSchema, AttachableModuleInstance, creatableModule, ModuleInstance,
|
|
31
15
|
} from '@xyo-network/module-model'
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
Payload, Schema, WithStorageMeta,
|
|
35
|
-
} from '@xyo-network/payload-model'
|
|
36
|
-
import { LRUCache } from 'lru-cache'
|
|
16
|
+
import { Schema } from '@xyo-network/payload-model'
|
|
37
17
|
|
|
38
18
|
import { MemoryArchivistConfig, MemoryArchivistConfigSchema } from './Config.ts'
|
|
19
|
+
import { MemoryDriver } from './MemoryDriver.ts'
|
|
39
20
|
|
|
40
|
-
export type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>>
|
|
41
|
-
|
|
21
|
+
export type MemoryArchivistParams<TConfig extends AnyConfigSchema<MemoryArchivistConfig> = AnyConfigSchema<MemoryArchivistConfig>>
|
|
22
|
+
= GenericArchivistParams<TConfig>
|
|
42
23
|
@creatableModule()
|
|
43
24
|
export class MemoryArchivist<
|
|
44
25
|
TParams extends MemoryArchivistParams<AnyConfigSchema<MemoryArchivistConfig>> = MemoryArchivistParams,
|
|
45
26
|
TEventData extends ArchivistModuleEventData = ArchivistModuleEventData,
|
|
46
27
|
>
|
|
47
|
-
extends
|
|
28
|
+
extends GenericArchivist<TParams, TEventData>
|
|
48
29
|
implements AttachableArchivistInstance, ModuleInstance {
|
|
49
30
|
static override readonly configSchemas: Schema[] = [...super.configSchemas, MemoryArchivistConfigSchema]
|
|
50
31
|
static override readonly defaultConfigSchema: Schema = MemoryArchivistConfigSchema
|
|
51
32
|
static override readonly labels = { ...super.labels, [StorageClassLabel]: 'memory' }
|
|
52
33
|
|
|
53
|
-
private _cache?: LRUCache<Hash, WithStorageMeta<Payload>>
|
|
54
|
-
private _dataHashIndex?: LRUCache<Hash, Hash>
|
|
55
|
-
private _sequenceIndex: WithStorageMeta<Payload>[] = []
|
|
56
|
-
|
|
57
34
|
override get queries() {
|
|
58
35
|
return [
|
|
59
36
|
ArchivistAllQuerySchema,
|
|
@@ -66,139 +43,10 @@ export class MemoryArchivist<
|
|
|
66
43
|
]
|
|
67
44
|
}
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
protected get dataHashIndex() {
|
|
75
|
-
this._dataHashIndex = this._dataHashIndex ?? new LRUCache<Hash, Hash>({ max: this.max })
|
|
76
|
-
return this._dataHashIndex
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
protected get max() {
|
|
80
|
-
return this.config?.max ?? 10_000
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private static findIndexFromCursor(payloads: WithStorageMeta[], cursor: Hex) {
|
|
84
|
-
const index = payloads.findIndex(({ _sequence }) => _sequence === cursor)
|
|
85
|
-
if (index === -1) {
|
|
86
|
-
return Infinity // move to the end
|
|
87
|
-
}
|
|
88
|
-
return index
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async from(payloads: Payload[], account?: AccountInstance): Promise<MemoryArchivist> {
|
|
92
|
-
const archivist = await MemoryArchivist.create({ account: account ?? await Account.random() })
|
|
93
|
-
await archivist.insert(payloads)
|
|
94
|
-
return archivist
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
protected override allHandler(): Promisable<WithStorageMeta<Payload>[]> {
|
|
98
|
-
return [...this.cache.values()].filter(exists).toSorted(PayloadBuilder.compareStorageMeta)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
protected override clearHandler(): void | Promise<void> {
|
|
102
|
-
this.cache.clear()
|
|
103
|
-
this.rebuildDataHashIndex()
|
|
104
|
-
this.rebuildDataHashIndex()
|
|
105
|
-
return this.emit('cleared', { mod: this })
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
protected override async commitHandler(): Promise<BoundWitness[]> {
|
|
109
|
-
const payloads = assertEx(await this.allHandler(), () => 'Nothing to commit')
|
|
110
|
-
const settled = await Promise.allSettled(
|
|
111
|
-
Object.values((await this.parentArchivists()).commit ?? [])?.map(async (parent) => {
|
|
112
|
-
const queryPayload: ArchivistInsertQuery = { schema: ArchivistInsertQuerySchema }
|
|
113
|
-
const query = await this.bindQuery(queryPayload, payloads)
|
|
114
|
-
return (await parent?.query(query[0], query[1]))?.[0]
|
|
115
|
-
}).filter(exists),
|
|
116
|
-
)
|
|
117
|
-
await this.clearHandler()
|
|
118
|
-
return settled.filter(fulfilled).map(result => result.value).filter(exists)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
protected override async deleteHandler(hashes: Hash[]): Promise<WithStorageMeta[]> {
|
|
122
|
-
const deletedPayloads: WithStorageMeta<Payload>[] = (await Promise.all(this.cache
|
|
123
|
-
.dump()
|
|
124
|
-
.map(async ([key, item]) => {
|
|
125
|
-
const itemValueDataHash = await PayloadBuilder.dataHash(item.value)
|
|
126
|
-
if (hashes.includes(key) || hashes.includes(itemValueDataHash)) {
|
|
127
|
-
this.cache.delete(key)
|
|
128
|
-
return item.value
|
|
129
|
-
}
|
|
130
|
-
})))
|
|
131
|
-
.filter(exists)
|
|
132
|
-
this.rebuildDataHashIndex()
|
|
133
|
-
await this.rebuildSequenceIndex()
|
|
134
|
-
return deletedPayloads
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
protected override getHandler(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]> {
|
|
138
|
-
return hashes.map((hash) => {
|
|
139
|
-
const resolvedHash = this.dataHashIndex.get(hash) ?? hash
|
|
140
|
-
const result = this.cache.get(resolvedHash)
|
|
141
|
-
if (resolvedHash !== hash && !result) {
|
|
142
|
-
throw new Error('Missing referenced payload')
|
|
143
|
-
}
|
|
144
|
-
return result
|
|
145
|
-
}).filter(exists)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
protected override insertHandler(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[] {
|
|
149
|
-
const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta)
|
|
150
|
-
this._sequenceIndex.push(...payloadsWithMeta)
|
|
151
|
-
return payloadsWithMeta.map((payload) => {
|
|
152
|
-
return this.insertPayloadIntoCache(payload)
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
protected override nextHandler(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]> {
|
|
157
|
-
const {
|
|
158
|
-
limit = 100, cursor, order, open = true,
|
|
159
|
-
} = options ?? {}
|
|
160
|
-
let all = this._sequenceIndex.toSorted(PayloadBuilder.compareStorageMeta)
|
|
161
|
-
if (order === 'desc') {
|
|
162
|
-
all = all.toReversed()
|
|
163
|
-
}
|
|
164
|
-
const startIndex = isDefined(cursor)
|
|
165
|
-
? MemoryArchivist.findIndexFromCursor(all, cursor) + (open ? 1 : 0)
|
|
166
|
-
: 0
|
|
167
|
-
return all.slice(startIndex, startIndex + limit)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
protected override payloadCountHandler() {
|
|
171
|
-
return this.cache.size
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
protected override snapshotHandler(): PromisableArray<ArchivistSnapshotPayload<WithStorageMeta<Payload>, Hash>> {
|
|
175
|
-
return [{
|
|
176
|
-
hash: Object.fromEntries(
|
|
177
|
-
[...this.cache.entries()].toSorted(([, payloadA], [, payloadB]) => {
|
|
178
|
-
const diff = hexToBigInt(payloadA._sequence) - hexToBigInt(payloadB._sequence)
|
|
179
|
-
return diff > 0n ? 1 : diff < 0n ? -1 : 0
|
|
180
|
-
}),
|
|
181
|
-
),
|
|
182
|
-
dataHash: Object.fromEntries(this.dataHashIndex.entries()),
|
|
183
|
-
schema: ArchivistSnapshotPayloadSchema,
|
|
184
|
-
}]
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
private insertPayloadIntoCache(payload: WithStorageMeta<Payload>): WithStorageMeta<Payload> {
|
|
188
|
-
this.cache.set(payload._hash, payload)
|
|
189
|
-
this.dataHashIndex.set(payload._dataHash, payload._hash)
|
|
190
|
-
return payload
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private rebuildDataHashIndex() {
|
|
194
|
-
this._dataHashIndex = new LRUCache<Hash, Hash>({ max: this.max })
|
|
195
|
-
const payloads = this.cache.dump().map(([, item]) => item.value)
|
|
196
|
-
for (const payload of payloads) {
|
|
197
|
-
this.dataHashIndex.set(payload._dataHash, payload._hash)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private async rebuildSequenceIndex() {
|
|
202
|
-
this._sequenceIndex = (await this.allHandler()).toSorted(PayloadBuilder.compareStorageMeta)
|
|
46
|
+
static override async paramsHandler<T extends AttachableModuleInstance<MemoryArchivistParams, ArchivistModuleEventData>>(
|
|
47
|
+
inParams?: Partial<T['params']>,
|
|
48
|
+
): Promise<T['params']> {
|
|
49
|
+
const superParams = await super.paramsHandler(inParams)
|
|
50
|
+
return { ...superParams, driver: superParams.driver ?? await MemoryDriver.create(superParams) }
|
|
203
51
|
}
|
|
204
52
|
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import {
|
|
3
|
+
AbstractCreatable, creatable, CreatableParams,
|
|
4
|
+
} from '@xylabs/creatable'
|
|
5
|
+
import { exists } from '@xylabs/exists'
|
|
6
|
+
import type { Hash, Hex } from '@xylabs/hex'
|
|
7
|
+
import type { Promisable } from '@xylabs/promise'
|
|
8
|
+
import { isDefined } from '@xylabs/typeof'
|
|
9
|
+
import type { ArchivistDriver, ArchivistNextOptions } from '@xyo-network/archivist-model'
|
|
10
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
11
|
+
import type { Payload, WithStorageMeta } from '@xyo-network/payload-model'
|
|
12
|
+
import { LRUCache } from 'lru-cache'
|
|
13
|
+
|
|
14
|
+
export interface MemoryDriverConfig {
|
|
15
|
+
max?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MemoryDriverParams extends CreatableParams {
|
|
19
|
+
config: MemoryDriverConfig
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@creatable()
|
|
23
|
+
export class MemoryDriver extends AbstractCreatable<MemoryDriverParams>
|
|
24
|
+
implements ArchivistDriver<Hash, Payload, WithStorageMeta<Payload>> {
|
|
25
|
+
private _cache?: LRUCache<Hash, WithStorageMeta<Payload>>
|
|
26
|
+
private _config?: MemoryDriverConfig
|
|
27
|
+
private _dataHashIndex?: LRUCache<Hash, Hash>
|
|
28
|
+
private _sequenceIndex: WithStorageMeta<Payload>[] = []
|
|
29
|
+
|
|
30
|
+
protected get cache() {
|
|
31
|
+
this._cache = this._cache ?? new LRUCache<Hash, WithStorageMeta<Payload>>({ max: this.max })
|
|
32
|
+
return this._cache
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected get config() {
|
|
36
|
+
return assertEx(this._config, () => 'Driver config is not set')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected get dataHashIndex() {
|
|
40
|
+
this._dataHashIndex = this._dataHashIndex ?? new LRUCache<Hash, Hash>({ max: this.max })
|
|
41
|
+
return this._dataHashIndex
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected get max() {
|
|
45
|
+
return this.config?.max ?? 10_000
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private static findIndexFromCursor(payloads: WithStorageMeta[], cursor: Hex) {
|
|
49
|
+
const index = payloads.findIndex(({ _sequence }) => _sequence === cursor)
|
|
50
|
+
if (index === -1) {
|
|
51
|
+
return Infinity // move to the end
|
|
52
|
+
}
|
|
53
|
+
return index
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
all(): Promisable<WithStorageMeta<Payload>[]> {
|
|
57
|
+
return [...this.cache.values()].filter(exists).toSorted(PayloadBuilder.compareStorageMeta)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
clear(): void | Promise<void> {
|
|
61
|
+
this.cache.clear()
|
|
62
|
+
this.rebuildDataHashIndex()
|
|
63
|
+
this.rebuildDataHashIndex()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
count() {
|
|
67
|
+
return this.cache.size
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override createHandler(): Promisable<void> {
|
|
71
|
+
this._config = this.params.config ?? {}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async delete(hashes: Hash[]): Promise<WithStorageMeta[]> {
|
|
75
|
+
const deletedPayloads: WithStorageMeta<Payload>[] = (await Promise.all(this.cache
|
|
76
|
+
.dump()
|
|
77
|
+
.map(async ([key, item]) => {
|
|
78
|
+
const itemValueDataHash = await PayloadBuilder.dataHash(item.value)
|
|
79
|
+
if (hashes.includes(key) || hashes.includes(itemValueDataHash)) {
|
|
80
|
+
this.cache.delete(key)
|
|
81
|
+
return item.value
|
|
82
|
+
}
|
|
83
|
+
})))
|
|
84
|
+
.filter(exists)
|
|
85
|
+
this.rebuildDataHashIndex()
|
|
86
|
+
await this.rebuildSequenceIndex()
|
|
87
|
+
return deletedPayloads
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get(hashes: Hash[]): Promisable<WithStorageMeta<Payload>[]> {
|
|
91
|
+
return hashes.map((hash) => {
|
|
92
|
+
const resolvedHash = this.dataHashIndex.get(hash) ?? hash
|
|
93
|
+
const result = this.cache.get(resolvedHash)
|
|
94
|
+
if (resolvedHash !== hash && !result) {
|
|
95
|
+
throw new Error('Missing referenced payload')
|
|
96
|
+
}
|
|
97
|
+
return result
|
|
98
|
+
}).filter(exists)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
insert(payloads: WithStorageMeta<Payload>[]): WithStorageMeta<Payload>[] {
|
|
102
|
+
const payloadsWithMeta = payloads.toSorted(PayloadBuilder.compareStorageMeta)
|
|
103
|
+
this._sequenceIndex.push(...payloadsWithMeta)
|
|
104
|
+
return payloadsWithMeta.map((payload) => {
|
|
105
|
+
return this.insertPayloadIntoCache(payload)
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
next(options?: ArchivistNextOptions): Promisable<WithStorageMeta<Payload>[]> {
|
|
110
|
+
const {
|
|
111
|
+
limit = 100, cursor, order, open = true,
|
|
112
|
+
} = options ?? {}
|
|
113
|
+
let all = this._sequenceIndex.toSorted(PayloadBuilder.compareStorageMeta)
|
|
114
|
+
if (order === 'desc') {
|
|
115
|
+
all = all.toReversed()
|
|
116
|
+
}
|
|
117
|
+
const startIndex = isDefined(cursor)
|
|
118
|
+
? MemoryDriver.findIndexFromCursor(all, cursor) + (open ? 1 : 0)
|
|
119
|
+
: 0
|
|
120
|
+
return all.slice(startIndex, startIndex + limit)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private insertPayloadIntoCache(payload: WithStorageMeta<Payload>): WithStorageMeta<Payload> {
|
|
124
|
+
this.cache.set(payload._hash, payload)
|
|
125
|
+
this.dataHashIndex.set(payload._dataHash, payload._hash)
|
|
126
|
+
return payload
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private rebuildDataHashIndex() {
|
|
130
|
+
this._dataHashIndex = new LRUCache<Hash, Hash>({ max: this.max })
|
|
131
|
+
const payloads = this.cache.dump().map(([, item]) => item.value)
|
|
132
|
+
for (const payload of payloads) {
|
|
133
|
+
this.dataHashIndex.set(payload._dataHash, payload._hash)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private async rebuildSequenceIndex() {
|
|
138
|
+
this._sequenceIndex = (await this.all()).toSorted(PayloadBuilder.compareStorageMeta)
|
|
139
|
+
}
|
|
140
|
+
}
|