@twin.org/entity-storage-connector-synchronised 0.0.2-next.4 → 0.0.2-next.6
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/cjs/index.cjs
CHANGED
|
@@ -40,6 +40,11 @@ class SynchronisedEntityStorageConnector {
|
|
|
40
40
|
* @internal
|
|
41
41
|
*/
|
|
42
42
|
_eventBusComponent;
|
|
43
|
+
/**
|
|
44
|
+
* The node identity.
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
_nodeIdentity;
|
|
43
48
|
/**
|
|
44
49
|
* Create a new instance of SynchronisedEntityStorageConnector.
|
|
45
50
|
* @param options The options for the connector.
|
|
@@ -82,11 +87,12 @@ class SynchronisedEntityStorageConnector {
|
|
|
82
87
|
/**
|
|
83
88
|
* The component needs to be started when the node is initialized.
|
|
84
89
|
* @param nodeIdentity The identity of the node starting the component.
|
|
85
|
-
* @param
|
|
90
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
86
91
|
* @param componentState A persistent state which can be modified by the method.
|
|
87
92
|
* @returns Nothing.
|
|
88
93
|
*/
|
|
89
|
-
async start(nodeIdentity,
|
|
94
|
+
async start(nodeIdentity, nodeLoggingComponentType, componentState) {
|
|
95
|
+
this._nodeIdentity = nodeIdentity;
|
|
90
96
|
// Tell the synchronised storage about this storage key
|
|
91
97
|
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.RegisterStorageKey, {
|
|
92
98
|
storageKey: this._storageKey
|
|
@@ -112,15 +118,19 @@ class SynchronisedEntityStorageConnector {
|
|
|
112
118
|
*/
|
|
113
119
|
async set(entity, conditions) {
|
|
114
120
|
core.Guards.object(this.CLASS_NAME, "entity", entity);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
if (core.Is.stringValue(this._nodeIdentity)) {
|
|
122
|
+
// Make sure the entity has the required properties
|
|
123
|
+
entity.dateModified = new Date(Date.now()).toISOString();
|
|
124
|
+
entity.nodeIdentity = this._nodeIdentity;
|
|
125
|
+
await this._entityStorageConnector.set(entity, conditions);
|
|
126
|
+
// Tell the synchronised storage about the entity changes
|
|
127
|
+
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemChange, {
|
|
128
|
+
storageKey: this._storageKey,
|
|
129
|
+
operation: synchronisedStorageModels.SyncChangeOperation.Set,
|
|
130
|
+
nodeIdentity: this._nodeIdentity,
|
|
131
|
+
id: entity[this._primaryKey.property]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
124
134
|
}
|
|
125
135
|
/**
|
|
126
136
|
* Remove the entity.
|
|
@@ -130,13 +140,16 @@ class SynchronisedEntityStorageConnector {
|
|
|
130
140
|
*/
|
|
131
141
|
async remove(id, conditions) {
|
|
132
142
|
core.Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
if (core.Is.stringValue(this._nodeIdentity)) {
|
|
144
|
+
await this._entityStorageConnector.remove(id, conditions);
|
|
145
|
+
// Tell the synchronised storage about the entity removal
|
|
146
|
+
await this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemChange, {
|
|
147
|
+
storageKey: this._storageKey,
|
|
148
|
+
operation: synchronisedStorageModels.SyncChangeOperation.Delete,
|
|
149
|
+
nodeIdentity: this._nodeIdentity,
|
|
150
|
+
id
|
|
151
|
+
});
|
|
152
|
+
}
|
|
140
153
|
}
|
|
141
154
|
/**
|
|
142
155
|
* Find all the entities which match the conditions.
|
|
@@ -158,53 +171,144 @@ class SynchronisedEntityStorageConnector {
|
|
|
158
171
|
handleEventBusMessages() {
|
|
159
172
|
// When the synchronised storage requests an item, we need to provide it
|
|
160
173
|
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemRequest, async (params) => {
|
|
161
|
-
|
|
162
|
-
if (params.data.storageKey === this._storageKey) {
|
|
163
|
-
let entity;
|
|
164
|
-
try {
|
|
165
|
-
entity = await this._entityStorageConnector.get(params.data.id);
|
|
166
|
-
}
|
|
167
|
-
catch { }
|
|
168
|
-
// Publish the item response with the entity
|
|
169
|
-
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemResponse, {
|
|
170
|
-
storageKey: this._storageKey,
|
|
171
|
-
id: params.data.id,
|
|
172
|
-
entity
|
|
173
|
-
});
|
|
174
|
-
}
|
|
174
|
+
await this.handleLocalItemRequest(params);
|
|
175
175
|
});
|
|
176
176
|
// When the synchronised storage requests a batch, we need to provide it
|
|
177
177
|
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.BatchRequest, async (params) => {
|
|
178
|
-
|
|
179
|
-
if (params.data.storageKey === this._storageKey) {
|
|
180
|
-
let cursor;
|
|
181
|
-
do {
|
|
182
|
-
const result = await this._entityStorageConnector.query(undefined, [{ property: "dateModified", sortDirection: entity.SortDirection.Ascending }], undefined, cursor, params.data.batchSize);
|
|
183
|
-
cursor = result.cursor;
|
|
184
|
-
// Publish the batch response with the entities
|
|
185
|
-
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.BatchResponse, {
|
|
186
|
-
storageKey: this._storageKey,
|
|
187
|
-
entities: result.entities,
|
|
188
|
-
lastEntry: !core.Is.stringValue(cursor)
|
|
189
|
-
});
|
|
190
|
-
} while (core.Is.stringValue(cursor));
|
|
191
|
-
}
|
|
178
|
+
await this.handleBatchRequest(params);
|
|
192
179
|
});
|
|
193
180
|
// Subscribe to remote item set events from the synchronised storage and update the local storage
|
|
194
181
|
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.RemoteItemSet, async (params) => {
|
|
195
|
-
|
|
196
|
-
if (params.data.storageKey === this._storageKey) {
|
|
197
|
-
await this.set(params.data.entity);
|
|
198
|
-
}
|
|
182
|
+
await this.handleRemoteItemSet(params);
|
|
199
183
|
});
|
|
200
184
|
// Subscribe to remote item remove events from the synchronised storage and update the local storage
|
|
201
185
|
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.RemoteItemRemove, async (params) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
186
|
+
await this.handleRemoteItemRemove(params);
|
|
187
|
+
});
|
|
188
|
+
// Subscribe to resets from the synchronised storage and update the local storage
|
|
189
|
+
this._eventBusComponent.subscribe(synchronisedStorageModels.SynchronisedStorageTopics.Reset, async (params) => {
|
|
190
|
+
await this.handleReset(params);
|
|
206
191
|
});
|
|
207
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Handle a local item request.
|
|
195
|
+
* @param event The request parameters
|
|
196
|
+
* @internal
|
|
197
|
+
*/
|
|
198
|
+
async handleLocalItemRequest(event) {
|
|
199
|
+
// Only handle the request if it matches the storage key
|
|
200
|
+
if (event.data.storageKey === this._storageKey) {
|
|
201
|
+
let entity;
|
|
202
|
+
try {
|
|
203
|
+
entity = await this._entityStorageConnector.get(event.data.id);
|
|
204
|
+
}
|
|
205
|
+
catch { }
|
|
206
|
+
// Publish the item response with the entity
|
|
207
|
+
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.LocalItemResponse, {
|
|
208
|
+
storageKey: this._storageKey,
|
|
209
|
+
id: event.data.id,
|
|
210
|
+
entity
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Handle a remote item set event.
|
|
216
|
+
* @param event The event parameters
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
async handleRemoteItemSet(event) {
|
|
220
|
+
// Only set the item if it matches the storage key
|
|
221
|
+
// and it is from another node, remote updates can not change data for this node
|
|
222
|
+
// That must be done via the regular entity storage methods
|
|
223
|
+
if (event.data.storageKey === this._storageKey &&
|
|
224
|
+
event.data.entity.nodeIdentity !== this._nodeIdentity) {
|
|
225
|
+
await this._entityStorageConnector.set(event.data.entity);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Handle a remote item remove event.
|
|
230
|
+
* @param params The event parameters
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
233
|
+
async handleRemoteItemRemove(params) {
|
|
234
|
+
// Only remove the item if it matches the storage key
|
|
235
|
+
// and it is from another node, remote updates can not change data for this node
|
|
236
|
+
// That must be done via the regular entity storage methods
|
|
237
|
+
if (params.data.storageKey === this._storageKey &&
|
|
238
|
+
params.data.nodeIdentity !== this._nodeIdentity) {
|
|
239
|
+
await this._entityStorageConnector.remove(params.data.id);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Handle a batch request.
|
|
244
|
+
* @param event The request parameters
|
|
245
|
+
* @internal
|
|
246
|
+
*/
|
|
247
|
+
async handleBatchRequest(event) {
|
|
248
|
+
// Only handle the request if it matches the storage key
|
|
249
|
+
if (event.data.storageKey === this._storageKey) {
|
|
250
|
+
let cursor;
|
|
251
|
+
do {
|
|
252
|
+
const condition = {
|
|
253
|
+
conditions: []
|
|
254
|
+
};
|
|
255
|
+
if (event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Local ||
|
|
256
|
+
event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Remote) {
|
|
257
|
+
condition.conditions.push({
|
|
258
|
+
property: "nodeIdentity",
|
|
259
|
+
value: this._nodeIdentity,
|
|
260
|
+
comparison: event.data.requestMode === synchronisedStorageModels.SyncNodeIdentityMode.Local
|
|
261
|
+
? entity.ComparisonOperator.Equals
|
|
262
|
+
: entity.ComparisonOperator.NotEquals
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
const result = await this._entityStorageConnector.query(condition, [{ property: "dateModified", sortDirection: entity.SortDirection.Ascending }], undefined, cursor, event.data.batchSize);
|
|
266
|
+
cursor = result.cursor;
|
|
267
|
+
// Publish the batch response with the entities
|
|
268
|
+
this._eventBusComponent.publish(synchronisedStorageModels.SynchronisedStorageTopics.BatchResponse, {
|
|
269
|
+
storageKey: this._storageKey,
|
|
270
|
+
entities: result.entities,
|
|
271
|
+
lastEntry: !core.Is.stringValue(cursor)
|
|
272
|
+
});
|
|
273
|
+
} while (core.Is.stringValue(cursor));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Handle a reset event.
|
|
278
|
+
* @param event The event parameters
|
|
279
|
+
* @internal
|
|
280
|
+
*/
|
|
281
|
+
async handleReset(event) {
|
|
282
|
+
// Only reset the storage if it matches the storage key
|
|
283
|
+
if (event.data.storageKey === this._storageKey) {
|
|
284
|
+
let cursor;
|
|
285
|
+
let toRemove = [];
|
|
286
|
+
// Build a list of the ids to remove
|
|
287
|
+
do {
|
|
288
|
+
const condition = {
|
|
289
|
+
conditions: []
|
|
290
|
+
};
|
|
291
|
+
// Depending on the reset mode we can filter the entities to remove
|
|
292
|
+
if (event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Local ||
|
|
293
|
+
event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Remote) {
|
|
294
|
+
condition.conditions.push({
|
|
295
|
+
property: "nodeIdentity",
|
|
296
|
+
value: this._nodeIdentity,
|
|
297
|
+
comparison: event.data.resetMode === synchronisedStorageModels.SyncNodeIdentityMode.Local
|
|
298
|
+
? entity.ComparisonOperator.Equals
|
|
299
|
+
: entity.ComparisonOperator.NotEquals
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
const result = await this._entityStorageConnector.query(condition, undefined, undefined, cursor);
|
|
303
|
+
cursor = result.cursor;
|
|
304
|
+
toRemove = toRemove.concat(result.entities.map(entity => entity.id));
|
|
305
|
+
} while (core.Is.stringValue(cursor));
|
|
306
|
+
// Remove the entities
|
|
307
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
308
|
+
await this.remove(toRemove[i]);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
208
312
|
}
|
|
209
313
|
|
|
210
314
|
exports.SynchronisedEntityStorageConnector = SynchronisedEntityStorageConnector;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Guards, StringHelper, Is, GeneralError, ComponentFactory } from '@twin.org/core';
|
|
2
|
-
import { EntitySchemaFactory, EntitySchemaHelper, SortDirection } from '@twin.org/entity';
|
|
2
|
+
import { EntitySchemaFactory, EntitySchemaHelper, ComparisonOperator, SortDirection } from '@twin.org/entity';
|
|
3
3
|
import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
|
|
4
|
-
import { SynchronisedStorageTopics, SyncChangeOperation } from '@twin.org/synchronised-storage-models';
|
|
4
|
+
import { SynchronisedStorageTopics, SyncChangeOperation, SyncNodeIdentityMode } from '@twin.org/synchronised-storage-models';
|
|
5
5
|
|
|
6
6
|
// Copyright 2024 IOTA Stiftung.
|
|
7
7
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -38,6 +38,11 @@ class SynchronisedEntityStorageConnector {
|
|
|
38
38
|
* @internal
|
|
39
39
|
*/
|
|
40
40
|
_eventBusComponent;
|
|
41
|
+
/**
|
|
42
|
+
* The node identity.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
_nodeIdentity;
|
|
41
46
|
/**
|
|
42
47
|
* Create a new instance of SynchronisedEntityStorageConnector.
|
|
43
48
|
* @param options The options for the connector.
|
|
@@ -80,11 +85,12 @@ class SynchronisedEntityStorageConnector {
|
|
|
80
85
|
/**
|
|
81
86
|
* The component needs to be started when the node is initialized.
|
|
82
87
|
* @param nodeIdentity The identity of the node starting the component.
|
|
83
|
-
* @param
|
|
88
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
84
89
|
* @param componentState A persistent state which can be modified by the method.
|
|
85
90
|
* @returns Nothing.
|
|
86
91
|
*/
|
|
87
|
-
async start(nodeIdentity,
|
|
92
|
+
async start(nodeIdentity, nodeLoggingComponentType, componentState) {
|
|
93
|
+
this._nodeIdentity = nodeIdentity;
|
|
88
94
|
// Tell the synchronised storage about this storage key
|
|
89
95
|
await this._eventBusComponent.publish(SynchronisedStorageTopics.RegisterStorageKey, {
|
|
90
96
|
storageKey: this._storageKey
|
|
@@ -110,15 +116,19 @@ class SynchronisedEntityStorageConnector {
|
|
|
110
116
|
*/
|
|
111
117
|
async set(entity, conditions) {
|
|
112
118
|
Guards.object(this.CLASS_NAME, "entity", entity);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
if (Is.stringValue(this._nodeIdentity)) {
|
|
120
|
+
// Make sure the entity has the required properties
|
|
121
|
+
entity.dateModified = new Date(Date.now()).toISOString();
|
|
122
|
+
entity.nodeIdentity = this._nodeIdentity;
|
|
123
|
+
await this._entityStorageConnector.set(entity, conditions);
|
|
124
|
+
// Tell the synchronised storage about the entity changes
|
|
125
|
+
await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
|
|
126
|
+
storageKey: this._storageKey,
|
|
127
|
+
operation: SyncChangeOperation.Set,
|
|
128
|
+
nodeIdentity: this._nodeIdentity,
|
|
129
|
+
id: entity[this._primaryKey.property]
|
|
130
|
+
});
|
|
131
|
+
}
|
|
122
132
|
}
|
|
123
133
|
/**
|
|
124
134
|
* Remove the entity.
|
|
@@ -128,13 +138,16 @@ class SynchronisedEntityStorageConnector {
|
|
|
128
138
|
*/
|
|
129
139
|
async remove(id, conditions) {
|
|
130
140
|
Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
if (Is.stringValue(this._nodeIdentity)) {
|
|
142
|
+
await this._entityStorageConnector.remove(id, conditions);
|
|
143
|
+
// Tell the synchronised storage about the entity removal
|
|
144
|
+
await this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemChange, {
|
|
145
|
+
storageKey: this._storageKey,
|
|
146
|
+
operation: SyncChangeOperation.Delete,
|
|
147
|
+
nodeIdentity: this._nodeIdentity,
|
|
148
|
+
id
|
|
149
|
+
});
|
|
150
|
+
}
|
|
138
151
|
}
|
|
139
152
|
/**
|
|
140
153
|
* Find all the entities which match the conditions.
|
|
@@ -156,53 +169,144 @@ class SynchronisedEntityStorageConnector {
|
|
|
156
169
|
handleEventBusMessages() {
|
|
157
170
|
// When the synchronised storage requests an item, we need to provide it
|
|
158
171
|
this._eventBusComponent.subscribe(SynchronisedStorageTopics.LocalItemRequest, async (params) => {
|
|
159
|
-
|
|
160
|
-
if (params.data.storageKey === this._storageKey) {
|
|
161
|
-
let entity;
|
|
162
|
-
try {
|
|
163
|
-
entity = await this._entityStorageConnector.get(params.data.id);
|
|
164
|
-
}
|
|
165
|
-
catch { }
|
|
166
|
-
// Publish the item response with the entity
|
|
167
|
-
this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemResponse, {
|
|
168
|
-
storageKey: this._storageKey,
|
|
169
|
-
id: params.data.id,
|
|
170
|
-
entity
|
|
171
|
-
});
|
|
172
|
-
}
|
|
172
|
+
await this.handleLocalItemRequest(params);
|
|
173
173
|
});
|
|
174
174
|
// When the synchronised storage requests a batch, we need to provide it
|
|
175
175
|
this._eventBusComponent.subscribe(SynchronisedStorageTopics.BatchRequest, async (params) => {
|
|
176
|
-
|
|
177
|
-
if (params.data.storageKey === this._storageKey) {
|
|
178
|
-
let cursor;
|
|
179
|
-
do {
|
|
180
|
-
const result = await this._entityStorageConnector.query(undefined, [{ property: "dateModified", sortDirection: SortDirection.Ascending }], undefined, cursor, params.data.batchSize);
|
|
181
|
-
cursor = result.cursor;
|
|
182
|
-
// Publish the batch response with the entities
|
|
183
|
-
this._eventBusComponent.publish(SynchronisedStorageTopics.BatchResponse, {
|
|
184
|
-
storageKey: this._storageKey,
|
|
185
|
-
entities: result.entities,
|
|
186
|
-
lastEntry: !Is.stringValue(cursor)
|
|
187
|
-
});
|
|
188
|
-
} while (Is.stringValue(cursor));
|
|
189
|
-
}
|
|
176
|
+
await this.handleBatchRequest(params);
|
|
190
177
|
});
|
|
191
178
|
// Subscribe to remote item set events from the synchronised storage and update the local storage
|
|
192
179
|
this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemSet, async (params) => {
|
|
193
|
-
|
|
194
|
-
if (params.data.storageKey === this._storageKey) {
|
|
195
|
-
await this.set(params.data.entity);
|
|
196
|
-
}
|
|
180
|
+
await this.handleRemoteItemSet(params);
|
|
197
181
|
});
|
|
198
182
|
// Subscribe to remote item remove events from the synchronised storage and update the local storage
|
|
199
183
|
this._eventBusComponent.subscribe(SynchronisedStorageTopics.RemoteItemRemove, async (params) => {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
184
|
+
await this.handleRemoteItemRemove(params);
|
|
185
|
+
});
|
|
186
|
+
// Subscribe to resets from the synchronised storage and update the local storage
|
|
187
|
+
this._eventBusComponent.subscribe(SynchronisedStorageTopics.Reset, async (params) => {
|
|
188
|
+
await this.handleReset(params);
|
|
204
189
|
});
|
|
205
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Handle a local item request.
|
|
193
|
+
* @param event The request parameters
|
|
194
|
+
* @internal
|
|
195
|
+
*/
|
|
196
|
+
async handleLocalItemRequest(event) {
|
|
197
|
+
// Only handle the request if it matches the storage key
|
|
198
|
+
if (event.data.storageKey === this._storageKey) {
|
|
199
|
+
let entity;
|
|
200
|
+
try {
|
|
201
|
+
entity = await this._entityStorageConnector.get(event.data.id);
|
|
202
|
+
}
|
|
203
|
+
catch { }
|
|
204
|
+
// Publish the item response with the entity
|
|
205
|
+
this._eventBusComponent.publish(SynchronisedStorageTopics.LocalItemResponse, {
|
|
206
|
+
storageKey: this._storageKey,
|
|
207
|
+
id: event.data.id,
|
|
208
|
+
entity
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Handle a remote item set event.
|
|
214
|
+
* @param event The event parameters
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
async handleRemoteItemSet(event) {
|
|
218
|
+
// Only set the item if it matches the storage key
|
|
219
|
+
// and it is from another node, remote updates can not change data for this node
|
|
220
|
+
// That must be done via the regular entity storage methods
|
|
221
|
+
if (event.data.storageKey === this._storageKey &&
|
|
222
|
+
event.data.entity.nodeIdentity !== this._nodeIdentity) {
|
|
223
|
+
await this._entityStorageConnector.set(event.data.entity);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Handle a remote item remove event.
|
|
228
|
+
* @param params The event parameters
|
|
229
|
+
* @internal
|
|
230
|
+
*/
|
|
231
|
+
async handleRemoteItemRemove(params) {
|
|
232
|
+
// Only remove the item if it matches the storage key
|
|
233
|
+
// and it is from another node, remote updates can not change data for this node
|
|
234
|
+
// That must be done via the regular entity storage methods
|
|
235
|
+
if (params.data.storageKey === this._storageKey &&
|
|
236
|
+
params.data.nodeIdentity !== this._nodeIdentity) {
|
|
237
|
+
await this._entityStorageConnector.remove(params.data.id);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Handle a batch request.
|
|
242
|
+
* @param event The request parameters
|
|
243
|
+
* @internal
|
|
244
|
+
*/
|
|
245
|
+
async handleBatchRequest(event) {
|
|
246
|
+
// Only handle the request if it matches the storage key
|
|
247
|
+
if (event.data.storageKey === this._storageKey) {
|
|
248
|
+
let cursor;
|
|
249
|
+
do {
|
|
250
|
+
const condition = {
|
|
251
|
+
conditions: []
|
|
252
|
+
};
|
|
253
|
+
if (event.data.requestMode === SyncNodeIdentityMode.Local ||
|
|
254
|
+
event.data.requestMode === SyncNodeIdentityMode.Remote) {
|
|
255
|
+
condition.conditions.push({
|
|
256
|
+
property: "nodeIdentity",
|
|
257
|
+
value: this._nodeIdentity,
|
|
258
|
+
comparison: event.data.requestMode === SyncNodeIdentityMode.Local
|
|
259
|
+
? ComparisonOperator.Equals
|
|
260
|
+
: ComparisonOperator.NotEquals
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const result = await this._entityStorageConnector.query(condition, [{ property: "dateModified", sortDirection: SortDirection.Ascending }], undefined, cursor, event.data.batchSize);
|
|
264
|
+
cursor = result.cursor;
|
|
265
|
+
// Publish the batch response with the entities
|
|
266
|
+
this._eventBusComponent.publish(SynchronisedStorageTopics.BatchResponse, {
|
|
267
|
+
storageKey: this._storageKey,
|
|
268
|
+
entities: result.entities,
|
|
269
|
+
lastEntry: !Is.stringValue(cursor)
|
|
270
|
+
});
|
|
271
|
+
} while (Is.stringValue(cursor));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Handle a reset event.
|
|
276
|
+
* @param event The event parameters
|
|
277
|
+
* @internal
|
|
278
|
+
*/
|
|
279
|
+
async handleReset(event) {
|
|
280
|
+
// Only reset the storage if it matches the storage key
|
|
281
|
+
if (event.data.storageKey === this._storageKey) {
|
|
282
|
+
let cursor;
|
|
283
|
+
let toRemove = [];
|
|
284
|
+
// Build a list of the ids to remove
|
|
285
|
+
do {
|
|
286
|
+
const condition = {
|
|
287
|
+
conditions: []
|
|
288
|
+
};
|
|
289
|
+
// Depending on the reset mode we can filter the entities to remove
|
|
290
|
+
if (event.data.resetMode === SyncNodeIdentityMode.Local ||
|
|
291
|
+
event.data.resetMode === SyncNodeIdentityMode.Remote) {
|
|
292
|
+
condition.conditions.push({
|
|
293
|
+
property: "nodeIdentity",
|
|
294
|
+
value: this._nodeIdentity,
|
|
295
|
+
comparison: event.data.resetMode === SyncNodeIdentityMode.Local
|
|
296
|
+
? ComparisonOperator.Equals
|
|
297
|
+
: ComparisonOperator.NotEquals
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
const result = await this._entityStorageConnector.query(condition, undefined, undefined, cursor);
|
|
301
|
+
cursor = result.cursor;
|
|
302
|
+
toRemove = toRemove.concat(result.entities.map(entity => entity.id));
|
|
303
|
+
} while (Is.stringValue(cursor));
|
|
304
|
+
// Remove the entities
|
|
305
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
306
|
+
await this.remove(toRemove[i]);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
206
310
|
}
|
|
207
311
|
|
|
208
312
|
export { SynchronisedEntityStorageConnector };
|
|
@@ -23,11 +23,11 @@ export declare class SynchronisedEntityStorageConnector<T extends ISynchronisedE
|
|
|
23
23
|
/**
|
|
24
24
|
* The component needs to be started when the node is initialized.
|
|
25
25
|
* @param nodeIdentity The identity of the node starting the component.
|
|
26
|
-
* @param
|
|
26
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
27
27
|
* @param componentState A persistent state which can be modified by the method.
|
|
28
28
|
* @returns Nothing.
|
|
29
29
|
*/
|
|
30
|
-
start(nodeIdentity: string,
|
|
30
|
+
start(nodeIdentity: string, nodeLoggingComponentType: string | undefined, componentState?: {
|
|
31
31
|
[id: string]: unknown;
|
|
32
32
|
}): Promise<void>;
|
|
33
33
|
/**
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.6](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.5...entity-storage-connector-synchronised-v0.0.2-next.6) (2025-08-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* update framework core ([b59a380](https://github.com/twinfoundation/entity-storage/commit/b59a380bb7fba2b43610f69074dcdee24a4737da))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
18
|
+
|
|
19
|
+
## [0.0.2-next.5](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.4...entity-storage-connector-synchronised-v0.0.2-next.5) (2025-08-11)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* support new synchronised storage features ([0d9ebab](https://github.com/twinfoundation/entity-storage/commit/0d9ebab237040892cab8e7db751aa2e40c0c76e0))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
32
|
+
* devDependencies
|
|
33
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
34
|
+
|
|
3
35
|
## [0.0.2-next.4](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-synchronised-v0.0.2-next.3...entity-storage-connector-synchronised-v0.0.2-next.4) (2025-08-08)
|
|
4
36
|
|
|
5
37
|
|
|
@@ -66,7 +66,7 @@ The schema for the entities.
|
|
|
66
66
|
|
|
67
67
|
### start()
|
|
68
68
|
|
|
69
|
-
> **start**(`nodeIdentity`, `
|
|
69
|
+
> **start**(`nodeIdentity`, `nodeLoggingComponentType`, `componentState?`): `Promise`\<`void`\>
|
|
70
70
|
|
|
71
71
|
The component needs to be started when the node is initialized.
|
|
72
72
|
|
|
@@ -78,9 +78,9 @@ The component needs to be started when the node is initialized.
|
|
|
78
78
|
|
|
79
79
|
The identity of the node starting the component.
|
|
80
80
|
|
|
81
|
-
#####
|
|
81
|
+
##### nodeLoggingComponentType
|
|
82
82
|
|
|
83
|
-
The node logging
|
|
83
|
+
The node logging component type.
|
|
84
84
|
|
|
85
85
|
`undefined` | `string`
|
|
86
86
|
|
|
@@ -204,7 +204,7 @@ Nothing.
|
|
|
204
204
|
|
|
205
205
|
### query()
|
|
206
206
|
|
|
207
|
-
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `pageSize?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor
|
|
207
|
+
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `pageSize?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
|
|
208
208
|
|
|
209
209
|
Find all the entities which match the conditions.
|
|
210
210
|
|
|
@@ -242,7 +242,7 @@ The suggested number of entities to return in each chunk, in some scenarios can
|
|
|
242
242
|
|
|
243
243
|
#### Returns
|
|
244
244
|
|
|
245
|
-
`Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor
|
|
245
|
+
`Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
|
|
246
246
|
|
|
247
247
|
All the entities for the storage matching the conditions,
|
|
248
248
|
and a cursor which can be used to request more entities.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-synchronised",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.6",
|
|
4
4
|
"description": "Entity Storage connector implementation using synchronised storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@twin.org/core": "next",
|
|
18
18
|
"@twin.org/entity": "next",
|
|
19
|
-
"@twin.org/entity-storage-models": "0.0.2-next.
|
|
19
|
+
"@twin.org/entity-storage-models": "0.0.2-next.6",
|
|
20
20
|
"@twin.org/event-bus-models": "next",
|
|
21
21
|
"@twin.org/logging-models": "next",
|
|
22
22
|
"@twin.org/nameof": "next",
|