@twin.org/entity-storage-connector-synchronised 0.0.2-next.9 → 0.0.3-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/ISynchronisedEntityStorageConnectorConfig.js +4 -0
- package/dist/es/models/ISynchronisedEntityStorageConnectorConfig.js.map +1 -0
- package/dist/es/models/ISynchronisedEntityStorageConnectorConstructorOptions.js +2 -0
- package/dist/es/models/ISynchronisedEntityStorageConnectorConstructorOptions.js.map +1 -0
- package/dist/{esm/index.mjs → es/synchronisedEntityStorageConnector.js} +84 -58
- package/dist/es/synchronisedEntityStorageConnector.js.map +1 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/ISynchronisedEntityStorageConnectorConstructorOptions.d.ts +1 -1
- package/dist/types/synchronisedEntityStorageConnector.d.ts +11 -7
- package/docs/changelog.md +30 -0
- package/docs/reference/classes/SynchronisedEntityStorageConnector.md +24 -16
- package/locales/en.json +8 -1
- package/package.json +14 -11
- package/dist/cjs/index.cjs +0 -313
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./synchronisedEntityStorageConnector.js";
|
|
4
|
+
export * from "./models/ISynchronisedEntityStorageConnectorConfig.js";
|
|
5
|
+
export * from "./models/ISynchronisedEntityStorageConnectorConstructorOptions.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,yCAAyC,CAAC;AACxD,cAAc,uDAAuD,CAAC;AACtE,cAAc,mEAAmE,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./synchronisedEntityStorageConnector.js\";\nexport * from \"./models/ISynchronisedEntityStorageConnectorConfig.js\";\nexport * from \"./models/ISynchronisedEntityStorageConnectorConstructorOptions.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISynchronisedEntityStorageConnectorConfig.js","sourceRoot":"","sources":["../../../src/models/ISynchronisedEntityStorageConnectorConfig.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 Synchronised Entity Storage Connector.\n */\nexport interface ISynchronisedEntityStorageConnectorConfig {\n\t/**\n\t * The storage key for the synchronised entity storage connector.\n\t * Will default to kebab cased entity schema name.\n\t */\n\tstorageKey?: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISynchronisedEntityStorageConnectorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ISynchronisedEntityStorageConnectorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ISynchronisedEntityStorageConnectorConfig } from \"./ISynchronisedEntityStorageConnectorConfig.js\";\n\n/**\n * Options for the Synchronised Entity Storage Connector constructor.\n */\nexport interface ISynchronisedEntityStorageConnectorConstructorOptions {\n\t/**\n\t * The name of the entity schema.\n\t */\n\tentitySchema: string;\n\n\t/**\n\t * The entity storage connector type to use for actual data.\n\t */\n\tentityStorageConnectorType: string;\n\n\t/**\n\t * The event bus component type.\n\t * @default event-bus\n\t */\n\teventBusComponentType?: string;\n\n\t/**\n\t * The configuration for the connector.\n\t */\n\tconfig?: ISynchronisedEntityStorageConnectorConfig;\n}\n"]}
|
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
import { Guards, StringHelper, Is, GeneralError, ComponentFactory } from '@twin.org/core';
|
|
2
|
-
import { EntitySchemaFactory, EntitySchemaHelper, ComparisonOperator, SortDirection } from '@twin.org/entity';
|
|
3
|
-
import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
|
|
4
|
-
import { SynchronisedStorageTopics, SyncChangeOperation, SyncNodeIdentityMode } from '@twin.org/synchronised-storage-models';
|
|
5
|
-
|
|
6
1
|
// Copyright 2024 IOTA Stiftung.
|
|
7
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import { ContextIdHelper, ContextIdKeys, ContextIdStore } from "@twin.org/context";
|
|
4
|
+
import { ComponentFactory, GeneralError, Guards, Is, StringHelper } from "@twin.org/core";
|
|
5
|
+
import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, SortDirection } from "@twin.org/entity";
|
|
6
|
+
import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
|
|
7
|
+
import { SyncChangeOperation, SynchronisedStorageTopics, SyncNodeIdMode } from "@twin.org/synchronised-storage-models";
|
|
8
8
|
/**
|
|
9
9
|
* Class for performing entity storage operations in synchronised storage.
|
|
10
10
|
*/
|
|
11
|
-
class SynchronisedEntityStorageConnector {
|
|
11
|
+
export class SynchronisedEntityStorageConnector {
|
|
12
12
|
/**
|
|
13
13
|
* Runtime name for the class.
|
|
14
14
|
*/
|
|
15
|
-
CLASS_NAME = "SynchronisedEntityStorageConnector";
|
|
15
|
+
static CLASS_NAME = "SynchronisedEntityStorageConnector";
|
|
16
|
+
/**
|
|
17
|
+
* Fixed name for node id properties.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
static _PROP_NAME_NODE_ID = "nodeId";
|
|
21
|
+
/**
|
|
22
|
+
* Fixed name for date modified properties.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
static _PROP_NAME_DATE_MODIFIED = "dateModified";
|
|
26
|
+
/**
|
|
27
|
+
* Fixed name for id properties.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
static _PROP_NAME_ID = "id";
|
|
16
31
|
/**
|
|
17
32
|
* The schema for the entity.
|
|
18
33
|
* @internal
|
|
@@ -42,32 +57,32 @@ class SynchronisedEntityStorageConnector {
|
|
|
42
57
|
* The node identity.
|
|
43
58
|
* @internal
|
|
44
59
|
*/
|
|
45
|
-
|
|
60
|
+
_nodeId;
|
|
46
61
|
/**
|
|
47
62
|
* Create a new instance of SynchronisedEntityStorageConnector.
|
|
48
63
|
* @param options The options for the connector.
|
|
49
64
|
*/
|
|
50
65
|
constructor(options) {
|
|
51
|
-
Guards.object(
|
|
52
|
-
Guards.stringValue(
|
|
53
|
-
Guards.stringValue(
|
|
66
|
+
Guards.object(SynchronisedEntityStorageConnector.CLASS_NAME, "options", options);
|
|
67
|
+
Guards.stringValue(SynchronisedEntityStorageConnector.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
68
|
+
Guards.stringValue(SynchronisedEntityStorageConnector.CLASS_NAME, "options.entityStorageConnectorType", options.entityStorageConnectorType);
|
|
54
69
|
this._entitySchema = EntitySchemaFactory.get(options.entitySchema);
|
|
55
70
|
this._storageKey = options?.config?.storageKey ?? StringHelper.kebabCase(options.entitySchema);
|
|
56
71
|
this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
57
72
|
const requiredProperties = [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
SynchronisedEntityStorageConnector._PROP_NAME_ID,
|
|
74
|
+
SynchronisedEntityStorageConnector._PROP_NAME_NODE_ID,
|
|
75
|
+
SynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED
|
|
61
76
|
];
|
|
62
77
|
for (const requiredProperty of requiredProperties) {
|
|
63
78
|
const foundProperty = this._entitySchema.properties?.find(prop => prop.property === requiredProperty);
|
|
64
79
|
if (Is.empty(foundProperty)) {
|
|
65
|
-
throw new GeneralError(
|
|
80
|
+
throw new GeneralError(SynchronisedEntityStorageConnector.CLASS_NAME, "missingRequiredProperty", { requiredProperty });
|
|
66
81
|
}
|
|
67
82
|
else if (Is.empty(foundProperty.isPrimary) &&
|
|
68
83
|
Is.empty(foundProperty.isSecondary) &&
|
|
69
84
|
Is.empty(foundProperty.sortDirection)) {
|
|
70
|
-
throw new GeneralError(
|
|
85
|
+
throw new GeneralError(SynchronisedEntityStorageConnector.CLASS_NAME, "missingRequiredPropertySort", {
|
|
71
86
|
requiredProperty
|
|
72
87
|
});
|
|
73
88
|
}
|
|
@@ -75,6 +90,13 @@ class SynchronisedEntityStorageConnector {
|
|
|
75
90
|
this._entityStorageConnector = EntityStorageConnectorFactory.get(options.entityStorageConnectorType);
|
|
76
91
|
this._eventBusComponent = ComponentFactory.get(options.eventBusComponentType ?? "event-bus");
|
|
77
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns the class name of the component.
|
|
95
|
+
* @returns The class name of the component.
|
|
96
|
+
*/
|
|
97
|
+
className() {
|
|
98
|
+
return SynchronisedEntityStorageConnector.CLASS_NAME;
|
|
99
|
+
}
|
|
78
100
|
/**
|
|
79
101
|
* Get the schema for the entities.
|
|
80
102
|
* @returns The schema for the entities.
|
|
@@ -84,17 +106,18 @@ class SynchronisedEntityStorageConnector {
|
|
|
84
106
|
}
|
|
85
107
|
/**
|
|
86
108
|
* The component needs to be started when the node is initialized.
|
|
87
|
-
* @param nodeIdentity The identity of the node starting the component.
|
|
88
109
|
* @param nodeLoggingComponentType The node logging component type.
|
|
89
110
|
* @returns Nothing.
|
|
90
111
|
*/
|
|
91
|
-
async start(
|
|
92
|
-
|
|
112
|
+
async start(nodeLoggingComponentType) {
|
|
113
|
+
const contextIds = await ContextIdStore.getContextIds();
|
|
114
|
+
ContextIdHelper.guard(contextIds, ContextIdKeys.Node);
|
|
115
|
+
this._nodeId = contextIds[ContextIdKeys.Node];
|
|
93
116
|
// Tell the synchronised storage about this storage key
|
|
94
117
|
await this._eventBusComponent.publish(SynchronisedStorageTopics.RegisterStorageKey, {
|
|
95
118
|
storageKey: this._storageKey
|
|
96
119
|
});
|
|
97
|
-
this.handleEventBusMessages();
|
|
120
|
+
await this.handleEventBusMessages();
|
|
98
121
|
}
|
|
99
122
|
/**
|
|
100
123
|
* Get an entity.
|
|
@@ -104,7 +127,7 @@ class SynchronisedEntityStorageConnector {
|
|
|
104
127
|
* @returns The object if it can be found or undefined.
|
|
105
128
|
*/
|
|
106
129
|
async get(id, secondaryIndex, conditions) {
|
|
107
|
-
Guards.stringValue(
|
|
130
|
+
Guards.stringValue(SynchronisedEntityStorageConnector.CLASS_NAME, "id", id);
|
|
108
131
|
return this._entityStorageConnector.get(id, secondaryIndex, conditions);
|
|
109
132
|
}
|
|
110
133
|
/**
|
|
@@ -114,17 +137,17 @@ class SynchronisedEntityStorageConnector {
|
|
|
114
137
|
* @returns The id of the entity.
|
|
115
138
|
*/
|
|
116
139
|
async set(entity, conditions) {
|
|
117
|
-
Guards.object(
|
|
118
|
-
if (Is.stringValue(this.
|
|
119
|
-
// Make sure the entity has the required properties
|
|
140
|
+
Guards.object(SynchronisedEntityStorageConnector.CLASS_NAME, "entity", entity);
|
|
141
|
+
if (Is.stringValue(this._nodeId)) {
|
|
142
|
+
// Make sure the entity has the required properties populated
|
|
120
143
|
entity.dateModified = new Date(Date.now()).toISOString();
|
|
121
|
-
entity.
|
|
144
|
+
entity.nodeId = this._nodeId;
|
|
122
145
|
await this._entityStorageConnector.set(entity, conditions);
|
|
123
146
|
// Tell the synchronised storage about the entity changes
|
|
124
147
|
await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
|
|
125
148
|
storageKey: this._storageKey,
|
|
126
149
|
operation: SyncChangeOperation.Set,
|
|
127
|
-
|
|
150
|
+
nodeId: this._nodeId,
|
|
128
151
|
id: entity[this._primaryKey.property]
|
|
129
152
|
});
|
|
130
153
|
}
|
|
@@ -136,14 +159,14 @@ class SynchronisedEntityStorageConnector {
|
|
|
136
159
|
* @returns Nothing.
|
|
137
160
|
*/
|
|
138
161
|
async remove(id, conditions) {
|
|
139
|
-
Guards.stringValue(
|
|
140
|
-
if (Is.stringValue(this.
|
|
162
|
+
Guards.stringValue(SynchronisedEntityStorageConnector.CLASS_NAME, "id", id);
|
|
163
|
+
if (Is.stringValue(this._nodeId)) {
|
|
141
164
|
await this._entityStorageConnector.remove(id, conditions);
|
|
142
165
|
// Tell the synchronised storage about the entity removal
|
|
143
166
|
await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
|
|
144
167
|
storageKey: this._storageKey,
|
|
145
168
|
operation: SyncChangeOperation.Delete,
|
|
146
|
-
|
|
169
|
+
nodeId: this._nodeId,
|
|
147
170
|
id
|
|
148
171
|
});
|
|
149
172
|
}
|
|
@@ -153,37 +176,38 @@ class SynchronisedEntityStorageConnector {
|
|
|
153
176
|
* @param conditions The conditions to match for the entities.
|
|
154
177
|
* @param sortProperties The optional sort order.
|
|
155
178
|
* @param properties The optional properties to return, defaults to all.
|
|
156
|
-
* @param cursor The cursor to request the next
|
|
157
|
-
* @param
|
|
179
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
180
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
158
181
|
* @returns All the entities for the storage matching the conditions,
|
|
159
182
|
* and a cursor which can be used to request more entities.
|
|
160
183
|
*/
|
|
161
|
-
async query(conditions, sortProperties, properties, cursor,
|
|
162
|
-
|
|
184
|
+
async query(conditions, sortProperties, properties, cursor, limit) {
|
|
185
|
+
// We deliberately skip the partition key as we want to query all partitions in synchronised storage
|
|
186
|
+
return this._entityStorageConnector.query(conditions, sortProperties, properties, cursor, limit);
|
|
163
187
|
}
|
|
164
188
|
/**
|
|
165
189
|
* Handle the event bus messages.
|
|
166
190
|
* @internal
|
|
167
191
|
*/
|
|
168
|
-
handleEventBusMessages() {
|
|
192
|
+
async handleEventBusMessages() {
|
|
169
193
|
// When the synchronised storage requests an item, we need to provide it
|
|
170
|
-
this._eventBusComponent.subscribe(SynchronisedStorageTopics.LocalItemRequest, async (params) => {
|
|
194
|
+
await this._eventBusComponent.subscribe(SynchronisedStorageTopics.LocalItemRequest, async (params) => {
|
|
171
195
|
await this.handleLocalItemRequest(params);
|
|
172
196
|
});
|
|
173
197
|
// When the synchronised storage requests a batch, we need to provide it
|
|
174
|
-
this._eventBusComponent.subscribe(SynchronisedStorageTopics.BatchRequest, async (params) => {
|
|
198
|
+
await this._eventBusComponent.subscribe(SynchronisedStorageTopics.BatchRequest, async (params) => {
|
|
175
199
|
await this.handleBatchRequest(params);
|
|
176
200
|
});
|
|
177
201
|
// Subscribe to remote item set events from the synchronised storage and update the local storage
|
|
178
|
-
this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemSet, async (params) => {
|
|
202
|
+
await this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemSet, async (params) => {
|
|
179
203
|
await this.handleRemoteItemSet(params);
|
|
180
204
|
});
|
|
181
205
|
// Subscribe to remote item remove events from the synchronised storage and update the local storage
|
|
182
|
-
this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemRemove, async (params) => {
|
|
206
|
+
await this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemRemove, async (params) => {
|
|
183
207
|
await this.handleRemoteItemRemove(params);
|
|
184
208
|
});
|
|
185
209
|
// Subscribe to resets from the synchronised storage and update the local storage
|
|
186
|
-
this._eventBusComponent.subscribe(SynchronisedStorageTopics.Reset, async (params) => {
|
|
210
|
+
await this._eventBusComponent.subscribe(SynchronisedStorageTopics.Reset, async (params) => {
|
|
187
211
|
await this.handleReset(params);
|
|
188
212
|
});
|
|
189
213
|
}
|
|
@@ -201,7 +225,7 @@ class SynchronisedEntityStorageConnector {
|
|
|
201
225
|
}
|
|
202
226
|
catch { }
|
|
203
227
|
// Publish the item response with the entity
|
|
204
|
-
this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemResponse, {
|
|
228
|
+
await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemResponse, {
|
|
205
229
|
storageKey: this._storageKey,
|
|
206
230
|
id: event.data.id,
|
|
207
231
|
entity
|
|
@@ -217,8 +241,7 @@ class SynchronisedEntityStorageConnector {
|
|
|
217
241
|
// Only set the item if it matches the storage key
|
|
218
242
|
// and it is from another node, remote updates can not change data for this node
|
|
219
243
|
// That must be done via the regular entity storage methods
|
|
220
|
-
if (event.data.storageKey === this._storageKey &&
|
|
221
|
-
event.data.entity.nodeIdentity !== this._nodeIdentity) {
|
|
244
|
+
if (event.data.storageKey === this._storageKey && event.data.entity.nodeId !== this._nodeId) {
|
|
222
245
|
await this._entityStorageConnector.set(event.data.entity);
|
|
223
246
|
}
|
|
224
247
|
}
|
|
@@ -231,8 +254,7 @@ class SynchronisedEntityStorageConnector {
|
|
|
231
254
|
// Only remove the item if it matches the storage key
|
|
232
255
|
// and it is from another node, remote updates can not change data for this node
|
|
233
256
|
// That must be done via the regular entity storage methods
|
|
234
|
-
if (params.data.storageKey === this._storageKey &&
|
|
235
|
-
params.data.nodeIdentity !== this._nodeIdentity) {
|
|
257
|
+
if (params.data.storageKey === this._storageKey && params.data.nodeId !== this._nodeId) {
|
|
236
258
|
await this._entityStorageConnector.remove(params.data.id);
|
|
237
259
|
}
|
|
238
260
|
}
|
|
@@ -249,20 +271,25 @@ class SynchronisedEntityStorageConnector {
|
|
|
249
271
|
const condition = {
|
|
250
272
|
conditions: []
|
|
251
273
|
};
|
|
252
|
-
if (event.data.requestMode ===
|
|
253
|
-
event.data.requestMode ===
|
|
274
|
+
if (event.data.requestMode === SyncNodeIdMode.Local ||
|
|
275
|
+
event.data.requestMode === SyncNodeIdMode.Remote) {
|
|
254
276
|
condition.conditions.push({
|
|
255
|
-
property:
|
|
256
|
-
value: this.
|
|
257
|
-
comparison: event.data.requestMode ===
|
|
277
|
+
property: SynchronisedEntityStorageConnector._PROP_NAME_NODE_ID,
|
|
278
|
+
value: this._nodeId,
|
|
279
|
+
comparison: event.data.requestMode === SyncNodeIdMode.Local
|
|
258
280
|
? ComparisonOperator.Equals
|
|
259
281
|
: ComparisonOperator.NotEquals
|
|
260
282
|
});
|
|
261
283
|
}
|
|
262
|
-
const result = await this._entityStorageConnector.query(condition, [
|
|
284
|
+
const result = await this._entityStorageConnector.query(condition, [
|
|
285
|
+
{
|
|
286
|
+
property: SynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED,
|
|
287
|
+
sortDirection: SortDirection.Ascending
|
|
288
|
+
}
|
|
289
|
+
], undefined, cursor, event.data.batchSize);
|
|
263
290
|
cursor = result.cursor;
|
|
264
291
|
// Publish the batch response with the entities
|
|
265
|
-
this._eventBusComponent.publish(SynchronisedStorageTopics.BatchResponse, {
|
|
292
|
+
await this._eventBusComponent.publish(SynchronisedStorageTopics.BatchResponse, {
|
|
266
293
|
storageKey: this._storageKey,
|
|
267
294
|
entities: result.entities,
|
|
268
295
|
lastEntry: !Is.stringValue(cursor)
|
|
@@ -286,12 +313,12 @@ class SynchronisedEntityStorageConnector {
|
|
|
286
313
|
conditions: []
|
|
287
314
|
};
|
|
288
315
|
// Depending on the reset mode we can filter the entities to remove
|
|
289
|
-
if (event.data.resetMode ===
|
|
290
|
-
event.data.resetMode ===
|
|
316
|
+
if (event.data.resetMode === SyncNodeIdMode.Local ||
|
|
317
|
+
event.data.resetMode === SyncNodeIdMode.Remote) {
|
|
291
318
|
condition.conditions.push({
|
|
292
|
-
property: "
|
|
293
|
-
value: this.
|
|
294
|
-
comparison: event.data.resetMode ===
|
|
319
|
+
property: "nodeId",
|
|
320
|
+
value: this._nodeId,
|
|
321
|
+
comparison: event.data.resetMode === SyncNodeIdMode.Local
|
|
295
322
|
? ComparisonOperator.Equals
|
|
296
323
|
: ComparisonOperator.NotEquals
|
|
297
324
|
});
|
|
@@ -307,5 +334,4 @@ class SynchronisedEntityStorageConnector {
|
|
|
307
334
|
}
|
|
308
335
|
}
|
|
309
336
|
}
|
|
310
|
-
|
|
311
|
-
export { SynchronisedEntityStorageConnector };
|
|
337
|
+
//# sourceMappingURL=synchronisedEntityStorageConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synchronisedEntityStorageConnector.js","sourceRoot":"","sources":["../../src/synchronisedEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { ContextIdHelper, ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, GeneralError, Guards, Is, StringHelper } from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport type { IEvent, IEventBusComponent } from \"@twin.org/event-bus-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\ttype ISyncBatchRequest,\n\ttype ISyncBatchResponse,\n\ttype ISynchronisedEntity,\n\ttype ISyncItemChange,\n\ttype ISyncItemRemove,\n\ttype ISyncItemRequest,\n\ttype ISyncItemResponse,\n\ttype ISyncItemSet,\n\ttype ISyncRegisterStorageKey,\n\ttype ISyncReset,\n\tSyncChangeOperation,\n\tSynchronisedStorageTopics,\n\tSyncNodeIdMode\n} from \"@twin.org/synchronised-storage-models\";\nimport type { ISynchronisedEntityStorageConnectorConstructorOptions } from \"./models/ISynchronisedEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations in synchronised storage.\n */\nexport class SynchronisedEntityStorageConnector<T extends ISynchronisedEntity = ISynchronisedEntity>\n\timplements IEntityStorageConnector<T>\n{\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<SynchronisedEntityStorageConnector>();\n\n\t/**\n\t * Fixed name for node id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_NODE_ID = \"nodeId\";\n\n\t/**\n\t * Fixed name for date modified properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_DATE_MODIFIED = \"dateModified\";\n\n\t/**\n\t * Fixed name for id properties.\n\t * @internal\n\t */\n\tprivate static readonly _PROP_NAME_ID = \"id\";\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 primary key for the entity schema.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The storage key for the entity.\n\t * @internal\n\t */\n\tprivate readonly _storageKey: string;\n\n\t/**\n\t * The entity storage connector to use for actual data.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnector: IEntityStorageConnector<T>;\n\n\t/**\n\t * The event bus component.\n\t * @internal\n\t */\n\tprivate readonly _eventBusComponent: IEventBusComponent;\n\n\t/**\n\t * The node identity.\n\t * @internal\n\t */\n\tprivate _nodeId?: string;\n\n\t/**\n\t * Create a new instance of SynchronisedEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: ISynchronisedEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object<ISynchronisedEntityStorageConnectorConstructorOptions>(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options),\n\t\t\toptions\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entityStorageConnectorType),\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._storageKey = options?.config?.storageKey ?? StringHelper.kebabCase(options.entitySchema);\n\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);\n\n\t\tconst requiredProperties: (keyof ISynchronisedEntity)[] = [\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_ID,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_NODE_ID,\n\t\t\tSynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED\n\t\t];\n\n\t\tfor (const requiredProperty of requiredProperties) {\n\t\t\tconst foundProperty = this._entitySchema.properties?.find(\n\t\t\t\tprop => prop.property === requiredProperty\n\t\t\t);\n\t\t\tif (Is.empty(foundProperty)) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredProperty\",\n\t\t\t\t\t{ requiredProperty }\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tIs.empty(foundProperty.isPrimary) &&\n\t\t\t\tIs.empty(foundProperty.isSecondary) &&\n\t\t\t\tIs.empty(foundProperty.sortDirection)\n\t\t\t) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tSynchronisedEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"missingRequiredPropertySort\",\n\t\t\t\t\t{\n\t\t\t\t\t\trequiredProperty\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions.entityStorageConnectorType\n\t\t);\n\n\t\tthis._eventBusComponent = ComponentFactory.get(options.eventBusComponentType ?? \"event-bus\");\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 SynchronisedEntityStorageConnector.CLASS_NAME;\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 * The component needs to be started when the node is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Node);\n\t\tthis._nodeId = contextIds[ContextIdKeys.Node];\n\n\t\t// Tell the synchronised storage about this storage key\n\t\tawait this._eventBusComponent.publish<ISyncRegisterStorageKey>(\n\t\t\tSynchronisedStorageTopics.RegisterStorageKey,\n\t\t\t{\n\t\t\t\tstorageKey: this._storageKey\n\t\t\t}\n\t\t);\n\n\t\tawait this.handleEventBusMessages();\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\treturn this._entityStorageConnector.get(id, secondaryIndex, conditions);\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 The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\t// Make sure the entity has the required properties populated\n\t\t\tentity.dateModified = new Date(Date.now()).toISOString();\n\t\t\tentity.nodeId = this._nodeId;\n\n\t\t\tawait this._entityStorageConnector.set(entity, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity changes\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Set,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid: entity[this._primaryKey.property] as string\n\t\t\t\t}\n\t\t\t);\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(SynchronisedEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tif (Is.stringValue(this._nodeId)) {\n\t\t\tawait this._entityStorageConnector.remove(id, conditions);\n\n\t\t\t// Tell the synchronised storage about the entity removal\n\t\t\tawait this._eventBusComponent.publish<ISyncItemChange>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemChange,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\toperation: SyncChangeOperation.Delete,\n\t\t\t\t\tnodeId: this._nodeId,\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t);\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\t// We deliberately skip the partition key as we want to query all partitions in synchronised storage\n\t\treturn this._entityStorageConnector.query(\n\t\t\tconditions,\n\t\t\tsortProperties,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\t}\n\n\t/**\n\t * Handle the event bus messages.\n\t * @internal\n\t */\n\tprivate async handleEventBusMessages(): Promise<void> {\n\t\t// When the synchronised storage requests an item, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRequest>(\n\t\t\tSynchronisedStorageTopics.LocalItemRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleLocalItemRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// When the synchronised storage requests a batch, we need to provide it\n\t\tawait this._eventBusComponent.subscribe<ISyncBatchRequest>(\n\t\t\tSynchronisedStorageTopics.BatchRequest,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleBatchRequest(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item set events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemSet>(\n\t\t\tSynchronisedStorageTopics.RemoteItemSet,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemSet(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to remote item remove events from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncItemRemove>(\n\t\t\tSynchronisedStorageTopics.RemoteItemRemove,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleRemoteItemRemove(params);\n\t\t\t}\n\t\t);\n\n\t\t// Subscribe to resets from the synchronised storage and update the local storage\n\t\tawait this._eventBusComponent.subscribe<ISyncReset>(\n\t\t\tSynchronisedStorageTopics.Reset,\n\t\t\tasync params => {\n\t\t\t\tawait this.handleReset(params);\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Handle a local item request.\n\t * @param event The request parameters\n\t * @internal\n\t */\n\tprivate async handleLocalItemRequest(event: IEvent<ISyncItemRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet entity: T | undefined;\n\t\t\ttry {\n\t\t\t\tentity = await this._entityStorageConnector.get(event.data.id);\n\t\t\t} catch {}\n\n\t\t\t// Publish the item response with the entity\n\t\t\tawait this._eventBusComponent.publish<ISyncItemResponse>(\n\t\t\t\tSynchronisedStorageTopics.LocalItemResponse,\n\t\t\t\t{\n\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\tid: event.data.id,\n\t\t\t\t\tentity\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item set event.\n\t * @param event The event parameters\n\t * @internal\n\t */\n\tprivate async handleRemoteItemSet(event: IEvent<ISyncItemSet>): Promise<void> {\n\t\t// Only set the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (event.data.storageKey === this._storageKey && event.data.entity.nodeId !== this._nodeId) {\n\t\t\tawait this._entityStorageConnector.set(event.data.entity as T);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a remote item remove event.\n\t * @param params The event parameters\n\t * @internal\n\t */\n\tprivate async handleRemoteItemRemove(params: IEvent<ISyncItemRemove>): Promise<void> {\n\t\t// Only remove the item if it matches the storage key\n\t\t// and it is from another node, remote updates can not change data for this node\n\t\t// That must be done via the regular entity storage methods\n\t\tif (params.data.storageKey === this._storageKey && params.data.nodeId !== this._nodeId) {\n\t\t\tawait this._entityStorageConnector.remove(params.data.id);\n\t\t}\n\t}\n\n\t/**\n\t * Handle a batch request.\n\t * @param event The request parameters\n\t * @internal\n\t */\n\tprivate async handleBatchRequest(event: IEvent<ISyncBatchRequest>): Promise<void> {\n\t\t// Only handle the request if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\t\t\t\tif (\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_NODE_ID,\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.requestMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproperty: SynchronisedEntityStorageConnector._PROP_NAME_DATE_MODIFIED,\n\t\t\t\t\t\t\tsortDirection: SortDirection.Ascending\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor,\n\t\t\t\t\tevent.data.batchSize\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\n\t\t\t\t// Publish the batch response with the entities\n\t\t\t\tawait this._eventBusComponent.publish<ISyncBatchResponse>(\n\t\t\t\t\tSynchronisedStorageTopics.BatchResponse,\n\t\t\t\t\t{\n\t\t\t\t\t\tstorageKey: this._storageKey,\n\t\t\t\t\t\tentities: result.entities as T[],\n\t\t\t\t\t\tlastEntry: !Is.stringValue(cursor)\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} while (Is.stringValue(cursor));\n\t\t}\n\t}\n\n\t/**\n\t * Handle a reset event.\n\t * @param event The event parameters\n\t * @internal\n\t */\n\tprivate async handleReset(event: IEvent<ISyncReset>): Promise<void> {\n\t\t// Only reset the storage if it matches the storage key\n\t\tif (event.data.storageKey === this._storageKey) {\n\t\t\tlet cursor;\n\t\t\tlet toRemove: string[] = [];\n\n\t\t\t// Build a list of the ids to remove\n\t\t\tdo {\n\t\t\t\tconst condition: EntityCondition<T> = {\n\t\t\t\t\tconditions: []\n\t\t\t\t};\n\n\t\t\t\t// Depending on the reset mode we can filter the entities to remove\n\t\t\t\tif (\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local ||\n\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Remote\n\t\t\t\t) {\n\t\t\t\t\tcondition.conditions.push({\n\t\t\t\t\t\tproperty: \"nodeId\",\n\t\t\t\t\t\tvalue: this._nodeId,\n\t\t\t\t\t\tcomparison:\n\t\t\t\t\t\t\tevent.data.resetMode === SyncNodeIdMode.Local\n\t\t\t\t\t\t\t\t? ComparisonOperator.Equals\n\t\t\t\t\t\t\t\t: ComparisonOperator.NotEquals\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tcondition,\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\tcursor\n\t\t\t\t);\n\n\t\t\t\tcursor = result.cursor;\n\t\t\t\ttoRemove = toRemove.concat(result.entities.map(entity => (entity as T).id));\n\t\t\t} while (Is.stringValue(cursor));\n\n\t\t\t// Remove the entities\n\t\t\tfor (let i = 0; i < toRemove.length; i++) {\n\t\t\t\tawait this.remove(toRemove[i]);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./synchronisedEntityStorageConnector";
|
|
2
|
-
export * from "./models/ISynchronisedEntityStorageConnectorConfig";
|
|
3
|
-
export * from "./models/ISynchronisedEntityStorageConnectorConstructorOptions";
|
|
1
|
+
export * from "./synchronisedEntityStorageConnector.js";
|
|
2
|
+
export * from "./models/ISynchronisedEntityStorageConnectorConfig.js";
|
|
3
|
+
export * from "./models/ISynchronisedEntityStorageConnectorConstructorOptions.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ISynchronisedEntityStorageConnectorConfig } from "./ISynchronisedEntityStorageConnectorConfig";
|
|
1
|
+
import type { ISynchronisedEntityStorageConnectorConfig } from "./ISynchronisedEntityStorageConnectorConfig.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for the Synchronised Entity Storage Connector constructor.
|
|
4
4
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type EntityCondition, type IEntitySchema, SortDirection } from "@twin.org/entity";
|
|
2
2
|
import { type IEntityStorageConnector } from "@twin.org/entity-storage-models";
|
|
3
3
|
import { type ISynchronisedEntity } from "@twin.org/synchronised-storage-models";
|
|
4
|
-
import type { ISynchronisedEntityStorageConnectorConstructorOptions } from "./models/ISynchronisedEntityStorageConnectorConstructorOptions";
|
|
4
|
+
import type { ISynchronisedEntityStorageConnectorConstructorOptions } from "./models/ISynchronisedEntityStorageConnectorConstructorOptions.js";
|
|
5
5
|
/**
|
|
6
6
|
* Class for performing entity storage operations in synchronised storage.
|
|
7
7
|
*/
|
|
@@ -9,12 +9,17 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
|
|
|
9
9
|
/**
|
|
10
10
|
* Runtime name for the class.
|
|
11
11
|
*/
|
|
12
|
-
readonly CLASS_NAME: string;
|
|
12
|
+
static readonly CLASS_NAME: string;
|
|
13
13
|
/**
|
|
14
14
|
* Create a new instance of SynchronisedEntityStorageConnector.
|
|
15
15
|
* @param options The options for the connector.
|
|
16
16
|
*/
|
|
17
17
|
constructor(options: ISynchronisedEntityStorageConnectorConstructorOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Returns the class name of the component.
|
|
20
|
+
* @returns The class name of the component.
|
|
21
|
+
*/
|
|
22
|
+
className(): string;
|
|
18
23
|
/**
|
|
19
24
|
* Get the schema for the entities.
|
|
20
25
|
* @returns The schema for the entities.
|
|
@@ -22,11 +27,10 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
|
|
|
22
27
|
getSchema(): IEntitySchema;
|
|
23
28
|
/**
|
|
24
29
|
* The component needs to be started when the node is initialized.
|
|
25
|
-
* @param nodeIdentity The identity of the node starting the component.
|
|
26
30
|
* @param nodeLoggingComponentType The node logging component type.
|
|
27
31
|
* @returns Nothing.
|
|
28
32
|
*/
|
|
29
|
-
start(
|
|
33
|
+
start(nodeLoggingComponentType?: string): Promise<void>;
|
|
30
34
|
/**
|
|
31
35
|
* Get an entity.
|
|
32
36
|
* @param id The id of the entity to get, or the index value if secondaryIndex is set.
|
|
@@ -63,15 +67,15 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
|
|
|
63
67
|
* @param conditions The conditions to match for the entities.
|
|
64
68
|
* @param sortProperties The optional sort order.
|
|
65
69
|
* @param properties The optional properties to return, defaults to all.
|
|
66
|
-
* @param cursor The cursor to request the next
|
|
67
|
-
* @param
|
|
70
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
71
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
68
72
|
* @returns All the entities for the storage matching the conditions,
|
|
69
73
|
* and a cursor which can be used to request more entities.
|
|
70
74
|
*/
|
|
71
75
|
query(conditions?: EntityCondition<T>, sortProperties?: {
|
|
72
76
|
property: keyof T;
|
|
73
77
|
sortDirection: SortDirection;
|
|
74
|
-
}[], properties?: (keyof T)[], cursor?: string,
|
|
78
|
+
}[], properties?: (keyof T)[], cursor?: string, limit?: number): Promise<{
|
|
75
79
|
/**
|
|
76
80
|
* The entities, which can be partial if a limited keys list was provided.
|
|
77
81
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.1](https://github.com/twinfoundation/synchronised-storage/compare/entity-storage-connector-synchronised-v0.0.3-next.0...entity-storage-connector-synchronised-v0.0.3-next.1) (2025-11-12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add context id features ([#24](https://github.com/twinfoundation/synchronised-storage/issues/24)) ([5266b18](https://github.com/twinfoundation/synchronised-storage/commit/5266b18088317c7dc274a209a79102a6fc88a8e4))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/synchronised-storage-models bumped from 0.0.3-next.0 to 0.0.3-next.1
|
|
16
|
+
|
|
17
|
+
## [0.0.2-next.10](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.9...entity-storage-connector-synchronised-v0.0.2-next.10) (2025-10-09)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add validate-locales ([e66ef0d](https://github.com/twinfoundation/entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
|
|
27
|
+
* The following workspace dependencies were updated
|
|
28
|
+
* dependencies
|
|
29
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
30
|
+
* devDependencies
|
|
31
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
32
|
+
|
|
3
33
|
## [0.0.2-next.9](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.8...entity-storage-connector-synchronised-v0.0.2-next.9) (2025-10-02)
|
|
4
34
|
|
|
5
35
|
|
|
@@ -36,15 +36,29 @@ The options for the connector.
|
|
|
36
36
|
|
|
37
37
|
### CLASS\_NAME
|
|
38
38
|
|
|
39
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
39
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
40
40
|
|
|
41
41
|
Runtime name for the class.
|
|
42
42
|
|
|
43
|
+
## Methods
|
|
44
|
+
|
|
45
|
+
### className()
|
|
46
|
+
|
|
47
|
+
> **className**(): `string`
|
|
48
|
+
|
|
49
|
+
Returns the class name of the component.
|
|
50
|
+
|
|
51
|
+
#### Returns
|
|
52
|
+
|
|
53
|
+
`string`
|
|
54
|
+
|
|
55
|
+
The class name of the component.
|
|
56
|
+
|
|
43
57
|
#### Implementation of
|
|
44
58
|
|
|
45
|
-
`IEntityStorageConnector.
|
|
59
|
+
`IEntityStorageConnector.className`
|
|
46
60
|
|
|
47
|
-
|
|
61
|
+
***
|
|
48
62
|
|
|
49
63
|
### getSchema()
|
|
50
64
|
|
|
@@ -66,24 +80,18 @@ The schema for the entities.
|
|
|
66
80
|
|
|
67
81
|
### start()
|
|
68
82
|
|
|
69
|
-
> **start**(`
|
|
83
|
+
> **start**(`nodeLoggingComponentType?`): `Promise`\<`void`\>
|
|
70
84
|
|
|
71
85
|
The component needs to be started when the node is initialized.
|
|
72
86
|
|
|
73
87
|
#### Parameters
|
|
74
88
|
|
|
75
|
-
#####
|
|
89
|
+
##### nodeLoggingComponentType?
|
|
76
90
|
|
|
77
91
|
`string`
|
|
78
92
|
|
|
79
|
-
The identity of the node starting the component.
|
|
80
|
-
|
|
81
|
-
##### nodeLoggingComponentType
|
|
82
|
-
|
|
83
93
|
The node logging component type.
|
|
84
94
|
|
|
85
|
-
`undefined` | `string`
|
|
86
|
-
|
|
87
95
|
#### Returns
|
|
88
96
|
|
|
89
97
|
`Promise`\<`void`\>
|
|
@@ -98,7 +106,7 @@ Nothing.
|
|
|
98
106
|
|
|
99
107
|
### get()
|
|
100
108
|
|
|
101
|
-
> **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`
|
|
109
|
+
> **get**(`id`, `secondaryIndex?`, `conditions?`): `Promise`\<`T` \| `undefined`\>
|
|
102
110
|
|
|
103
111
|
Get an entity.
|
|
104
112
|
|
|
@@ -124,7 +132,7 @@ The optional conditions to match for the entities.
|
|
|
124
132
|
|
|
125
133
|
#### Returns
|
|
126
134
|
|
|
127
|
-
`Promise`\<`
|
|
135
|
+
`Promise`\<`T` \| `undefined`\>
|
|
128
136
|
|
|
129
137
|
The object if it can be found or undefined.
|
|
130
138
|
|
|
@@ -200,7 +208,7 @@ Nothing.
|
|
|
200
208
|
|
|
201
209
|
### query()
|
|
202
210
|
|
|
203
|
-
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `
|
|
211
|
+
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `limit?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
|
|
204
212
|
|
|
205
213
|
Find all the entities which match the conditions.
|
|
206
214
|
|
|
@@ -228,9 +236,9 @@ The optional properties to return, defaults to all.
|
|
|
228
236
|
|
|
229
237
|
`string`
|
|
230
238
|
|
|
231
|
-
The cursor to request the next
|
|
239
|
+
The cursor to request the next chunk of entities.
|
|
232
240
|
|
|
233
|
-
#####
|
|
241
|
+
##### limit?
|
|
234
242
|
|
|
235
243
|
`number`
|
|
236
244
|
|
package/locales/en.json
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"error": {
|
|
3
|
+
"synchronisedEntityStorageConnector": {
|
|
4
|
+
"missingRequiredProperty": "The property \"{requiredProperty}\" is required when using the Synchronised Entity Storage Connector.",
|
|
5
|
+
"missingRequiredPropertySort": "The property \"{requiredProperty}\" requires sorting attributes for the Synchronised Entity Storage Connector."
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-synchronised",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-next.1",
|
|
4
4
|
"description": "Entity Storage connector implementation using synchronised storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/twinfoundation/
|
|
7
|
+
"url": "git+https://github.com/twinfoundation/synchronised-storage.git",
|
|
8
8
|
"directory": "packages/entity-storage-connector-synchronised"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
@@ -14,28 +14,27 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@twin.org/context": "next",
|
|
17
18
|
"@twin.org/core": "next",
|
|
18
19
|
"@twin.org/entity": "next",
|
|
19
|
-
"@twin.org/entity-storage-models": "
|
|
20
|
+
"@twin.org/entity-storage-models": "next",
|
|
20
21
|
"@twin.org/event-bus-models": "next",
|
|
21
22
|
"@twin.org/logging-models": "next",
|
|
22
23
|
"@twin.org/nameof": "next",
|
|
23
|
-
"@twin.org/synchronised-storage-models": "next"
|
|
24
|
+
"@twin.org/synchronised-storage-models": "0.0.3-next.1"
|
|
24
25
|
},
|
|
25
|
-
"main": "./dist/
|
|
26
|
-
"module": "./dist/esm/index.mjs",
|
|
26
|
+
"main": "./dist/es/index.js",
|
|
27
27
|
"types": "./dist/types/index.d.ts",
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|
|
30
30
|
"types": "./dist/types/index.d.ts",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
31
|
+
"import": "./dist/es/index.js",
|
|
32
|
+
"default": "./dist/es/index.js"
|
|
33
33
|
},
|
|
34
34
|
"./locales/*.json": "./locales/*.json"
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
|
-
"dist/
|
|
38
|
-
"dist/esm",
|
|
37
|
+
"dist/es",
|
|
39
38
|
"dist/types",
|
|
40
39
|
"locales",
|
|
41
40
|
"docs"
|
|
@@ -54,5 +53,9 @@
|
|
|
54
53
|
"connector",
|
|
55
54
|
"adapter",
|
|
56
55
|
"integration"
|
|
57
|
-
]
|
|
56
|
+
],
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "git+https://github.com/twinfoundation/synchronised-storage/issues"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://twindev.org"
|
|
58
61
|
}
|
package/dist/cjs/index.cjs
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var core = require('@twin.org/core');
|
|
4
|
-
var entity = require('@twin.org/entity');
|
|
5
|
-
var entityStorageModels = require('@twin.org/entity-storage-models');
|
|
6
|
-
var synchronisedStorageModels = require('@twin.org/synchronised-storage-models');
|
|
7
|
-
|
|
8
|
-
// Copyright 2024 IOTA Stiftung.
|
|
9
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
10
|
-
/**
|
|
11
|
-
* Class for performing entity storage operations in synchronised storage.
|
|
12
|
-
*/
|
|
13
|
-
class SynchronisedEntityStorageConnector {
|
|
14
|
-
/**
|
|
15
|
-
* Runtime name for the class.
|
|
16
|
-
*/
|
|
17
|
-
CLASS_NAME = "SynchronisedEntityStorageConnector";
|
|
18
|
-
/**
|
|
19
|
-
* The schema for the entity.
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
22
|
-
_entitySchema;
|
|
23
|
-
/**
|
|
24
|
-
* The primary key for the entity schema.
|
|
25
|
-
* @internal
|
|
26
|
-
*/
|
|
27
|
-
_primaryKey;
|
|
28
|
-
/**
|
|
29
|
-
* The storage key for the entity.
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
_storageKey;
|
|
33
|
-
/**
|
|
34
|
-
* The entity storage connector to use for actual data.
|
|
35
|
-
* @internal
|
|
36
|
-
*/
|
|
37
|
-
_entityStorageConnector;
|
|
38
|
-
/**
|
|
39
|
-
* The event bus component.
|
|
40
|
-
* @internal
|
|
41
|
-
*/
|
|
42
|
-
_eventBusComponent;
|
|
43
|
-
/**
|
|
44
|
-
* The node identity.
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
_nodeIdentity;
|
|
48
|
-
/**
|
|
49
|
-
* Create a new instance of SynchronisedEntityStorageConnector.
|
|
50
|
-
* @param options The options for the connector.
|
|
51
|
-
*/
|
|
52
|
-
constructor(options) {
|
|
53
|
-
core.Guards.object(this.CLASS_NAME, "options", options);
|
|
54
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
55
|
-
core.Guards.stringValue(this.CLASS_NAME, "options.entityStorageConnectorType", options.entityStorageConnectorType);
|
|
56
|
-
this._entitySchema = entity.EntitySchemaFactory.get(options.entitySchema);
|
|
57
|
-
this._storageKey = options?.config?.storageKey ?? core.StringHelper.kebabCase(options.entitySchema);
|
|
58
|
-
this._primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
59
|
-
const requiredProperties = [
|
|
60
|
-
"id",
|
|
61
|
-
"nodeIdentity",
|
|
62
|
-
"dateModified"
|
|
63
|
-
];
|
|
64
|
-
for (const requiredProperty of requiredProperties) {
|
|
65
|
-
const foundProperty = this._entitySchema.properties?.find(prop => prop.property === requiredProperty);
|
|
66
|
-
if (core.Is.empty(foundProperty)) {
|
|
67
|
-
throw new core.GeneralError(this.CLASS_NAME, "missingRequiredProperty", { requiredProperty });
|
|
68
|
-
}
|
|
69
|
-
else if (core.Is.empty(foundProperty.isPrimary) &&
|
|
70
|
-
core.Is.empty(foundProperty.isSecondary) &&
|
|
71
|
-
core.Is.empty(foundProperty.sortDirection)) {
|
|
72
|
-
throw new core.GeneralError(this.CLASS_NAME, "missingRequiredPropertySort", {
|
|
73
|
-
requiredProperty
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
this._entityStorageConnector = entityStorageModels.EntityStorageConnectorFactory.get(options.entityStorageConnectorType);
|
|
78
|
-
this._eventBusComponent = core.ComponentFactory.get(options.eventBusComponentType ?? "event-bus");
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get the schema for the entities.
|
|
82
|
-
* @returns The schema for the entities.
|
|
83
|
-
*/
|
|
84
|
-
getSchema() {
|
|
85
|
-
return this._entitySchema;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* The component needs to be started when the node is initialized.
|
|
89
|
-
* @param nodeIdentity The identity of the node starting the component.
|
|
90
|
-
* @param nodeLoggingComponentType The node logging component type.
|
|
91
|
-
* @returns Nothing.
|
|
92
|
-
*/
|
|
93
|
-
async start(nodeIdentity, nodeLoggingComponentType) {
|
|
94
|
-
this._nodeIdentity = nodeIdentity;
|
|
95
|
-
// Tell the synchronised storage about this storage key
|
|
96
|
-
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.RegisterStorageKey, {
|
|
97
|
-
storageKey: this._storageKey
|
|
98
|
-
});
|
|
99
|
-
this.handleEventBusMessages();
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Get an entity.
|
|
103
|
-
* @param id The id of the entity to get, or the index value if secondaryIndex is set.
|
|
104
|
-
* @param secondaryIndex Get the item using a secondary index.
|
|
105
|
-
* @param conditions The optional conditions to match for the entities.
|
|
106
|
-
* @returns The object if it can be found or undefined.
|
|
107
|
-
*/
|
|
108
|
-
async get(id, secondaryIndex, conditions) {
|
|
109
|
-
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
110
|
-
return this._entityStorageConnector.get(id, secondaryIndex, conditions);
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Set an entity.
|
|
114
|
-
* @param entity The entity to set.
|
|
115
|
-
* @param conditions The optional conditions to match for the entities.
|
|
116
|
-
* @returns The id of the entity.
|
|
117
|
-
*/
|
|
118
|
-
async set(entity, conditions) {
|
|
119
|
-
core.Guards.object(this.CLASS_NAME, "entity", entity);
|
|
120
|
-
if (core.Is.stringValue(this._nodeIdentity)) {
|
|
121
|
-
// Make sure the entity has the required properties
|
|
122
|
-
entity.dateModified = new Date(Date.now()).toISOString();
|
|
123
|
-
entity.nodeIdentity = this._nodeIdentity;
|
|
124
|
-
await this._entityStorageConnector.set(entity, conditions);
|
|
125
|
-
// Tell the synchronised storage about the entity changes
|
|
126
|
-
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemChange, {
|
|
127
|
-
storageKey: this._storageKey,
|
|
128
|
-
operation: synchronisedStorageModels.SyncChangeOperation.Set,
|
|
129
|
-
nodeIdentity: this._nodeIdentity,
|
|
130
|
-
id: entity[this._primaryKey.property]
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Remove the entity.
|
|
136
|
-
* @param id The id of the entity to remove.
|
|
137
|
-
* @param conditions The optional conditions to match for the entities.
|
|
138
|
-
* @returns Nothing.
|
|
139
|
-
*/
|
|
140
|
-
async remove(id, conditions) {
|
|
141
|
-
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
142
|
-
if (core.Is.stringValue(this._nodeIdentity)) {
|
|
143
|
-
await this._entityStorageConnector.remove(id, conditions);
|
|
144
|
-
// Tell the synchronised storage about the entity removal
|
|
145
|
-
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemChange, {
|
|
146
|
-
storageKey: this._storageKey,
|
|
147
|
-
operation: synchronisedStorageModels.SyncChangeOperation.Delete,
|
|
148
|
-
nodeIdentity: this._nodeIdentity,
|
|
149
|
-
id
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Find all the entities which match the conditions.
|
|
155
|
-
* @param conditions The conditions to match for the entities.
|
|
156
|
-
* @param sortProperties The optional sort order.
|
|
157
|
-
* @param properties The optional properties to return, defaults to all.
|
|
158
|
-
* @param cursor The cursor to request the next page of entities.
|
|
159
|
-
* @param pageSize The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
160
|
-
* @returns All the entities for the storage matching the conditions,
|
|
161
|
-
* and a cursor which can be used to request more entities.
|
|
162
|
-
*/
|
|
163
|
-
async query(conditions, sortProperties, properties, cursor, pageSize) {
|
|
164
|
-
return this._entityStorageConnector.query(conditions, sortProperties, properties, cursor, pageSize);
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Handle the event bus messages.
|
|
168
|
-
* @internal
|
|
169
|
-
*/
|
|
170
|
-
handleEventBusMessages() {
|
|
171
|
-
// When the synchronised storage requests an item, we need to provide it
|
|
172
|
-
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemRequest, async (params) => {
|
|
173
|
-
await this.handleLocalItemRequest(params);
|
|
174
|
-
});
|
|
175
|
-
// When the synchronised storage requests a batch, we need to provide it
|
|
176
|
-
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.BatchRequest, async (params) => {
|
|
177
|
-
await this.handleBatchRequest(params);
|
|
178
|
-
});
|
|
179
|
-
// Subscribe to remote item set events from the synchronised storage and update the local storage
|
|
180
|
-
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.RemoteItemSet, async (params) => {
|
|
181
|
-
await this.handleRemoteItemSet(params);
|
|
182
|
-
});
|
|
183
|
-
// Subscribe to remote item remove events from the synchronised storage and update the local storage
|
|
184
|
-
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.RemoteItemRemove, async (params) => {
|
|
185
|
-
await this.handleRemoteItemRemove(params);
|
|
186
|
-
});
|
|
187
|
-
// Subscribe to resets from the synchronised storage and update the local storage
|
|
188
|
-
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.Reset, async (params) => {
|
|
189
|
-
await this.handleReset(params);
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Handle a local item request.
|
|
194
|
-
* @param event The request parameters
|
|
195
|
-
* @internal
|
|
196
|
-
*/
|
|
197
|
-
async handleLocalItemRequest(event) {
|
|
198
|
-
// Only handle the request if it matches the storage key
|
|
199
|
-
if (event.data.storageKey === this._storageKey) {
|
|
200
|
-
let entity;
|
|
201
|
-
try {
|
|
202
|
-
entity = await this._entityStorageConnector.get(event.data.id);
|
|
203
|
-
}
|
|
204
|
-
catch { }
|
|
205
|
-
// Publish the item response with the entity
|
|
206
|
-
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemResponse, {
|
|
207
|
-
storageKey: this._storageKey,
|
|
208
|
-
id: event.data.id,
|
|
209
|
-
entity
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Handle a remote item set event.
|
|
215
|
-
* @param event The event parameters
|
|
216
|
-
* @internal
|
|
217
|
-
*/
|
|
218
|
-
async handleRemoteItemSet(event) {
|
|
219
|
-
// Only set the item if it matches the storage key
|
|
220
|
-
// and it is from another node, remote updates can not change data for this node
|
|
221
|
-
// That must be done via the regular entity storage methods
|
|
222
|
-
if (event.data.storageKey === this._storageKey &&
|
|
223
|
-
event.data.entity.nodeIdentity !== this._nodeIdentity) {
|
|
224
|
-
await this._entityStorageConnector.set(event.data.entity);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Handle a remote item remove event.
|
|
229
|
-
* @param params The event parameters
|
|
230
|
-
* @internal
|
|
231
|
-
*/
|
|
232
|
-
async handleRemoteItemRemove(params) {
|
|
233
|
-
// Only remove the item if it matches the storage key
|
|
234
|
-
// and it is from another node, remote updates can not change data for this node
|
|
235
|
-
// That must be done via the regular entity storage methods
|
|
236
|
-
if (params.data.storageKey === this._storageKey &&
|
|
237
|
-
params.data.nodeIdentity !== this._nodeIdentity) {
|
|
238
|
-
await this._entityStorageConnector.remove(params.data.id);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Handle a batch request.
|
|
243
|
-
* @param event The request parameters
|
|
244
|
-
* @internal
|
|
245
|
-
*/
|
|
246
|
-
async handleBatchRequest(event) {
|
|
247
|
-
// Only handle the request if it matches the storage key
|
|
248
|
-
if (event.data.storageKey === this._storageKey) {
|
|
249
|
-
let cursor;
|
|
250
|
-
do {
|
|
251
|
-
const condition = {
|
|
252
|
-
conditions: []
|
|
253
|
-
};
|
|
254
|
-
if (event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Local ||
|
|
255
|
-
event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Remote) {
|
|
256
|
-
condition.conditions.push({
|
|
257
|
-
property: "nodeIdentity",
|
|
258
|
-
value: this._nodeIdentity,
|
|
259
|
-
comparison: event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Local
|
|
260
|
-
? entity.ComparisonOperator.Equals
|
|
261
|
-
: entity.ComparisonOperator.NotEquals
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
const result = await this._entityStorageConnector.query(condition, [{ property: "dateModified", sortDirection: entity.SortDirection.Ascending }], undefined, cursor, event.data.batchSize);
|
|
265
|
-
cursor = result.cursor;
|
|
266
|
-
// Publish the batch response with the entities
|
|
267
|
-
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.BatchResponse, {
|
|
268
|
-
storageKey: this._storageKey,
|
|
269
|
-
entities: result.entities,
|
|
270
|
-
lastEntry: !core.Is.stringValue(cursor)
|
|
271
|
-
});
|
|
272
|
-
} while (core.Is.stringValue(cursor));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Handle a reset event.
|
|
277
|
-
* @param event The event parameters
|
|
278
|
-
* @internal
|
|
279
|
-
*/
|
|
280
|
-
async handleReset(event) {
|
|
281
|
-
// Only reset the storage if it matches the storage key
|
|
282
|
-
if (event.data.storageKey === this._storageKey) {
|
|
283
|
-
let cursor;
|
|
284
|
-
let toRemove = [];
|
|
285
|
-
// Build a list of the ids to remove
|
|
286
|
-
do {
|
|
287
|
-
const condition = {
|
|
288
|
-
conditions: []
|
|
289
|
-
};
|
|
290
|
-
// Depending on the reset mode we can filter the entities to remove
|
|
291
|
-
if (event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Local ||
|
|
292
|
-
event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Remote) {
|
|
293
|
-
condition.conditions.push({
|
|
294
|
-
property: "nodeIdentity",
|
|
295
|
-
value: this._nodeIdentity,
|
|
296
|
-
comparison: event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Local
|
|
297
|
-
? entity.ComparisonOperator.Equals
|
|
298
|
-
: entity.ComparisonOperator.NotEquals
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
const result = await this._entityStorageConnector.query(condition, undefined, undefined, cursor);
|
|
302
|
-
cursor = result.cursor;
|
|
303
|
-
toRemove = toRemove.concat(result.entities.map(entity => entity.id));
|
|
304
|
-
} while (core.Is.stringValue(cursor));
|
|
305
|
-
// Remove the entities
|
|
306
|
-
for (let i = 0; i < toRemove.length; i++) {
|
|
307
|
-
await this.remove(toRemove[i]);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
exports.SynchronisedEntityStorageConnector = SynchronisedEntityStorageConnector;
|