@twin.org/synchronised-storage-service 0.0.1-next.9 → 0.0.3-next.2
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/data/verifiableStorageKeys.json +5 -0
- package/dist/es/entities/syncSnapshotEntry.js +93 -0
- package/dist/es/entities/syncSnapshotEntry.js.map +1 -0
- package/dist/es/helpers/blobStorageHelper.js +185 -0
- package/dist/es/helpers/blobStorageHelper.js.map +1 -0
- package/dist/es/helpers/changeSetHelper.js +215 -0
- package/dist/es/helpers/changeSetHelper.js.map +1 -0
- package/dist/es/helpers/localSyncStateHelper.js +384 -0
- package/dist/es/helpers/localSyncStateHelper.js.map +1 -0
- package/dist/es/helpers/remoteSyncStateHelper.js +560 -0
- package/dist/es/helpers/remoteSyncStateHelper.js.map +1 -0
- package/dist/es/helpers/versions.js +6 -0
- package/dist/es/helpers/versions.js.map +1 -0
- package/dist/es/index.js +13 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/ISyncPointerStore.js +4 -0
- package/dist/es/models/ISyncPointerStore.js.map +1 -0
- package/dist/es/models/ISyncSnapshot.js +4 -0
- package/dist/es/models/ISyncSnapshot.js.map +1 -0
- package/dist/es/models/ISyncState.js +2 -0
- package/dist/es/models/ISyncState.js.map +1 -0
- package/dist/es/models/ISynchronisedStorageServiceConfig.js +4 -0
- package/dist/es/models/ISynchronisedStorageServiceConfig.js.map +1 -0
- package/dist/es/models/ISynchronisedStorageServiceConstructorOptions.js +2 -0
- package/dist/es/models/ISynchronisedStorageServiceConstructorOptions.js.map +1 -0
- package/dist/es/restEntryPoints.js +10 -0
- package/dist/es/restEntryPoints.js.map +1 -0
- package/dist/es/schema.js +11 -0
- package/dist/es/schema.js.map +1 -0
- package/dist/es/synchronisedStorageRoutes.js +142 -0
- package/dist/es/synchronisedStorageRoutes.js.map +1 -0
- package/dist/es/synchronisedStorageService.js +512 -0
- package/dist/es/synchronisedStorageService.js.map +1 -0
- package/dist/types/entities/syncSnapshotEntry.d.ts +3 -3
- package/dist/types/helpers/blobStorageHelper.d.ts +3 -3
- package/dist/types/helpers/changeSetHelper.d.ts +16 -32
- package/dist/types/helpers/localSyncStateHelper.d.ts +11 -11
- package/dist/types/helpers/remoteSyncStateHelper.d.ts +18 -14
- package/dist/types/index.d.ts +10 -10
- package/dist/types/models/ISyncState.d.ts +1 -1
- package/dist/types/models/ISynchronisedStorageServiceConfig.d.ts +7 -8
- package/dist/types/models/ISynchronisedStorageServiceConstructorOptions.d.ts +6 -6
- package/dist/types/synchronisedStorageRoutes.d.ts +1 -1
- package/dist/types/synchronisedStorageService.d.ts +17 -21
- package/docs/architecture.md +168 -12
- package/docs/changelog.md +149 -0
- package/docs/open-api/spec.json +62 -57
- package/docs/reference/classes/SyncSnapshotEntry.md +4 -10
- package/docs/reference/classes/SynchronisedStorageService.md +38 -50
- package/docs/reference/interfaces/ISynchronisedStorageServiceConfig.md +11 -17
- package/docs/reference/interfaces/ISynchronisedStorageServiceConstructorOptions.md +8 -8
- package/locales/en.json +7 -15
- package/package.json +26 -9
- package/dist/cjs/index.cjs +0 -2235
- package/dist/esm/index.mjs +0 -2227
|
@@ -1,81 +1,65 @@
|
|
|
1
1
|
import type { IEventBusComponent } from "@twin.org/event-bus-models";
|
|
2
|
-
import { type IIdentityConnector } from "@twin.org/identity-models";
|
|
3
2
|
import type { ILoggingComponent } from "@twin.org/logging-models";
|
|
4
|
-
import { type
|
|
5
|
-
import
|
|
6
|
-
import type { BlobStorageHelper } from "./blobStorageHelper";
|
|
3
|
+
import { type ISyncChangeSet, type SyncNodeIdMode } from "@twin.org/synchronised-storage-models";
|
|
4
|
+
import type { BlobStorageHelper } from "./blobStorageHelper.js";
|
|
7
5
|
/**
|
|
8
6
|
* Class for performing change set operations.
|
|
9
7
|
*/
|
|
10
|
-
export declare class ChangeSetHelper
|
|
8
|
+
export declare class ChangeSetHelper {
|
|
11
9
|
/**
|
|
12
10
|
* Runtime name for the class.
|
|
13
11
|
*/
|
|
14
|
-
readonly CLASS_NAME: string;
|
|
12
|
+
static readonly CLASS_NAME: string;
|
|
15
13
|
/**
|
|
16
14
|
* Create a new instance of ChangeSetHelper.
|
|
17
|
-
* @param
|
|
15
|
+
* @param logging The logging component to use for logging.
|
|
18
16
|
* @param eventBusComponent The event bus component to use for events.
|
|
19
|
-
* @param identityConnector The identity connector to use for signing/verifying changesets.
|
|
20
17
|
* @param blobStorageHelper The blob storage component to use for remote sync states.
|
|
21
|
-
* @param decentralisedStorageMethodId The id of the identity method to use when signing/verifying changesets.
|
|
22
18
|
*/
|
|
23
|
-
constructor(
|
|
19
|
+
constructor(logging: ILoggingComponent | undefined, eventBusComponent: IEventBusComponent, blobStorageHelper: BlobStorageHelper);
|
|
24
20
|
/**
|
|
25
21
|
* Set the node identity to use for signing changesets.
|
|
26
|
-
* @param
|
|
22
|
+
* @param nodeId The identity of the node that is performing the update.
|
|
27
23
|
*/
|
|
28
|
-
|
|
24
|
+
setNodeId(nodeId: string): void;
|
|
29
25
|
/**
|
|
30
|
-
* Get
|
|
26
|
+
* Get a changeset.
|
|
31
27
|
* @param changeSetStorageId The id of the sync changeset to apply.
|
|
32
28
|
* @returns The changeset if it was verified.
|
|
33
29
|
*/
|
|
34
|
-
|
|
30
|
+
getChangeset(changeSetStorageId: string): Promise<ISyncChangeSet | undefined>;
|
|
35
31
|
/**
|
|
36
32
|
* Apply a sync changeset.
|
|
37
33
|
* @param changeSetStorageId The id of the sync changeset to apply.
|
|
38
34
|
* @returns The changeset if it existed.
|
|
39
35
|
*/
|
|
40
|
-
getAndApplyChangeset(changeSetStorageId: string): Promise<ISyncChangeSet
|
|
36
|
+
getAndApplyChangeset(changeSetStorageId: string): Promise<ISyncChangeSet | undefined>;
|
|
41
37
|
/**
|
|
42
38
|
* Apply a sync changeset.
|
|
43
39
|
* @param syncChangeset The sync changeset to apply.
|
|
44
40
|
* @returns Nothing.
|
|
45
41
|
*/
|
|
46
|
-
applyChangeset(syncChangeset: ISyncChangeSet
|
|
42
|
+
applyChangeset(syncChangeset: ISyncChangeSet): Promise<void>;
|
|
47
43
|
/**
|
|
48
44
|
* Store the changeset.
|
|
49
45
|
* @param syncChangeSet The sync change set to store.
|
|
50
46
|
* @returns The id of the change set.
|
|
51
47
|
*/
|
|
52
48
|
storeChangeSet(syncChangeSet: ISyncChangeSet): Promise<string>;
|
|
53
|
-
/**
|
|
54
|
-
* Verify the proof of a sync changeset.
|
|
55
|
-
* @param syncChangeset The sync changeset to verify.
|
|
56
|
-
* @returns True if the proof is valid, false otherwise.
|
|
57
|
-
*/
|
|
58
|
-
verifyChangesetProof(syncChangeset: ISyncChangeSet): Promise<boolean>;
|
|
59
|
-
/**
|
|
60
|
-
* Create the proof of a sync change set.
|
|
61
|
-
* @param syncChangeset The sync changeset to create the proof for.
|
|
62
|
-
* @returns The proof.
|
|
63
|
-
*/
|
|
64
|
-
createChangeSetProof(syncChangeset: ISyncChangeSet): Promise<IProof>;
|
|
65
49
|
/**
|
|
66
50
|
* Copy a change set.
|
|
67
51
|
* @param syncChangeSet The sync changeset to copy.
|
|
68
52
|
* @returns The id of the updated change set.
|
|
69
53
|
*/
|
|
70
|
-
copyChangeset(syncChangeSet: ISyncChangeSet
|
|
71
|
-
syncChangeSet: ISyncChangeSet
|
|
54
|
+
copyChangeset(syncChangeSet: ISyncChangeSet): Promise<{
|
|
55
|
+
syncChangeSet: ISyncChangeSet;
|
|
72
56
|
changeSetStorageId: string;
|
|
73
57
|
} | undefined>;
|
|
74
58
|
/**
|
|
75
59
|
* Reset the storage for a given storage key.
|
|
76
60
|
* @param storageKey The key of the storage to reset.
|
|
77
|
-
* @param resetMode The reset mode, this will use the
|
|
61
|
+
* @param resetMode The reset mode, this will use the nodeId in the entities to determine which are local/remote.
|
|
78
62
|
* @returns Nothing.
|
|
79
63
|
*/
|
|
80
|
-
reset(storageKey: string, resetMode:
|
|
64
|
+
reset(storageKey: string, resetMode: SyncNodeIdMode): Promise<void>;
|
|
81
65
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
|
|
2
2
|
import type { ILoggingComponent } from "@twin.org/logging-models";
|
|
3
|
-
import { type
|
|
4
|
-
import type { ChangeSetHelper } from "./changeSetHelper";
|
|
5
|
-
import type { SyncSnapshotEntry } from "../entities/syncSnapshotEntry";
|
|
6
|
-
import type { ISyncState } from "../models/ISyncState";
|
|
3
|
+
import { type SyncChangeOperation } from "@twin.org/synchronised-storage-models";
|
|
4
|
+
import type { ChangeSetHelper } from "./changeSetHelper.js";
|
|
5
|
+
import type { SyncSnapshotEntry } from "../entities/syncSnapshotEntry.js";
|
|
6
|
+
import type { ISyncState } from "../models/ISyncState.js";
|
|
7
7
|
/**
|
|
8
8
|
* Class for performing entity storage operations in decentralised storage.
|
|
9
9
|
*/
|
|
10
|
-
export declare class LocalSyncStateHelper
|
|
10
|
+
export declare class LocalSyncStateHelper {
|
|
11
11
|
/**
|
|
12
12
|
* Runtime name for the class.
|
|
13
13
|
*/
|
|
14
|
-
readonly CLASS_NAME: string;
|
|
14
|
+
static readonly CLASS_NAME: string;
|
|
15
15
|
/**
|
|
16
16
|
* Create a new instance of LocalSyncStateHelper.
|
|
17
|
-
* @param
|
|
17
|
+
* @param logging The logging component to use for logging.
|
|
18
18
|
* @param snapshotEntryEntityStorage The storage connector for the sync snapshot entries.
|
|
19
19
|
* @param changeSetHelper The change set helper to use for applying changesets.
|
|
20
20
|
*/
|
|
21
|
-
constructor(
|
|
21
|
+
constructor(logging: ILoggingComponent | undefined, snapshotEntryEntityStorage: IEntityStorageConnector<SyncSnapshotEntry>, changeSetHelper: ChangeSetHelper);
|
|
22
22
|
/**
|
|
23
23
|
* Add a new change to the local snapshot.
|
|
24
24
|
* @param storageKey The storage key of the snapshot to add the change for.
|
|
@@ -33,19 +33,19 @@ export declare class LocalSyncStateHelper<T extends ISynchronisedEntity = ISynch
|
|
|
33
33
|
* @param isLocal Whether to get the local snapshot or not.
|
|
34
34
|
* @returns The local snapshot entry.
|
|
35
35
|
*/
|
|
36
|
-
getSnapshots(storageKey: string, isLocal: boolean): Promise<SyncSnapshotEntry
|
|
36
|
+
getSnapshots(storageKey: string, isLocal: boolean): Promise<SyncSnapshotEntry[]>;
|
|
37
37
|
/**
|
|
38
38
|
* Set the current local snapshot with changes for this node.
|
|
39
39
|
* @param localChangeSnapshot The local change snapshot to set.
|
|
40
40
|
* @returns Nothing.
|
|
41
41
|
*/
|
|
42
|
-
setLocalChangeSnapshot(localChangeSnapshot: SyncSnapshotEntry
|
|
42
|
+
setLocalChangeSnapshot(localChangeSnapshot: SyncSnapshotEntry): Promise<void>;
|
|
43
43
|
/**
|
|
44
44
|
* Get the current local snapshot with the changes for this node.
|
|
45
45
|
* @param localChangeSnapshot The local change snapshot to remove.
|
|
46
46
|
* @returns Nothing.
|
|
47
47
|
*/
|
|
48
|
-
removeLocalChangeSnapshot(localChangeSnapshot: SyncSnapshotEntry
|
|
48
|
+
removeLocalChangeSnapshot(localChangeSnapshot: SyncSnapshotEntry): Promise<void>;
|
|
49
49
|
/**
|
|
50
50
|
* Apply a sync state to the local node.
|
|
51
51
|
* @param storageKey The storage key of the snapshot to sync with.
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import type { IEventBusComponent } from "@twin.org/event-bus-models";
|
|
2
2
|
import type { ILoggingComponent } from "@twin.org/logging-models";
|
|
3
|
-
import { type ISyncChange, type ISyncChangeSet
|
|
3
|
+
import { type ISyncChange, type ISyncChangeSet } from "@twin.org/synchronised-storage-models";
|
|
4
4
|
import type { IVerifiableStorageConnector } from "@twin.org/verifiable-storage-models";
|
|
5
|
-
import type { BlobStorageHelper } from "./blobStorageHelper";
|
|
6
|
-
import type { ChangeSetHelper } from "./changeSetHelper";
|
|
7
|
-
import type { ISyncPointerStore } from "../models/ISyncPointerStore";
|
|
8
|
-
import type { ISyncState } from "../models/ISyncState";
|
|
5
|
+
import type { BlobStorageHelper } from "./blobStorageHelper.js";
|
|
6
|
+
import type { ChangeSetHelper } from "./changeSetHelper.js";
|
|
7
|
+
import type { ISyncPointerStore } from "../models/ISyncPointerStore.js";
|
|
8
|
+
import type { ISyncState } from "../models/ISyncState.js";
|
|
9
9
|
/**
|
|
10
10
|
* Class for performing entity storage operations in decentralised storage.
|
|
11
11
|
*/
|
|
12
|
-
export declare class RemoteSyncStateHelper
|
|
12
|
+
export declare class RemoteSyncStateHelper {
|
|
13
13
|
/**
|
|
14
14
|
* Runtime name for the class.
|
|
15
15
|
*/
|
|
16
|
-
readonly CLASS_NAME: string;
|
|
16
|
+
static readonly CLASS_NAME: string;
|
|
17
17
|
/**
|
|
18
|
-
* Create a new instance of
|
|
18
|
+
* Create a new instance of RemoteSyncStateHelper.
|
|
19
19
|
* @param loggingComponent The logging component to use for logging.
|
|
20
20
|
* @param eventBusComponent The event bus component to use for events.
|
|
21
21
|
* @param verifiableSyncPointerStorageConnector The verifiable storage connector to use for storing sync pointers.
|
|
@@ -24,12 +24,16 @@ export declare class RemoteSyncStateHelper<T extends ISynchronisedEntity = ISync
|
|
|
24
24
|
* @param isTrustedNode Whether the node is trusted or not.
|
|
25
25
|
* @param maxConsolidations The maximum number of consolidations to keep in storage.
|
|
26
26
|
*/
|
|
27
|
-
constructor(loggingComponent: ILoggingComponent | undefined, eventBusComponent: IEventBusComponent, verifiableSyncPointerStorageConnector: IVerifiableStorageConnector, blobStorageHelper: BlobStorageHelper, changeSetHelper: ChangeSetHelper
|
|
27
|
+
constructor(loggingComponent: ILoggingComponent | undefined, eventBusComponent: IEventBusComponent, verifiableSyncPointerStorageConnector: IVerifiableStorageConnector, blobStorageHelper: BlobStorageHelper, changeSetHelper: ChangeSetHelper, isTrustedNode: boolean, maxConsolidations: number);
|
|
28
28
|
/**
|
|
29
29
|
* Set the node identity to use for signing changesets.
|
|
30
|
-
* @param
|
|
30
|
+
* @param nodeId The identity of the node that is performing the update.
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
setNodeId(nodeId: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Start the remote sync state helper.
|
|
35
|
+
*/
|
|
36
|
+
start(): Promise<void>;
|
|
33
37
|
/**
|
|
34
38
|
* Set the synchronised storage key.
|
|
35
39
|
* @param synchronisedStorageKey The synchronised storage key to use.
|
|
@@ -42,18 +46,18 @@ export declare class RemoteSyncStateHelper<T extends ISynchronisedEntity = ISync
|
|
|
42
46
|
* @param completeCallback The callback to call when the changeset is created and stored.
|
|
43
47
|
* @returns The storage id of the change set if created.
|
|
44
48
|
*/
|
|
45
|
-
buildChangeSet(storageKey: string, changes: ISyncChange
|
|
49
|
+
buildChangeSet(storageKey: string, changes: ISyncChange[], completeCallback: (syncChangeSet?: ISyncChangeSet, id?: string) => Promise<void>): Promise<void>;
|
|
46
50
|
/**
|
|
47
51
|
* Finalise the full details for the sync change set.
|
|
48
52
|
* @param storageKey The storage key of the change set.
|
|
49
53
|
* @param completeCallback The callback to call when the changeset is populated.
|
|
50
54
|
* @returns Nothing.
|
|
51
55
|
*/
|
|
52
|
-
finaliseFullChanges(storageKey: string, completeCallback: (syncChangeSet?: ISyncChangeSet
|
|
56
|
+
finaliseFullChanges(storageKey: string, completeCallback: (syncChangeSet?: ISyncChangeSet, id?: string) => Promise<void>): Promise<void>;
|
|
53
57
|
/**
|
|
54
58
|
* Add a new changeset into the sync state.
|
|
55
59
|
* @param storageKey The storage key of the change set to add.
|
|
56
|
-
* @param changeSetStorageId The id of the change set to add the
|
|
60
|
+
* @param changeSetStorageId The id of the change set to add the current state
|
|
57
61
|
* @returns Nothing.
|
|
58
62
|
*/
|
|
59
63
|
addChangeSetToSyncState(storageKey: string, changeSetStorageId: string): Promise<void>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export * from "./entities/syncSnapshotEntry";
|
|
2
|
-
export * from "./models/ISynchronisedStorageServiceConfig";
|
|
3
|
-
export * from "./models/ISynchronisedStorageServiceConstructorOptions";
|
|
4
|
-
export * from "./models/ISyncPointerStore";
|
|
5
|
-
export * from "./models/ISyncSnapshot";
|
|
6
|
-
export * from "./models/ISyncState";
|
|
7
|
-
export * from "./restEntryPoints";
|
|
8
|
-
export * from "./schema";
|
|
9
|
-
export * from "./synchronisedStorageRoutes";
|
|
10
|
-
export * from "./synchronisedStorageService";
|
|
1
|
+
export * from "./entities/syncSnapshotEntry.js";
|
|
2
|
+
export * from "./models/ISynchronisedStorageServiceConfig.js";
|
|
3
|
+
export * from "./models/ISynchronisedStorageServiceConstructorOptions.js";
|
|
4
|
+
export * from "./models/ISyncPointerStore.js";
|
|
5
|
+
export * from "./models/ISyncSnapshot.js";
|
|
6
|
+
export * from "./models/ISyncState.js";
|
|
7
|
+
export * from "./restEntryPoints.js";
|
|
8
|
+
export * from "./schema.js";
|
|
9
|
+
export * from "./synchronisedStorageRoutes.js";
|
|
10
|
+
export * from "./synchronisedStorageService.js";
|
|
@@ -2,28 +2,23 @@
|
|
|
2
2
|
* Configuration for the Synchronised Storage Service.
|
|
3
3
|
*/
|
|
4
4
|
export interface ISynchronisedStorageServiceConfig {
|
|
5
|
-
/**
|
|
6
|
-
* The id of the identity method to use when signing/verifying requests and changesets.
|
|
7
|
-
* @default synchronised-storage-assertion
|
|
8
|
-
*/
|
|
9
|
-
synchronisedStorageMethodId?: string;
|
|
10
5
|
/**
|
|
11
6
|
* How often to check for entity updates in minutes.
|
|
12
7
|
* @default 5
|
|
13
8
|
*/
|
|
14
9
|
entityUpdateIntervalMinutes?: number;
|
|
15
10
|
/**
|
|
16
|
-
* Interval to perform consolidation of changesets, only used if
|
|
11
|
+
* Interval to perform consolidation of changesets, only used if this is a trusted node.
|
|
17
12
|
* @default 60
|
|
18
13
|
*/
|
|
19
14
|
consolidationIntervalMinutes?: number;
|
|
20
15
|
/**
|
|
21
|
-
* The number of entities to process in a single consolidation batch.
|
|
16
|
+
* The number of entities to process in a single consolidation batch, only used if this is a trusted node.
|
|
22
17
|
* @default 1000
|
|
23
18
|
*/
|
|
24
19
|
consolidationBatchSize?: number;
|
|
25
20
|
/**
|
|
26
|
-
* The maximum number of consolidations to keep in storage.
|
|
21
|
+
* The maximum number of consolidations to keep in storage, only used if this is a trusted node.
|
|
27
22
|
* @default 5
|
|
28
23
|
*/
|
|
29
24
|
maxConsolidations?: number;
|
|
@@ -38,4 +33,8 @@ export interface ISynchronisedStorageServiceConfig {
|
|
|
38
33
|
* @default local
|
|
39
34
|
*/
|
|
40
35
|
verifiableStorageKeyId: "mainnet" | "testnet" | "devnet" | string;
|
|
36
|
+
/**
|
|
37
|
+
* Override the default trust generator.
|
|
38
|
+
*/
|
|
39
|
+
overrideTrustGeneratorType?: string;
|
|
41
40
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ISynchronisedStorageServiceConfig } from "./ISynchronisedStorageServiceConfig";
|
|
1
|
+
import type { ISynchronisedStorageServiceConfig } from "./ISynchronisedStorageServiceConfig.js";
|
|
2
2
|
/**
|
|
3
3
|
* Options for the Synchronised Storage Service constructor.
|
|
4
4
|
*/
|
|
@@ -30,16 +30,16 @@ export interface ISynchronisedStorageServiceConstructorOptions {
|
|
|
30
30
|
* @default verifiable-storage
|
|
31
31
|
*/
|
|
32
32
|
verifiableStorageConnectorType?: string;
|
|
33
|
-
/**
|
|
34
|
-
* The identity connector.
|
|
35
|
-
* @default identity
|
|
36
|
-
*/
|
|
37
|
-
identityConnectorType?: string;
|
|
38
33
|
/**
|
|
39
34
|
* The task scheduler component.
|
|
40
35
|
* @default task-scheduler
|
|
41
36
|
*/
|
|
42
37
|
taskSchedulerComponentType?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The type of the trust component.
|
|
40
|
+
* @default trust
|
|
41
|
+
*/
|
|
42
|
+
trustComponentType?: string;
|
|
43
43
|
/**
|
|
44
44
|
* The synchronised entity storage component type to use if this node is not trusted.
|
|
45
45
|
* If this is set, this node uses it as the trusted node to store changesets.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IHttpRequestContext, INoContentResponse, IRestRoute, ITag } from "@twin.org/api-models";
|
|
2
|
-
import type
|
|
2
|
+
import { type ISyncChangeSetRequest, type ISyncDecryptionKeyRequest, type ISyncDecryptionKeyResponse } from "@twin.org/synchronised-storage-models";
|
|
3
3
|
/**
|
|
4
4
|
* The tag to associate with the routes.
|
|
5
5
|
*/
|
|
@@ -1,51 +1,47 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import
|
|
3
|
-
import type { ISynchronisedStorageServiceConstructorOptions } from "./models/ISynchronisedStorageServiceConstructorOptions";
|
|
1
|
+
import { type ISyncChangeSet, type ISynchronisedStorageComponent } from "@twin.org/synchronised-storage-models";
|
|
2
|
+
import type { ISynchronisedStorageServiceConstructorOptions } from "./models/ISynchronisedStorageServiceConstructorOptions.js";
|
|
4
3
|
/**
|
|
5
4
|
* Class for performing synchronised storage operations.
|
|
6
5
|
*/
|
|
7
|
-
export declare class SynchronisedStorageService
|
|
6
|
+
export declare class SynchronisedStorageService implements ISynchronisedStorageComponent {
|
|
8
7
|
/**
|
|
9
8
|
* Runtime name for the class.
|
|
10
9
|
*/
|
|
11
|
-
readonly CLASS_NAME: string;
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
12
11
|
/**
|
|
13
12
|
* Create a new instance of SynchronisedStorageService.
|
|
14
13
|
* @param options The options for the service.
|
|
15
14
|
*/
|
|
16
15
|
constructor(options: ISynchronisedStorageServiceConstructorOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Returns the class name of the component.
|
|
18
|
+
* @returns The class name of the component.
|
|
19
|
+
*/
|
|
20
|
+
className(): string;
|
|
17
21
|
/**
|
|
18
22
|
* The component needs to be started when the node is initialized.
|
|
19
|
-
* @param
|
|
20
|
-
* @param nodeLoggingConnectorType The node logging connector type, defaults to "node-logging".
|
|
21
|
-
* @param componentState A persistent state which can be modified by the method.
|
|
23
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
22
24
|
* @returns Nothing.
|
|
23
25
|
*/
|
|
24
|
-
start(
|
|
25
|
-
[id: string]: unknown;
|
|
26
|
-
}): Promise<void>;
|
|
26
|
+
start(nodeLoggingComponentType?: string): Promise<void>;
|
|
27
27
|
/**
|
|
28
28
|
* The component needs to be stopped when the node is closed.
|
|
29
|
-
* @param
|
|
30
|
-
* @param nodeLoggingConnectorType The node logging connector type, defaults to "node-logging".
|
|
31
|
-
* @param componentState A persistent state which can be modified by the method.
|
|
29
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
32
30
|
* @returns Nothing.
|
|
33
31
|
*/
|
|
34
|
-
stop(
|
|
35
|
-
[id: string]: unknown;
|
|
36
|
-
}): Promise<void>;
|
|
32
|
+
stop(nodeLoggingComponentType?: string): Promise<void>;
|
|
37
33
|
/**
|
|
38
34
|
* Get the decryption key for the synchronised storage.
|
|
39
35
|
* This is used to decrypt the data stored in the synchronised storage.
|
|
40
|
-
* @param
|
|
41
|
-
* @param proof The proof of the request so we know the request is from the specified node.
|
|
36
|
+
* @param trustPayload Trust payload to verify the requesters identity.
|
|
42
37
|
* @returns The decryption key.
|
|
43
38
|
*/
|
|
44
|
-
getDecryptionKey(
|
|
39
|
+
getDecryptionKey(trustPayload: unknown): Promise<string>;
|
|
45
40
|
/**
|
|
46
41
|
* Synchronise a set of changes from an untrusted node, assumes this is a trusted node.
|
|
47
42
|
* @param syncChangeSet The change set to synchronise.
|
|
43
|
+
* @param trustPayload Trust payload to verify the requesters identity.
|
|
48
44
|
* @returns Nothing.
|
|
49
45
|
*/
|
|
50
|
-
syncChangeSet(syncChangeSet: ISyncChangeSet
|
|
46
|
+
syncChangeSet(syncChangeSet: ISyncChangeSet, trustPayload: unknown): Promise<void>;
|
|
51
47
|
}
|
package/docs/architecture.md
CHANGED
|
@@ -62,7 +62,6 @@ The Synchronised Storage Service implements a distributed, eventually-consistent
|
|
|
62
62
|
┌───────────▼────────────┐
|
|
63
63
|
│ Verifiable Storage │
|
|
64
64
|
│ • On-chain Pointers │
|
|
65
|
-
│ • State Root Hashes │
|
|
66
65
|
│ • Access Control │
|
|
67
66
|
└───────────┬────────────┘
|
|
68
67
|
│
|
|
@@ -70,7 +69,6 @@ The Synchronised Storage Service implements a distributed, eventually-consistent
|
|
|
70
69
|
│ Decentralised Storage │
|
|
71
70
|
│ • IPFS/Content Hash │
|
|
72
71
|
│ • Immutable Blobs │
|
|
73
|
-
│ • Distributed Refs │
|
|
74
72
|
└────────────────────────┘
|
|
75
73
|
```
|
|
76
74
|
|
|
@@ -89,10 +87,9 @@ The Synchronised Storage Service implements a distributed, eventually-consistent
|
|
|
89
87
|
|
|
90
88
|
- **Multi-Node Architecture**: Multiple trusted nodes operate in parallel to distribute processing load and provide high availability
|
|
91
89
|
- **Change Validation**: Verify cryptographic signatures and node permissions across the cluster
|
|
92
|
-
- **Change Set Consolidation**: Periodic compaction of
|
|
93
|
-
- **Decentralised Storage Interface**: Upload/download operations to IPFS
|
|
90
|
+
- **Change Set Consolidation**: Periodic compaction of changes to create complete data sets
|
|
91
|
+
- **Decentralised Storage Interface**: Upload/download operations to e.g. IPFS
|
|
94
92
|
- **Verifiable Storage Updates**: Atomic updates to on-chain state pointers with consensus agreement
|
|
95
|
-
- **Load Distribution**: Automatic distribution of regular node connections and change processing across available trusted nodes
|
|
96
93
|
|
|
97
94
|
## Data Flow Architecture
|
|
98
95
|
|
|
@@ -105,24 +102,183 @@ EntityStorage → ChangeCapture → LocalSnapshot → EventBus
|
|
|
105
102
|
### 2. Change Set Propagation
|
|
106
103
|
|
|
107
104
|
```typescript
|
|
108
|
-
|
|
105
|
+
RegularNode → [Sign] → ChangeSet → TrustedNode → [Verify] → GlobalState
|
|
109
106
|
```
|
|
110
107
|
|
|
111
108
|
### 3. Global State Persistence
|
|
112
109
|
|
|
113
110
|
```typescript
|
|
114
|
-
TrustedNode → [
|
|
111
|
+
TrustedNode → [Encrypt & Compress] → DecentralisedStorage → [StateRoot] → VerifiableStorage
|
|
115
112
|
```
|
|
116
113
|
|
|
117
114
|
### 4. Remote Synchronisation
|
|
118
115
|
|
|
119
116
|
```typescript
|
|
120
|
-
AnyNode → [Poll] → VerifiableStorage → [Fetch] → DecentralisedStorage → [
|
|
117
|
+
AnyNode → [Poll] → VerifiableStorage → [Fetch] → DecentralisedStorage → [Decrypt & Decompress] → LocalState
|
|
121
118
|
```
|
|
122
119
|
|
|
120
|
+
## Synchronisation Algorithms
|
|
121
|
+
|
|
122
|
+
### Apply Sync State Logic
|
|
123
|
+
|
|
124
|
+
The `applySyncState` method in `LocalSyncStateHelper` implements the core synchronisation algorithm that reconciles remote sync state with local state. This algorithm handles both full and incremental synchronisation scenarios:
|
|
125
|
+
|
|
126
|
+
#### Algorithm Overview
|
|
127
|
+
|
|
128
|
+
**Input Processing:**
|
|
129
|
+
|
|
130
|
+
- Retrieves existing local snapshots and remote sync state snapshots
|
|
131
|
+
- Sorts both collections by creation date (newest to oldest) for temporal ordering
|
|
132
|
+
- Extracts epoch information for gap detection analysis
|
|
133
|
+
|
|
134
|
+
**Epoch Gap Detection:**
|
|
135
|
+
|
|
136
|
+
If the node has not been running for a while or has failed communications it might start to miss data, so we use gap detection to determine if we need to use a full consolidation snapshot.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const newestExistingEpoch = existingSnapshots[0]?.epoch ?? 0;
|
|
140
|
+
const oldestSyncStateEpoch = syncStateSnapshots[syncStateSnapshots.length - 1]?.epoch ?? 0;
|
|
141
|
+
const hasEpochGap = newestExistingEpoch + 1 < oldestSyncStateEpoch;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Synchronisation Strategy Decision:**
|
|
145
|
+
|
|
146
|
+
1. **Full Synchronisation Trigger:**
|
|
147
|
+
- No existing consolidated snapshots locally, OR
|
|
148
|
+
- Detected epoch gap between local and remote state
|
|
149
|
+
|
|
150
|
+
2. **Incremental Synchronisation Trigger:**
|
|
151
|
+
- Existing consolidated snapshots present AND
|
|
152
|
+
- No epoch gaps detected
|
|
153
|
+
|
|
154
|
+
#### Full Synchronisation Process
|
|
155
|
+
|
|
156
|
+
When full sync is required:
|
|
157
|
+
|
|
158
|
+
1. **Consolidation Search:** Locates the most recent consolidated snapshot in remote state
|
|
159
|
+
2. **Entity Storage Reset:** Clears all remote entities from local storage to ensure clean state, but retains all local entries maintained by this node
|
|
160
|
+
3. **Progressive Application:** Processes snapshots from the consolidation point forward to the newest, ensuring newer changes override older ones
|
|
161
|
+
4. **Change Set Processing:** Applies all change sets from the consolidation and subsequent modifications
|
|
162
|
+
|
|
163
|
+
#### Incremental Synchronisation Process
|
|
164
|
+
|
|
165
|
+
When incremental sync is sufficient:
|
|
166
|
+
|
|
167
|
+
1. **Snapshot Mapping:** Creates lookup map of existing local snapshots for efficient comparison
|
|
168
|
+
2. **Change Detection:** Categorises remote snapshots into:
|
|
169
|
+
- **New Snapshots:** Not present locally
|
|
170
|
+
- **Modified Snapshots:** Present but with different `dateModified`
|
|
171
|
+
- **Unchanged Snapshots:** Identical local and remote versions
|
|
172
|
+
|
|
173
|
+
3. **Processing Optimisation:** Stops processing when encountering an unchanged snapshot (temporal consistency guarantee)
|
|
174
|
+
|
|
175
|
+
4. **Change Set Application:**
|
|
176
|
+
- Processes modified snapshots to apply incremental changes
|
|
177
|
+
- Processes new snapshots in chronological order (oldest to newest)
|
|
178
|
+
- Removes unreferenced local snapshots for storage clean-up
|
|
179
|
+
|
|
180
|
+
#### Key Design Principles
|
|
181
|
+
|
|
182
|
+
- **Temporal Consistency:** Changes are applied in chronological order to maintain causality
|
|
183
|
+
- **Conflict Resolution:** Newer changes automatically override older ones within the same entity
|
|
184
|
+
- **Storage Efficiency:** Only processes changed or new snapshots, avoiding redundant operations
|
|
185
|
+
- **Data Integrity:** Maintains referential integrity by cleaning up orphaned snapshot references
|
|
186
|
+
- **Gap Recovery:** Automatically triggers full synchronisation when data continuity is compromised
|
|
187
|
+
|
|
188
|
+
#### Error Handling & Edge Cases
|
|
189
|
+
|
|
190
|
+
- **Missing Consolidations:** Logs warning when full sync is needed but no consolidated snapshot is available
|
|
191
|
+
- **Empty Remote State:** Handles scenarios where remote sync state contains no snapshots
|
|
192
|
+
- **Epoch Inconsistencies:** Automatically recovers from epoch gaps through full synchronisation
|
|
193
|
+
- **Processing Interruption:** Uses `completedProcessing` flag to optimise incremental sync execution
|
|
194
|
+
|
|
195
|
+
This algorithm ensures eventually consistent data replication across distributed nodes while minimising network traffic and computational overhead through intelligent synchronisation strategy selection.
|
|
196
|
+
|
|
123
197
|
## Data Structures
|
|
124
198
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
199
|
+
### Sync Pointer Store
|
|
200
|
+
|
|
201
|
+
Stored in verifiable storage, for each storage type contains a storage id of the location for sync states.
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"syncPointers": {
|
|
206
|
+
"my-type-1": "blob:ipfs:0x11...1111",
|
|
207
|
+
"my-type-2": "blob:ipfs:0x22...2222"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Sync State
|
|
213
|
+
|
|
214
|
+
Stored in decentralised storage, contains all of the snapshots for a specific storage key
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"storageKey": "my-type-1",
|
|
219
|
+
"snapshots": [
|
|
220
|
+
{
|
|
221
|
+
"id": "0xaaa...aaa",
|
|
222
|
+
...
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "0xbbb...bbb",
|
|
226
|
+
...
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Sync Snapshot
|
|
233
|
+
|
|
234
|
+
Contains a list of all the storage ids for the change sets which make up the snapshot
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"id": "0xaaa...aaa",
|
|
239
|
+
"dateCreated": "2025-05-29T01:00:00.000Z",
|
|
240
|
+
"dateModified": "2025-05-29T01:00:00.000Z",
|
|
241
|
+
"isConsolidated": false, // Determines if this contains a complete data set
|
|
242
|
+
"epoch": 123, // A counter that is incremented for each snapshot
|
|
243
|
+
"changeSetStorageIds": [
|
|
244
|
+
"blob:ipfs:0x111...1111",
|
|
245
|
+
"blob:ipfs:0x111...1112"
|
|
246
|
+
...
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Sync Change Set
|
|
252
|
+
|
|
253
|
+
Contains a set of changes to be made to the entity storage, the proof is generated by the node identity which guarantees the validity of the data from the node
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"id": "0xaaa...aaa",
|
|
258
|
+
"storageKey": "my-type-1",
|
|
259
|
+
"dateCreated": "2025-05-29T01:00:00.000Z",
|
|
260
|
+
"dateModified": "2025-05-29T01:00:00.000Z",
|
|
261
|
+
"changes": [
|
|
262
|
+
...
|
|
263
|
+
],
|
|
264
|
+
"nodeIdentity": "did:iota:0xccc.cccccc",
|
|
265
|
+
"proof": {
|
|
266
|
+
// Cryptographic proof signed by the node identity
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Sync Change
|
|
272
|
+
|
|
273
|
+
Contains a mutation for an entry in entity storage, either a `set` of `delete`. The `id` and `nodeIdentity` are omitted from the entity and stored at a higher level in the data structures to shrink the data set size.
|
|
274
|
+
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"operation": "set",
|
|
278
|
+
"id": "my-item-1",
|
|
279
|
+
"entity": {
|
|
280
|
+
"foo": true,
|
|
281
|
+
"bar": 123
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|