@twin.org/entity-storage-connector-memory 0.0.3-next.31 → 0.0.3-next.33
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/es/memoryEntityStorageConnector.js +13 -8
- package/dist/es/memoryEntityStorageConnector.js.map +1 -1
- package/dist/es/models/IMemoryEntityStorageConnectorConfig.js.map +1 -1
- package/dist/types/models/IMemoryEntityStorageConnectorConfig.d.ts +4 -0
- package/docs/changelog.md +28 -0
- package/docs/reference/interfaces/IMemoryEntityStorageConnectorConfig.md +8 -0
- package/package.json +2 -2
|
@@ -60,6 +60,11 @@ export class MemoryEntityStorageConnector {
|
|
|
60
60
|
* @internal
|
|
61
61
|
*/
|
|
62
62
|
_maxCapacityBytes;
|
|
63
|
+
/**
|
|
64
|
+
* Milliseconds to wait for the directory lock before throwing.
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
_mutexTimeoutMs;
|
|
63
68
|
/**
|
|
64
69
|
* Create a new instance of MemoryEntityStorageConnector.
|
|
65
70
|
* @param options The options for the connector.
|
|
@@ -75,6 +80,7 @@ export class MemoryEntityStorageConnector {
|
|
|
75
80
|
this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
76
81
|
this._initialCapacityBytes = options.config?.initialCapacityBytes;
|
|
77
82
|
this._maxCapacityBytes = options.config?.maxCapacityBytes;
|
|
83
|
+
this._mutexTimeoutMs = Coerce.integer(options.config.mutexTimeoutMs);
|
|
78
84
|
}
|
|
79
85
|
/**
|
|
80
86
|
* Returns the class name of the component.
|
|
@@ -357,7 +363,7 @@ export class MemoryEntityStorageConnector {
|
|
|
357
363
|
ts: Date.now(),
|
|
358
364
|
message: "storeTearingDown"
|
|
359
365
|
});
|
|
360
|
-
await Mutex.lock(this._storageKey, { throwOnTimeout: true });
|
|
366
|
+
await Mutex.lock(this._storageKey, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });
|
|
361
367
|
try {
|
|
362
368
|
SharedObjectBuffer.remove(this._storageKey);
|
|
363
369
|
}
|
|
@@ -441,7 +447,7 @@ export class MemoryEntityStorageConnector {
|
|
|
441
447
|
// migration starts from an empty store regardless of any previous connector
|
|
442
448
|
// instances that shared the same schema name.
|
|
443
449
|
if (targetSchemaName !== this._storageKey) {
|
|
444
|
-
await Mutex.lock(targetSchemaName, { throwOnTimeout: true });
|
|
450
|
+
await Mutex.lock(targetSchemaName, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });
|
|
445
451
|
try {
|
|
446
452
|
SharedObjectBuffer.remove(targetSchemaName);
|
|
447
453
|
}
|
|
@@ -485,22 +491,21 @@ export class MemoryEntityStorageConnector {
|
|
|
485
491
|
* @internal
|
|
486
492
|
*/
|
|
487
493
|
async withLock(fn) {
|
|
488
|
-
|
|
489
|
-
await Mutex.lock(key, { throwOnTimeout: true });
|
|
494
|
+
await Mutex.lock(this._storageKey, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });
|
|
490
495
|
try {
|
|
491
|
-
await SharedObjectBuffer.create(
|
|
496
|
+
await SharedObjectBuffer.create(this._storageKey, {
|
|
492
497
|
initialCapacityBytes: this._initialCapacityBytes,
|
|
493
498
|
maxCapacityBytes: this._maxCapacityBytes
|
|
494
499
|
});
|
|
495
|
-
const entities = (await SharedObjectBuffer.read(
|
|
500
|
+
const entities = (await SharedObjectBuffer.read(this._storageKey)) ?? [];
|
|
496
501
|
const outcome = fn(entities);
|
|
497
502
|
if (outcome.updated !== undefined) {
|
|
498
|
-
await SharedObjectBuffer.write(
|
|
503
|
+
await SharedObjectBuffer.write(this._storageKey, outcome.updated);
|
|
499
504
|
}
|
|
500
505
|
return outcome.result;
|
|
501
506
|
}
|
|
502
507
|
finally {
|
|
503
|
-
Mutex.unlock(
|
|
508
|
+
Mutex.unlock(this._storageKey);
|
|
504
509
|
}
|
|
505
510
|
}
|
|
506
511
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memoryEntityStorageConnector.js","sourceRoot":"","sources":["../../src/memoryEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tCoerce,\n\tComponentFactory,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tMutex,\n\tObjectHelper,\n\tSharedObjectBuffer,\n\tValidation\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntityConditions,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySorter,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\ttype SortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IMemoryEntityStorageConnectorConfig } from \"./models/IMemoryEntityStorageConnectorConfig.js\";\nimport type { IMemoryEntityStorageConnectorConstructorOptions } from \"./models/IMemoryEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in-memory backed by a shared object buffer.\n *\n * All reads and writes are serialised with a per-schema lock so that concurrent async\n * access, including across worker threads, never produces torn or lost updates.\n *\n * All connector instances that share the same entity schema name share the same underlying\n * buffer, making data written in one instance immediately visible in another, including\n * across worker threads when the main thread forwards worker messages to the lock and\n * buffer handlers.\n */\nexport class MemoryEntityStorageConnector<T = unknown>\n\timplements IEntityStorageConnector<T>, IEntityStorageMigrationConnector<T>\n{\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MemoryEntityStorageConnector>();\n\n\t/**\n\t * Default limit for the number of items to return.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition key for the operation.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The primary key.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The resolved storage key used as the shared buffer and lock key.\n\t * @internal\n\t */\n\tprivate readonly _storageKey: string;\n\n\t/**\n\t * Initial capacity hint in bytes for the shared entity buffer.\n\t * @internal\n\t */\n\tprivate readonly _initialCapacityBytes?: number;\n\n\t/**\n\t * Maximum capacity in bytes for the shared entity buffer.\n\t * @internal\n\t */\n\tprivate readonly _maxCapacityBytes?: number;\n\n\t/**\n\t * Create a new instance of MemoryEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMemoryEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object<IMemoryEntityStorageConnectorConstructorOptions>(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options),\n\t\t\toptions\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMemoryEntityStorageConnectorConfig>(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.storageKey),\n\t\t\toptions.config.storageKey\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._storageKey = options.config.storageKey;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\t\tthis._initialCapacityBytes = options.config?.initialCapacityBytes;\n\t\tthis._maxCapacityBytes = options.config?.maxCapacityBytes;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MemoryEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tdata: { entityType: this._storageKey }\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Bootstrap the component by creating and initializing any resources it needs.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the bootstrapping process was successful.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tawait SharedObjectBuffer.create(this._storageKey, {\n\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get an entity.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst index = this.findItem(entities, id, secondaryIndex, finalConditions);\n\t\t\tconst item = index >= 0 ? entities[index] : undefined;\n\n\t\t\tif (Is.objectValue(item)) {\n\t\t\t\treturn {\n\t\t\t\t\tresult: EntityStorageHelper.unPrepareEntity<T>(item, [\n\t\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t])\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Resolves when the entity has been stored.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MemoryEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\n\t\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t: undefined,\n\t\t\t{ nullBehavior: \"omit\" }\n\t\t);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst existingIndex = this.findItem(\n\t\t\t\tentities,\n\t\t\t\tprepared[this._primaryKey.property] as string,\n\t\t\t\tundefined,\n\t\t\t\tfinalConditions\n\t\t\t);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tentities[existingIndex] = prepared;\n\t\t\t} else {\n\t\t\t\tentities.push(prepared);\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst preparedItems = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t\t: undefined,\n\t\t\t\t{ nullBehavior: \"omit\" }\n\t\t\t)\n\t\t);\n\n\t\treturn this.withLock(store => {\n\t\t\tconst indexMap = new Map<string, number>();\n\t\t\tfor (let i = 0; i < store.length; i++) {\n\t\t\t\tconst stored = store[i];\n\t\t\t\tconst storedPartition = ObjectHelper.propertyGet(\n\t\t\t\t\tstored,\n\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t);\n\t\t\t\tif (!Is.stringValue(partitionKey) || storedPartition === partitionKey) {\n\t\t\t\t\tindexMap.set(stored[this._primaryKey.property] as string, i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const prepared of preparedItems) {\n\t\t\t\tconst id = prepared[this._primaryKey.property] as string;\n\t\t\t\tconst existingIndex = indexMap.get(id);\n\t\t\t\tif (existingIndex !== undefined) {\n\t\t\t\t\tstore[existingIndex] = prepared;\n\t\t\t\t} else {\n\t\t\t\t\tconst newIndex = store.push(prepared) - 1;\n\t\t\t\t\tindexMap.set(id, newIndex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { updated: store, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst index = this.findItem(entities, id, undefined, finalConditions);\n\t\t\tif (index >= 0) {\n\t\t\t\tentities.splice(index, 1);\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\treturn this.withLock(store => {\n\t\t\tlet allEntities = store.slice();\n\n\t\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\t\tconditions: [],\n\t\t\t\tlogicalOperator: LogicalOperator.And\n\t\t\t};\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: partitionKey\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(conditions)) {\n\t\t\t\tfinalConditions.conditions.push(EntityStorageHelper.normalizeConditionValues(conditions));\n\t\t\t}\n\n\t\t\tconst resultEntities = [];\n\t\t\tconst finalLimit = limit ?? MemoryEntityStorageConnector._DEFAULT_LIMIT;\n\t\t\tlet nextCursor: string | undefined;\n\n\t\t\tif (allEntities.length > 0) {\n\t\t\t\tconst finalSortKeys = EntitySchemaHelper.buildSortProperties<T>(\n\t\t\t\t\tthis._entitySchema,\n\t\t\t\t\tsortProperties\n\t\t\t\t);\n\t\t\t\tallEntities = EntitySorter.sort(allEntities, finalSortKeys);\n\n\t\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\t\tfor (let i = startIndex; i < allEntities.length; i++) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tEntityConditions.check(allEntities[i], finalConditions) &&\n\t\t\t\t\t\tresultEntities.length < finalLimit\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst entity = Is.arrayValue(properties)\n\t\t\t\t\t\t\t? ObjectHelper.pick(allEntities[i], properties)\n\t\t\t\t\t\t\t: allEntities[i];\n\t\t\t\t\t\tresultEntities.push(\n\t\t\t\t\t\t\tEntityStorageHelper.unPrepareEntity<T>(entity, [\n\t\t\t\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (resultEntities.length >= finalLimit) {\n\t\t\t\t\t\t\tif (i < allEntities.length - 1) {\n\t\t\t\t\t\t\t\tnextCursor = (i + 1).toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { result: { entities: resultEntities, cursor: nextCursor } };\n\t\t});\n\t}\n\n\t/**\n\t * Remove all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\treturn this.withLock(entities => {\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tconst filtered = entities.filter(\n\t\t\t\t\titem =>\n\t\t\t\t\t\tObjectHelper.propertyGet(item, MemoryEntityStorageConnector._PARTITION_KEY) !==\n\t\t\t\t\t\tpartitionKey\n\t\t\t\t);\n\t\t\t\treturn { updated: filtered, result: undefined };\n\t\t\t}\n\t\t\treturn { updated: [], result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: { property: keyof T; value: unknown }[] = [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst index = this.findItem(entities, id, undefined, finalConditions);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tentities.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Teardown the storage by clearing the underlying shared buffer for this schema.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\tawait Mutex.lock(this._storageKey, { throwOnTimeout: true });\n\t\ttry {\n\t\t\tSharedObjectBuffer.remove(this._storageKey);\n\t\t} finally {\n\t\t\tMutex.unlock(this._storageKey);\n\t\t}\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTornDown\"\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(EntityStorageHelper.normalizeConditionValues(conditions));\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tif (finalConditions.conditions.length === 0) {\n\t\t\t\treturn { result: entities.length };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tresult: entities.filter(item => EntityConditions.check(item, finalConditions)).length\n\t\t\t};\n\t\t});\n\t}\n\n\t/**\n\t * Get all entities in the memory store.\n\t * @returns All stored entities with partition keys removed.\n\t */\n\tpublic async getStore(): Promise<T[]> {\n\t\treturn this.withLock(entities => ({\n\t\t\tresult: entities.map(item =>\n\t\t\t\tEntityStorageHelper.unPrepareEntity<T>(item, [MemoryEntityStorageConnector._PARTITION_KEY])\n\t\t\t)\n\t\t}));\n\t}\n\n\t/**\n\t * Get a unique list of all the context ids from the storage.\n\t * @returns The list of unique context ids.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\treturn this.withLock(entities => {\n\t\t\tconst contextIds: { [id: string]: IContextIds } = {};\n\t\t\tfor (const entity of entities) {\n\t\t\t\tconst partitionId = ObjectHelper.propertyGet(\n\t\t\t\t\tentity,\n\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t);\n\t\t\t\tif (Is.stringValue(partitionId)) {\n\t\t\t\t\tcontextIds[partitionId] = ContextIdHelper.shortSplit(\n\t\t\t\t\t\tthis._partitionContextIds ?? [],\n\t\t\t\t\t\tpartitionId\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { result: Object.values(contextIds) };\n\t\t});\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration it will use a temporary storage location.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\t// Resolve the target schema name the same way _storageKey is resolved in the constructor.\n\t\tconst targetSchemaEntry = EntitySchemaFactory.get(newEntitySchema);\n\t\tconst targetSchemaName = targetSchemaEntry.type ?? newEntitySchema;\n\n\t\t// When migrating to a different schema, wipe the target buffer so that every\n\t\t// migration starts from an empty store regardless of any previous connector\n\t\t// instances that shared the same schema name.\n\t\tif (targetSchemaName !== this._storageKey) {\n\t\t\tawait Mutex.lock(targetSchemaName, { throwOnTimeout: true });\n\t\t\ttry {\n\t\t\t\tSharedObjectBuffer.remove(targetSchemaName);\n\t\t\t} finally {\n\t\t\t\tMutex.unlock(targetSchemaName);\n\t\t\t}\n\t\t}\n\n\t\treturn new MemoryEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tpartitionContextIds: this._partitionContextIds,\n\t\t\tconfig: {\n\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old connector and replacing it with the target connector.\n\t * @param targetConnector The target connector to finalize the migration with.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is finalized.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\treturn targetConnector;\n\t}\n\n\t/**\n\t * Cleanup the migration if a migration fails or needs to be aborted.\n\t * @param targetConnector The target connector to cleanup the migration with.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is cleaned up.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<void> {}\n\n\t/**\n\t * Acquires the schema-keyed lock, runs fn with the current entity array, optionally\n\t * writes back a modified array, then releases the lock.\n\t * @param fn The synchronous function to run while the lock is held.\n\t * @returns The result produced by fn.\n\t * @internal\n\t */\n\tprivate async withLock<R>(fn: (entities: T[]) => { updated?: T[]; result: R }): Promise<R> {\n\t\tconst key = this._storageKey;\n\t\tawait Mutex.lock(key, { throwOnTimeout: true });\n\t\ttry {\n\t\t\tawait SharedObjectBuffer.create(key, {\n\t\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t\t});\n\t\t\tconst entities = (await SharedObjectBuffer.read<T[]>(key)) ?? [];\n\t\t\tconst outcome = fn(entities);\n\t\t\tif (outcome.updated !== undefined) {\n\t\t\t\tawait SharedObjectBuffer.write<T[]>(key, outcome.updated);\n\t\t\t}\n\t\t\treturn outcome.result;\n\t\t} finally {\n\t\t\tMutex.unlock(key);\n\t\t}\n\t}\n\n\t/**\n\t * Find the item in the provided entity array.\n\t * @param entities The current entity array.\n\t * @param id The id to search for.\n\t * @param secondaryIndex The secondary index to search for.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The index of the item if found or -1.\n\t * @internal\n\t */\n\tprivate findItem(\n\t\tentities: T[],\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): number {\n\t\tconst finalConditions: EntityCondition<T>[] = [];\n\n\t\tif (!Is.empty(secondaryIndex)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: secondaryIndex as string,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: id\n\t\t\t});\n\t\t}\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\tif (finalConditions.length === 0) {\n\t\t\t\tfinalConditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tfinalConditions.push(\n\t\t\t\t...conditions.map(c => ({\n\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: c.value\n\t\t\t\t}))\n\t\t\t);\n\t\t}\n\n\t\tif (finalConditions.length > 0) {\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tif (EntityConditions.check(entities[i], { conditions: finalConditions })) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn entities.findIndex(e => e[this._primaryKey.property] === id);\n\t\t}\n\n\t\treturn -1;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"memoryEntityStorageConnector.js","sourceRoot":"","sources":["../../src/memoryEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tCoerce,\n\tComponentFactory,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tMutex,\n\tObjectHelper,\n\tSharedObjectBuffer,\n\tValidation\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntityConditions,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\tEntitySorter,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\ttype SortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IMemoryEntityStorageConnectorConfig } from \"./models/IMemoryEntityStorageConnectorConfig.js\";\nimport type { IMemoryEntityStorageConnectorConstructorOptions } from \"./models/IMemoryEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in-memory backed by a shared object buffer.\n *\n * All reads and writes are serialised with a per-schema lock so that concurrent async\n * access, including across worker threads, never produces torn or lost updates.\n *\n * All connector instances that share the same entity schema name share the same underlying\n * buffer, making data written in one instance immediately visible in another, including\n * across worker threads when the main thread forwards worker messages to the lock and\n * buffer handlers.\n */\nexport class MemoryEntityStorageConnector<T = unknown>\n\timplements IEntityStorageConnector<T>, IEntityStorageMigrationConnector<T>\n{\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<MemoryEntityStorageConnector>();\n\n\t/**\n\t * Default limit for the number of items to return.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition key for the operation.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The primary key.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The resolved storage key used as the shared buffer and lock key.\n\t * @internal\n\t */\n\tprivate readonly _storageKey: string;\n\n\t/**\n\t * Initial capacity hint in bytes for the shared entity buffer.\n\t * @internal\n\t */\n\tprivate readonly _initialCapacityBytes?: number;\n\n\t/**\n\t * Maximum capacity in bytes for the shared entity buffer.\n\t * @internal\n\t */\n\tprivate readonly _maxCapacityBytes?: number;\n\n\t/**\n\t * Milliseconds to wait for the directory lock before throwing.\n\t * @internal\n\t */\n\tprivate readonly _mutexTimeoutMs?: number;\n\n\t/**\n\t * Create a new instance of MemoryEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IMemoryEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object<IMemoryEntityStorageConnectorConstructorOptions>(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options),\n\t\t\toptions\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IMemoryEntityStorageConnectorConfig>(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.storageKey),\n\t\t\toptions.config.storageKey\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._storageKey = options.config.storageKey;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\t\tthis._initialCapacityBytes = options.config?.initialCapacityBytes;\n\t\tthis._maxCapacityBytes = options.config?.maxCapacityBytes;\n\t\tthis._mutexTimeoutMs = Coerce.integer(options.config.mutexTimeoutMs);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn MemoryEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\treturn [\n\t\t\t{\n\t\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\tdata: { entityType: this._storageKey }\n\t\t\t}\n\t\t];\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Bootstrap the component by creating and initializing any resources it needs.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the bootstrapping process was successful.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tawait SharedObjectBuffer.create(this._storageKey, {\n\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get an entity.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst index = this.findItem(entities, id, secondaryIndex, finalConditions);\n\t\t\tconst item = index >= 0 ? entities[index] : undefined;\n\n\t\t\tif (Is.objectValue(item)) {\n\t\t\t\treturn {\n\t\t\t\t\tresult: EntityStorageHelper.unPrepareEntity<T>(item, [\n\t\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t])\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Resolves when the entity has been stored.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(MemoryEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\n\t\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t: undefined,\n\t\t\t{ nullBehavior: \"omit\" }\n\t\t);\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst existingIndex = this.findItem(\n\t\t\t\tentities,\n\t\t\t\tprepared[this._primaryKey.property] as string,\n\t\t\t\tundefined,\n\t\t\t\tfinalConditions\n\t\t\t);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tentities[existingIndex] = prepared;\n\t\t\t} else {\n\t\t\t\tentities.push(prepared);\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst preparedItems = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\tIs.stringValue(partitionKey)\n\t\t\t\t\t? [{ property: MemoryEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t\t: undefined,\n\t\t\t\t{ nullBehavior: \"omit\" }\n\t\t\t)\n\t\t);\n\n\t\treturn this.withLock(store => {\n\t\t\tconst indexMap = new Map<string, number>();\n\t\t\tfor (let i = 0; i < store.length; i++) {\n\t\t\t\tconst stored = store[i];\n\t\t\t\tconst storedPartition = ObjectHelper.propertyGet(\n\t\t\t\t\tstored,\n\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t);\n\t\t\t\tif (!Is.stringValue(partitionKey) || storedPartition === partitionKey) {\n\t\t\t\t\tindexMap.set(stored[this._primaryKey.property] as string, i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const prepared of preparedItems) {\n\t\t\t\tconst id = prepared[this._primaryKey.property] as string;\n\t\t\t\tconst existingIndex = indexMap.get(id);\n\t\t\t\tif (existingIndex !== undefined) {\n\t\t\t\t\tstore[existingIndex] = prepared;\n\t\t\t\t} else {\n\t\t\t\t\tconst newIndex = store.push(prepared) - 1;\n\t\t\t\t\tindexMap.set(id, newIndex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { updated: store, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions = conditions ?? [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tconst index = this.findItem(entities, id, undefined, finalConditions);\n\t\t\tif (index >= 0) {\n\t\t\t\tentities.splice(index, 1);\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tMemoryEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\treturn this.withLock(store => {\n\t\t\tlet allEntities = store.slice();\n\n\t\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\t\tconditions: [],\n\t\t\t\tlogicalOperator: LogicalOperator.And\n\t\t\t};\n\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: partitionKey\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!Is.empty(conditions)) {\n\t\t\t\tfinalConditions.conditions.push(EntityStorageHelper.normalizeConditionValues(conditions));\n\t\t\t}\n\n\t\t\tconst resultEntities = [];\n\t\t\tconst finalLimit = limit ?? MemoryEntityStorageConnector._DEFAULT_LIMIT;\n\t\t\tlet nextCursor: string | undefined;\n\n\t\t\tif (allEntities.length > 0) {\n\t\t\t\tconst finalSortKeys = EntitySchemaHelper.buildSortProperties<T>(\n\t\t\t\t\tthis._entitySchema,\n\t\t\t\t\tsortProperties\n\t\t\t\t);\n\t\t\t\tallEntities = EntitySorter.sort(allEntities, finalSortKeys);\n\n\t\t\t\tconst startIndex = Coerce.number(cursor) ?? 0;\n\n\t\t\t\tfor (let i = startIndex; i < allEntities.length; i++) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tEntityConditions.check(allEntities[i], finalConditions) &&\n\t\t\t\t\t\tresultEntities.length < finalLimit\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst entity = Is.arrayValue(properties)\n\t\t\t\t\t\t\t? ObjectHelper.pick(allEntities[i], properties)\n\t\t\t\t\t\t\t: allEntities[i];\n\t\t\t\t\t\tresultEntities.push(\n\t\t\t\t\t\t\tEntityStorageHelper.unPrepareEntity<T>(entity, [\n\t\t\t\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (resultEntities.length >= finalLimit) {\n\t\t\t\t\t\t\tif (i < allEntities.length - 1) {\n\t\t\t\t\t\t\t\tnextCursor = (i + 1).toString();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { result: { entities: resultEntities, cursor: nextCursor } };\n\t\t});\n\t}\n\n\t/**\n\t * Remove all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\treturn this.withLock(entities => {\n\t\t\tif (Is.stringValue(partitionKey)) {\n\t\t\t\tconst filtered = entities.filter(\n\t\t\t\t\titem =>\n\t\t\t\t\t\tObjectHelper.propertyGet(item, MemoryEntityStorageConnector._PARTITION_KEY) !==\n\t\t\t\t\t\tpartitionKey\n\t\t\t\t);\n\t\t\t\treturn { updated: filtered, result: undefined };\n\t\t\t}\n\t\t\treturn { updated: [], result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(MemoryEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: { property: keyof T; value: unknown }[] = [];\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY as keyof T,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst index = this.findItem(entities, id, undefined, finalConditions);\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tentities.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { updated: entities, result: undefined };\n\t\t});\n\t}\n\n\t/**\n\t * Teardown the storage by clearing the underlying shared buffer for this schema.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTearingDown\"\n\t\t});\n\n\t\tawait Mutex.lock(this._storageKey, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });\n\t\ttry {\n\t\t\tSharedObjectBuffer.remove(this._storageKey);\n\t\t} finally {\n\t\t\tMutex.unlock(this._storageKey);\n\t\t}\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: MemoryEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"storeTornDown\"\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\tconditions: [],\n\t\t\tlogicalOperator: LogicalOperator.And\n\t\t};\n\n\t\tif (Is.stringValue(partitionKey)) {\n\t\t\tfinalConditions.conditions.push({\n\t\t\t\tproperty: MemoryEntityStorageConnector._PARTITION_KEY,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: partitionKey\n\t\t\t});\n\t\t}\n\n\t\tif (!Is.empty(conditions)) {\n\t\t\tfinalConditions.conditions.push(EntityStorageHelper.normalizeConditionValues(conditions));\n\t\t}\n\n\t\treturn this.withLock(entities => {\n\t\t\tif (finalConditions.conditions.length === 0) {\n\t\t\t\treturn { result: entities.length };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tresult: entities.filter(item => EntityConditions.check(item, finalConditions)).length\n\t\t\t};\n\t\t});\n\t}\n\n\t/**\n\t * Get all entities in the memory store.\n\t * @returns All stored entities with partition keys removed.\n\t */\n\tpublic async getStore(): Promise<T[]> {\n\t\treturn this.withLock(entities => ({\n\t\t\tresult: entities.map(item =>\n\t\t\t\tEntityStorageHelper.unPrepareEntity<T>(item, [MemoryEntityStorageConnector._PARTITION_KEY])\n\t\t\t)\n\t\t}));\n\t}\n\n\t/**\n\t * Get a unique list of all the context ids from the storage.\n\t * @returns The list of unique context ids.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\treturn this.withLock(entities => {\n\t\t\tconst contextIds: { [id: string]: IContextIds } = {};\n\t\t\tfor (const entity of entities) {\n\t\t\t\tconst partitionId = ObjectHelper.propertyGet(\n\t\t\t\t\tentity,\n\t\t\t\t\tMemoryEntityStorageConnector._PARTITION_KEY\n\t\t\t\t);\n\t\t\t\tif (Is.stringValue(partitionId)) {\n\t\t\t\t\tcontextIds[partitionId] = ContextIdHelper.shortSplit(\n\t\t\t\t\t\tthis._partitionContextIds ?? [],\n\t\t\t\t\t\tpartitionId\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { result: Object.values(contextIds) };\n\t\t});\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration it will use a temporary storage location.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\t// Resolve the target schema name the same way _storageKey is resolved in the constructor.\n\t\tconst targetSchemaEntry = EntitySchemaFactory.get(newEntitySchema);\n\t\tconst targetSchemaName = targetSchemaEntry.type ?? newEntitySchema;\n\n\t\t// When migrating to a different schema, wipe the target buffer so that every\n\t\t// migration starts from an empty store regardless of any previous connector\n\t\t// instances that shared the same schema name.\n\t\tif (targetSchemaName !== this._storageKey) {\n\t\t\tawait Mutex.lock(targetSchemaName, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });\n\t\t\ttry {\n\t\t\t\tSharedObjectBuffer.remove(targetSchemaName);\n\t\t\t} finally {\n\t\t\t\tMutex.unlock(targetSchemaName);\n\t\t\t}\n\t\t}\n\n\t\treturn new MemoryEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tpartitionContextIds: this._partitionContextIds,\n\t\t\tconfig: {\n\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old connector and replacing it with the target connector.\n\t * @param targetConnector The target connector to finalize the migration with.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is finalized.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\treturn targetConnector;\n\t}\n\n\t/**\n\t * Cleanup the migration if a migration fails or needs to be aborted.\n\t * @param targetConnector The target connector to cleanup the migration with.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging the migration progress.\n\t * @returns A promise that resolves when the migration is cleaned up.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<void> {}\n\n\t/**\n\t * Acquires the schema-keyed lock, runs fn with the current entity array, optionally\n\t * writes back a modified array, then releases the lock.\n\t * @param fn The synchronous function to run while the lock is held.\n\t * @returns The result produced by fn.\n\t * @internal\n\t */\n\tprivate async withLock<R>(fn: (entities: T[]) => { updated?: T[]; result: R }): Promise<R> {\n\t\tawait Mutex.lock(this._storageKey, { throwOnTimeout: true, timeoutMs: this._mutexTimeoutMs });\n\t\ttry {\n\t\t\tawait SharedObjectBuffer.create(this._storageKey, {\n\t\t\t\tinitialCapacityBytes: this._initialCapacityBytes,\n\t\t\t\tmaxCapacityBytes: this._maxCapacityBytes\n\t\t\t});\n\t\t\tconst entities = (await SharedObjectBuffer.read<T[]>(this._storageKey)) ?? [];\n\t\t\tconst outcome = fn(entities);\n\t\t\tif (outcome.updated !== undefined) {\n\t\t\t\tawait SharedObjectBuffer.write<T[]>(this._storageKey, outcome.updated);\n\t\t\t}\n\t\t\treturn outcome.result;\n\t\t} finally {\n\t\t\tMutex.unlock(this._storageKey);\n\t\t}\n\t}\n\n\t/**\n\t * Find the item in the provided entity array.\n\t * @param entities The current entity array.\n\t * @param id The id to search for.\n\t * @param secondaryIndex The secondary index to search for.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The index of the item if found or -1.\n\t * @internal\n\t */\n\tprivate findItem(\n\t\tentities: T[],\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): number {\n\t\tconst finalConditions: EntityCondition<T>[] = [];\n\n\t\tif (!Is.empty(secondaryIndex)) {\n\t\t\tfinalConditions.push({\n\t\t\t\tproperty: secondaryIndex as string,\n\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\tvalue: id\n\t\t\t});\n\t\t}\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\tif (finalConditions.length === 0) {\n\t\t\t\tfinalConditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tfinalConditions.push(\n\t\t\t\t...conditions.map(c => ({\n\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: c.value\n\t\t\t\t}))\n\t\t\t);\n\t\t}\n\n\t\tif (finalConditions.length > 0) {\n\t\t\tfor (let i = 0; i < entities.length; i++) {\n\t\t\t\tif (EntityConditions.check(entities[i], { conditions: finalConditions })) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn entities.findIndex(e => e[this._primaryKey.property] === id);\n\t\t}\n\n\t\treturn -1;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IMemoryEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IMemoryEntityStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the Memory Entity Storage Connector.\n */\nexport interface IMemoryEntityStorageConnectorConfig {\n\t/**\n\t * Key to use for the shared buffer instead of the entity schema type.\n\t * Use this to give two connectors with the same entitySchema separate storage.\n\t */\n\tstorageKey: string;\n\n\t/**\n\t * Initial capacity in bytes for the shared entity buffer.\n\t * @default 16 MiB.\n\t */\n\tinitialCapacityBytes?: number;\n\n\t/**\n\t * Maximum JSON payload size in bytes for the shared entity buffer.\n\t * @default 256 MiB.\n\t */\n\tmaxCapacityBytes?: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"IMemoryEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/IMemoryEntityStorageConnectorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the Memory Entity Storage Connector.\n */\nexport interface IMemoryEntityStorageConnectorConfig {\n\t/**\n\t * Key to use for the shared buffer instead of the entity schema type.\n\t * Use this to give two connectors with the same entitySchema separate storage.\n\t */\n\tstorageKey: string;\n\n\t/**\n\t * Initial capacity in bytes for the shared entity buffer.\n\t * @default 16 MiB.\n\t */\n\tinitialCapacityBytes?: number;\n\n\t/**\n\t * Maximum JSON payload size in bytes for the shared entity buffer.\n\t * @default 256 MiB.\n\t */\n\tmaxCapacityBytes?: number;\n\n\t/**\n\t * Maximum milliseconds to wait for the per-directory write lock before throwing.\n\t */\n\tmutexTimeoutMs?: number;\n}\n"]}
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.33](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-memory-v0.0.3-next.32...entity-storage-connector-memory-v0.0.3-next.33) (2026-06-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* dynamodb get with condition ignores primary key ([d2d0ec2](https://github.com/iotaledger/twin-entity-storage/commit/d2d0ec21023bc22f0e5a35c2d49396d90b42a4ce))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.32 to 0.0.3-next.33
|
|
16
|
+
|
|
17
|
+
## [0.0.3-next.32](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-memory-v0.0.3-next.31...entity-storage-connector-memory-v0.0.3-next.32) (2026-06-16)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* dynamodb query gsi ([#140](https://github.com/iotaledger/twin-entity-storage/issues/140)) ([45b56d6](https://github.com/iotaledger/twin-entity-storage/commit/45b56d6260c9876012030cc6c85026ea84aebff5))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.31 to 0.0.3-next.32
|
|
30
|
+
|
|
3
31
|
## [0.0.3-next.31](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-memory-v0.0.3-next.30...entity-storage-connector-memory-v0.0.3-next.31) (2026-06-15)
|
|
4
32
|
|
|
5
33
|
|
|
@@ -38,3 +38,11 @@ Maximum JSON payload size in bytes for the shared entity buffer.
|
|
|
38
38
|
```ts
|
|
39
39
|
256 MiB.
|
|
40
40
|
```
|
|
41
|
+
|
|
42
|
+
***
|
|
43
|
+
|
|
44
|
+
### mutexTimeoutMs? {#mutextimeoutms}
|
|
45
|
+
|
|
46
|
+
> `optional` **mutexTimeoutMs?**: `number`
|
|
47
|
+
|
|
48
|
+
Maximum milliseconds to wait for the per-directory write lock before throwing.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-memory",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.33",
|
|
4
4
|
"description": "In-memory connector for local development, testing and short-lived workloads.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@twin.org/context": "next",
|
|
18
18
|
"@twin.org/core": "next",
|
|
19
19
|
"@twin.org/entity": "next",
|
|
20
|
-
"@twin.org/entity-storage-models": "0.0.3-next.
|
|
20
|
+
"@twin.org/entity-storage-models": "0.0.3-next.33",
|
|
21
21
|
"@twin.org/logging-models": "next",
|
|
22
22
|
"@twin.org/nameof": "next"
|
|
23
23
|
},
|