@optimystic/db-p2p 0.0.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/index.min.js +52 -0
- package/dist/index.min.js.map +7 -0
- package/dist/src/cluster/client.d.ts +12 -0
- package/dist/src/cluster/client.d.ts.map +1 -0
- package/dist/src/cluster/client.js +65 -0
- package/dist/src/cluster/client.js.map +1 -0
- package/dist/src/cluster/cluster-repo.d.ts +79 -0
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -0
- package/dist/src/cluster/cluster-repo.js +613 -0
- package/dist/src/cluster/cluster-repo.js.map +1 -0
- package/dist/src/cluster/partition-detector.d.ts +59 -0
- package/dist/src/cluster/partition-detector.d.ts.map +1 -0
- package/dist/src/cluster/partition-detector.js +129 -0
- package/dist/src/cluster/partition-detector.js.map +1 -0
- package/dist/src/cluster/service.d.ts +49 -0
- package/dist/src/cluster/service.d.ts.map +1 -0
- package/dist/src/cluster/service.js +107 -0
- package/dist/src/cluster/service.js.map +1 -0
- package/dist/src/index.d.ts +29 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +29 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/it-utility.d.ts +4 -0
- package/dist/src/it-utility.d.ts.map +1 -0
- package/dist/src/it-utility.js +32 -0
- package/dist/src/it-utility.js.map +1 -0
- package/dist/src/libp2p-key-network.d.ts +59 -0
- package/dist/src/libp2p-key-network.d.ts.map +1 -0
- package/dist/src/libp2p-key-network.js +278 -0
- package/dist/src/libp2p-key-network.js.map +1 -0
- package/dist/src/libp2p-node.d.ts +28 -0
- package/dist/src/libp2p-node.d.ts.map +1 -0
- package/dist/src/libp2p-node.js +270 -0
- package/dist/src/libp2p-node.js.map +1 -0
- package/dist/src/logger.d.ts +3 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +6 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/network/get-network-manager.d.ts +4 -0
- package/dist/src/network/get-network-manager.d.ts.map +1 -0
- package/dist/src/network/get-network-manager.js +17 -0
- package/dist/src/network/get-network-manager.js.map +1 -0
- package/dist/src/network/network-manager-service.d.ts +82 -0
- package/dist/src/network/network-manager-service.d.ts.map +1 -0
- package/dist/src/network/network-manager-service.js +283 -0
- package/dist/src/network/network-manager-service.js.map +1 -0
- package/dist/src/peer-utils.d.ts +2 -0
- package/dist/src/peer-utils.d.ts.map +1 -0
- package/dist/src/peer-utils.js +28 -0
- package/dist/src/peer-utils.js.map +1 -0
- package/dist/src/protocol-client.d.ts +12 -0
- package/dist/src/protocol-client.d.ts.map +1 -0
- package/dist/src/protocol-client.js +34 -0
- package/dist/src/protocol-client.js.map +1 -0
- package/dist/src/repo/client.d.ts +17 -0
- package/dist/src/repo/client.d.ts.map +1 -0
- package/dist/src/repo/client.js +82 -0
- package/dist/src/repo/client.js.map +1 -0
- package/dist/src/repo/cluster-coordinator.d.ts +59 -0
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -0
- package/dist/src/repo/cluster-coordinator.js +539 -0
- package/dist/src/repo/cluster-coordinator.js.map +1 -0
- package/dist/src/repo/coordinator-repo.d.ts +29 -0
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -0
- package/dist/src/repo/coordinator-repo.js +102 -0
- package/dist/src/repo/coordinator-repo.js.map +1 -0
- package/dist/src/repo/redirect.d.ts +14 -0
- package/dist/src/repo/redirect.d.ts.map +1 -0
- package/dist/src/repo/redirect.js +9 -0
- package/dist/src/repo/redirect.js.map +1 -0
- package/dist/src/repo/service.d.ts +52 -0
- package/dist/src/repo/service.d.ts.map +1 -0
- package/dist/src/repo/service.js +181 -0
- package/dist/src/repo/service.js.map +1 -0
- package/dist/src/repo/types.d.ts +7 -0
- package/dist/src/repo/types.d.ts.map +1 -0
- package/dist/src/repo/types.js +2 -0
- package/dist/src/repo/types.js.map +1 -0
- package/dist/src/routing/libp2p-known-peers.d.ts +4 -0
- package/dist/src/routing/libp2p-known-peers.d.ts.map +1 -0
- package/dist/src/routing/libp2p-known-peers.js +19 -0
- package/dist/src/routing/libp2p-known-peers.js.map +1 -0
- package/dist/src/routing/responsibility.d.ts +14 -0
- package/dist/src/routing/responsibility.d.ts.map +1 -0
- package/dist/src/routing/responsibility.js +45 -0
- package/dist/src/routing/responsibility.js.map +1 -0
- package/dist/src/routing/simple-cluster-coordinator.d.ts +23 -0
- package/dist/src/routing/simple-cluster-coordinator.d.ts.map +1 -0
- package/dist/src/routing/simple-cluster-coordinator.js +59 -0
- package/dist/src/routing/simple-cluster-coordinator.js.map +1 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts +65 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -0
- package/dist/src/storage/arachnode-fret-adapter.js +93 -0
- package/dist/src/storage/arachnode-fret-adapter.js.map +1 -0
- package/dist/src/storage/block-storage.d.ts +31 -0
- package/dist/src/storage/block-storage.d.ts.map +1 -0
- package/dist/src/storage/block-storage.js +154 -0
- package/dist/src/storage/block-storage.js.map +1 -0
- package/dist/src/storage/file-storage.d.ts +30 -0
- package/dist/src/storage/file-storage.d.ts.map +1 -0
- package/dist/src/storage/file-storage.js +127 -0
- package/dist/src/storage/file-storage.js.map +1 -0
- package/dist/src/storage/helpers.d.ts +3 -0
- package/dist/src/storage/helpers.d.ts.map +1 -0
- package/dist/src/storage/helpers.js +28 -0
- package/dist/src/storage/helpers.js.map +1 -0
- package/dist/src/storage/i-block-storage.d.ts +32 -0
- package/dist/src/storage/i-block-storage.d.ts.map +1 -0
- package/dist/src/storage/i-block-storage.js +2 -0
- package/dist/src/storage/i-block-storage.js.map +1 -0
- package/dist/src/storage/i-raw-storage.d.ts +20 -0
- package/dist/src/storage/i-raw-storage.d.ts.map +1 -0
- package/dist/src/storage/i-raw-storage.js +2 -0
- package/dist/src/storage/i-raw-storage.js.map +1 -0
- package/dist/src/storage/memory-storage.d.ts +27 -0
- package/dist/src/storage/memory-storage.d.ts.map +1 -0
- package/dist/src/storage/memory-storage.js +87 -0
- package/dist/src/storage/memory-storage.js.map +1 -0
- package/dist/src/storage/restoration-coordinator-v2.d.ts +63 -0
- package/dist/src/storage/restoration-coordinator-v2.d.ts.map +1 -0
- package/dist/src/storage/restoration-coordinator-v2.js +157 -0
- package/dist/src/storage/restoration-coordinator-v2.js.map +1 -0
- package/dist/src/storage/ring-selector.d.ts +56 -0
- package/dist/src/storage/ring-selector.d.ts.map +1 -0
- package/dist/src/storage/ring-selector.js +118 -0
- package/dist/src/storage/ring-selector.js.map +1 -0
- package/dist/src/storage/storage-monitor.d.ts +23 -0
- package/dist/src/storage/storage-monitor.d.ts.map +1 -0
- package/dist/src/storage/storage-monitor.js +40 -0
- package/dist/src/storage/storage-monitor.js.map +1 -0
- package/dist/src/storage/storage-repo.d.ts +17 -0
- package/dist/src/storage/storage-repo.d.ts.map +1 -0
- package/dist/src/storage/storage-repo.js +267 -0
- package/dist/src/storage/storage-repo.js.map +1 -0
- package/dist/src/storage/struct.d.ts +29 -0
- package/dist/src/storage/struct.d.ts.map +1 -0
- package/dist/src/storage/struct.js +2 -0
- package/dist/src/storage/struct.js.map +1 -0
- package/dist/src/sync/client.d.ts +27 -0
- package/dist/src/sync/client.d.ts.map +1 -0
- package/dist/src/sync/client.js +32 -0
- package/dist/src/sync/client.js.map +1 -0
- package/dist/src/sync/protocol.d.ts +58 -0
- package/dist/src/sync/protocol.d.ts.map +1 -0
- package/dist/src/sync/protocol.js +12 -0
- package/dist/src/sync/protocol.js.map +1 -0
- package/dist/src/sync/service.d.ts +62 -0
- package/dist/src/sync/service.d.ts.map +1 -0
- package/dist/src/sync/service.js +168 -0
- package/dist/src/sync/service.js.map +1 -0
- package/package.json +73 -0
- package/readme.md +497 -0
- package/src/cluster/client.ts +63 -0
- package/src/cluster/cluster-repo.ts +711 -0
- package/src/cluster/partition-detector.ts +158 -0
- package/src/cluster/service.ts +156 -0
- package/src/index.ts +30 -0
- package/src/it-utility.ts +36 -0
- package/src/libp2p-key-network.ts +334 -0
- package/src/libp2p-node.ts +335 -0
- package/src/logger.ts +9 -0
- package/src/network/get-network-manager.ts +17 -0
- package/src/network/network-manager-service.ts +334 -0
- package/src/peer-utils.ts +24 -0
- package/src/protocol-client.ts +54 -0
- package/src/repo/client.ts +112 -0
- package/src/repo/cluster-coordinator.ts +592 -0
- package/src/repo/coordinator-repo.ts +137 -0
- package/src/repo/redirect.ts +17 -0
- package/src/repo/service.ts +219 -0
- package/src/repo/types.ts +7 -0
- package/src/routing/libp2p-known-peers.ts +26 -0
- package/src/routing/responsibility.ts +63 -0
- package/src/routing/simple-cluster-coordinator.ts +70 -0
- package/src/storage/arachnode-fret-adapter.ts +128 -0
- package/src/storage/block-storage.ts +182 -0
- package/src/storage/file-storage.ts +163 -0
- package/src/storage/helpers.ts +29 -0
- package/src/storage/i-block-storage.ts +40 -0
- package/src/storage/i-raw-storage.ts +30 -0
- package/src/storage/memory-storage.ts +108 -0
- package/src/storage/restoration-coordinator-v2.ts +191 -0
- package/src/storage/ring-selector.ts +155 -0
- package/src/storage/storage-monitor.ts +59 -0
- package/src/storage/storage-repo.ts +320 -0
- package/src/storage/struct.ts +34 -0
- package/src/sync/client.ts +42 -0
- package/src/sync/protocol.ts +71 -0
- package/src/sync/service.ts +229 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IRawStorage } from './i-raw-storage.js';
|
|
2
|
+
export interface StorageCapacity {
|
|
3
|
+
total: number;
|
|
4
|
+
used: number;
|
|
5
|
+
available: number;
|
|
6
|
+
}
|
|
7
|
+
export interface StorageMonitorConfig {
|
|
8
|
+
totalBytes?: number;
|
|
9
|
+
usedBytes?: number;
|
|
10
|
+
availableBytes?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Monitors storage capacity for ring selection.
|
|
14
|
+
* Provides estimates based on storage backend or supplied overrides.
|
|
15
|
+
*/
|
|
16
|
+
export declare class StorageMonitor {
|
|
17
|
+
private readonly storage;
|
|
18
|
+
private readonly config;
|
|
19
|
+
constructor(storage: IRawStorage, config?: StorageMonitorConfig);
|
|
20
|
+
getCapacity(): Promise<StorageCapacity>;
|
|
21
|
+
private estimateUsedSpace;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=storage-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-monitor.d.ts","sourceRoot":"","sources":["../../../src/storage/storage-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,cAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,WAAW,EACpB,MAAM,GAAE,oBAAyB;IAG7C,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;YA8B/B,iBAAiB;CAG/B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monitors storage capacity for ring selection.
|
|
3
|
+
* Provides estimates based on storage backend or supplied overrides.
|
|
4
|
+
*/
|
|
5
|
+
export class StorageMonitor {
|
|
6
|
+
storage;
|
|
7
|
+
config;
|
|
8
|
+
constructor(storage, config = {}) {
|
|
9
|
+
this.storage = storage;
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
async getCapacity() {
|
|
13
|
+
const defaultTotal = 10 * 1024 * 1024 * 1024; // 10GB default
|
|
14
|
+
const total = this.config.totalBytes ?? defaultTotal;
|
|
15
|
+
const usedOverride = this.config.usedBytes;
|
|
16
|
+
const availableOverride = this.config.availableBytes;
|
|
17
|
+
if (usedOverride !== undefined ||
|
|
18
|
+
availableOverride !== undefined ||
|
|
19
|
+
this.config.totalBytes !== undefined) {
|
|
20
|
+
const used = usedOverride ?? Math.max(0, total - (availableOverride ?? total));
|
|
21
|
+
const available = availableOverride ?? Math.max(0, total - used);
|
|
22
|
+
return {
|
|
23
|
+
total,
|
|
24
|
+
used: Math.min(total, Math.max(0, used)),
|
|
25
|
+
available: Math.max(0, Math.min(total, available))
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const used = await this.estimateUsedSpace();
|
|
29
|
+
const available = Math.max(0, total - used);
|
|
30
|
+
return {
|
|
31
|
+
total,
|
|
32
|
+
used,
|
|
33
|
+
available
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async estimateUsedSpace() {
|
|
37
|
+
return 0; // TODO: Implement actual space calculation
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=storage-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-monitor.js","sourceRoot":"","sources":["../../../src/storage/storage-monitor.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,OAAO,cAAc;IAER;IACA;IAFlB,YACkB,OAAoB,EACpB,SAA+B,EAAE;QADjC,YAAO,GAAP,OAAO,CAAa;QACpB,WAAM,GAAN,MAAM,CAA2B;IAChD,CAAC;IAEJ,KAAK,CAAC,WAAW;QAChB,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,eAAe;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,YAAY,CAAC;QACrD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC3C,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QAErD,IACC,YAAY,KAAK,SAAS;YAC1B,iBAAiB,KAAK,SAAS;YAC/B,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,EACnC,CAAC;YACF,MAAM,IAAI,GAAG,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,iBAAiB,IAAI,KAAK,CAAC,CAAC,CAAC;YAC/E,MAAM,SAAS,GAAG,iBAAiB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;YACjE,OAAO;gBACN,KAAK;gBACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACxC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;aAClD,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;QAE5C,OAAO;YACN,KAAK;YACL,IAAI;YACJ,SAAS;SACT,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC9B,OAAO,CAAC,CAAC,CAAC,2CAA2C;IACtD,CAAC;CACD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IRepo, MessageOptions, BlockId, CommitRequest, CommitResult, GetBlockResults, PendRequest, PendResult, ActionBlocks, BlockGets, PendValidationHook } from "@optimystic/db-core";
|
|
2
|
+
import type { IBlockStorage } from "./i-block-storage.js";
|
|
3
|
+
export type StorageRepoOptions = {
|
|
4
|
+
/** Optional hook to validate transactions in PendRequests */
|
|
5
|
+
validatePend?: PendValidationHook;
|
|
6
|
+
};
|
|
7
|
+
export declare class StorageRepo implements IRepo {
|
|
8
|
+
private readonly createBlockStorage;
|
|
9
|
+
private readonly validatePend?;
|
|
10
|
+
constructor(createBlockStorage: (blockId: BlockId) => IBlockStorage, options?: StorageRepoOptions);
|
|
11
|
+
get({ blockIds, context }: BlockGets, options?: MessageOptions): Promise<GetBlockResults>;
|
|
12
|
+
pend(request: PendRequest, _options?: MessageOptions): Promise<PendResult>;
|
|
13
|
+
cancel(actionRef: ActionBlocks, _options?: MessageOptions): Promise<void>;
|
|
14
|
+
commit(request: CommitRequest, options?: MessageOptions): Promise<CommitResult>;
|
|
15
|
+
private internalCommit;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=storage-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-repo.d.ts","sourceRoot":"","sources":["../../../src/storage/storage-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EACzG,SAAS,EAGnB,kBAAkB,EAClB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAChC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAEF,qBAAa,WAAY,YAAW,KAAK;IAIvC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAHpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAqB;gBAGjC,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,aAAa,EACxE,OAAO,CAAC,EAAE,kBAAkB;IAKvB,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAoDzF,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA+F1E,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzE,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;YAmFvE,cAAc;CAmC5B"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { Latches, transformForBlockId, applyTransform, groupBy, concatTransform, emptyTransforms, blockIdsForTransforms, transformsFromTransform } from "@optimystic/db-core";
|
|
2
|
+
import { asyncIteratorToArray } from "../it-utility.js";
|
|
3
|
+
export class StorageRepo {
|
|
4
|
+
createBlockStorage;
|
|
5
|
+
validatePend;
|
|
6
|
+
constructor(createBlockStorage, options) {
|
|
7
|
+
this.createBlockStorage = createBlockStorage;
|
|
8
|
+
this.validatePend = options?.validatePend;
|
|
9
|
+
}
|
|
10
|
+
async get({ blockIds, context }, options) {
|
|
11
|
+
const distinctBlockIds = Array.from(new Set(blockIds));
|
|
12
|
+
const results = await Promise.all(distinctBlockIds.map(async (blockId) => {
|
|
13
|
+
const blockStorage = this.createBlockStorage(blockId);
|
|
14
|
+
// Ensure that all outstanding transactions in the context are committed
|
|
15
|
+
if (context) {
|
|
16
|
+
const latest = await blockStorage.getLatest();
|
|
17
|
+
const missing = latest
|
|
18
|
+
? context.committed.filter(c => c.rev > latest.rev)
|
|
19
|
+
: context.committed;
|
|
20
|
+
for (const { actionId, rev } of missing.sort((a, b) => a.rev - b.rev)) {
|
|
21
|
+
const pending = await blockStorage.getPendingTransaction(actionId);
|
|
22
|
+
if (pending) {
|
|
23
|
+
await this.internalCommit(blockId, actionId, rev, blockStorage);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const blockRev = await blockStorage.getBlock(context?.rev);
|
|
28
|
+
if (!blockRev) {
|
|
29
|
+
return [blockId, { state: {} }];
|
|
30
|
+
}
|
|
31
|
+
// Include pending action if requested
|
|
32
|
+
if (context?.actionId !== undefined) {
|
|
33
|
+
const pendingTransform = await blockStorage.getPendingTransaction(context.actionId);
|
|
34
|
+
if (!pendingTransform) {
|
|
35
|
+
throw new Error(`Pending action ${context.actionId} not found`);
|
|
36
|
+
}
|
|
37
|
+
const block = applyTransform(blockRev.block, pendingTransform);
|
|
38
|
+
return [blockId, {
|
|
39
|
+
block,
|
|
40
|
+
state: {
|
|
41
|
+
latest: await blockStorage.getLatest(),
|
|
42
|
+
pendings: [context.actionId]
|
|
43
|
+
}
|
|
44
|
+
}];
|
|
45
|
+
}
|
|
46
|
+
const pendings = await asyncIteratorToArray(blockStorage.listPendingTransactions());
|
|
47
|
+
return [blockId, {
|
|
48
|
+
block: blockRev.block,
|
|
49
|
+
state: {
|
|
50
|
+
latest: await blockStorage.getLatest(),
|
|
51
|
+
pendings
|
|
52
|
+
}
|
|
53
|
+
}];
|
|
54
|
+
}));
|
|
55
|
+
return Object.fromEntries(results);
|
|
56
|
+
}
|
|
57
|
+
async pend(request, _options) {
|
|
58
|
+
// Validate transaction if present and validation hook is configured
|
|
59
|
+
if (this.validatePend && request.transaction && request.operationsHash) {
|
|
60
|
+
const validationResult = await this.validatePend(request.transaction, request.operationsHash);
|
|
61
|
+
if (!validationResult.valid) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
reason: validationResult.reason ?? 'Transaction validation failed'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const blockIds = blockIdsForTransforms(request.transforms);
|
|
69
|
+
const pendings = [];
|
|
70
|
+
const missing = [];
|
|
71
|
+
// Potential race condition: A concurrent commit operation could complete
|
|
72
|
+
// between the conflict checks (latest.rev, listPendingTransactions) and the
|
|
73
|
+
// savePendingTransaction call below. This pend operation might succeed based on
|
|
74
|
+
// stale information, but the subsequent commit for this pend would likely
|
|
75
|
+
// fail correctly later if a conflict arose. Locking here could make the initial
|
|
76
|
+
// check more accurate but adds overhead. The current approach prioritizes
|
|
77
|
+
// letting the commit be the final arbiter.
|
|
78
|
+
for (const blockId of blockIds) {
|
|
79
|
+
const blockStorage = this.createBlockStorage(blockId);
|
|
80
|
+
const transforms = transformForBlockId(request.transforms, blockId);
|
|
81
|
+
// First handle any pending actions
|
|
82
|
+
const pending = await asyncIteratorToArray(blockStorage.listPendingTransactions());
|
|
83
|
+
pendings.push(...pending.map(actionId => ({ blockId, actionId })));
|
|
84
|
+
// Handle any conflicting revisions
|
|
85
|
+
if (request.rev !== undefined || transforms.insert) {
|
|
86
|
+
const latest = await blockStorage.getLatest();
|
|
87
|
+
if (latest && latest.rev >= (request.rev ?? 0)) {
|
|
88
|
+
const transforms = await asyncIteratorToArray(blockStorage.listRevisions(request.rev ?? 0, latest.rev));
|
|
89
|
+
for (const actionRev of transforms) {
|
|
90
|
+
const transform = await blockStorage.getTransaction(actionRev.actionId);
|
|
91
|
+
if (!transform) {
|
|
92
|
+
throw new Error(`Missing action ${actionRev.actionId} for block ${blockId}`);
|
|
93
|
+
}
|
|
94
|
+
missing.push({
|
|
95
|
+
actionId: actionRev.actionId,
|
|
96
|
+
rev: actionRev.rev,
|
|
97
|
+
transforms: transformsFromTransform(transform, blockId)
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (missing.length) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
missing
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (pendings.length > 0) {
|
|
110
|
+
if (request.policy === 'f') { // Fail on pending actions
|
|
111
|
+
return { success: false, pending: pendings };
|
|
112
|
+
}
|
|
113
|
+
else if (request.policy === 'r') { // Return populated pending actions
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
pending: await Promise.all(pendings.map(async (action) => {
|
|
117
|
+
const blockStorage = this.createBlockStorage(action.blockId);
|
|
118
|
+
return {
|
|
119
|
+
blockId: action.blockId,
|
|
120
|
+
actionId: action.actionId,
|
|
121
|
+
transform: (await blockStorage.getPendingTransaction(action.actionId))
|
|
122
|
+
?? (await blockStorage.getTransaction(action.actionId)) // Possible that since enumeration, the action has been promoted
|
|
123
|
+
};
|
|
124
|
+
}))
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Simultaneously save pending action for each block
|
|
129
|
+
// Note: that this is not atomic, after we checked for conflicts and pending actions
|
|
130
|
+
// new pending or committed actions may have been added. This is okay, because
|
|
131
|
+
// this check during pend is conservative.
|
|
132
|
+
await Promise.all(blockIds.map(blockId => {
|
|
133
|
+
const blockStorage = this.createBlockStorage(blockId);
|
|
134
|
+
const blockTransform = transformForBlockId(request.transforms, blockId);
|
|
135
|
+
return blockStorage.savePendingTransaction(request.actionId, blockTransform);
|
|
136
|
+
}));
|
|
137
|
+
return {
|
|
138
|
+
success: true,
|
|
139
|
+
pending: pendings,
|
|
140
|
+
blockIds
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async cancel(actionRef, _options) {
|
|
144
|
+
await Promise.all(actionRef.blockIds.map(blockId => {
|
|
145
|
+
const blockStorage = this.createBlockStorage(blockId);
|
|
146
|
+
return blockStorage.deletePendingTransaction(actionRef.actionId);
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
async commit(request, options) {
|
|
150
|
+
const uniqueBlockIds = Array.from(new Set(request.blockIds)).sort();
|
|
151
|
+
const releases = [];
|
|
152
|
+
try {
|
|
153
|
+
// Acquire locks sequentially based on sorted IDs to prevent deadlocks
|
|
154
|
+
for (const id of uniqueBlockIds) {
|
|
155
|
+
const lockId = `StorageRepo.commit:${id}`;
|
|
156
|
+
const release = await Latches.acquire(lockId);
|
|
157
|
+
releases.push(release);
|
|
158
|
+
}
|
|
159
|
+
// --- Start of Critical Section ---
|
|
160
|
+
const blockStorages = request.blockIds.map(blockId => ({
|
|
161
|
+
blockId,
|
|
162
|
+
storage: this.createBlockStorage(blockId)
|
|
163
|
+
}));
|
|
164
|
+
// Check for stale revisions and collect missing actions
|
|
165
|
+
const missedCommits = [];
|
|
166
|
+
for (const { blockId, storage } of blockStorages) {
|
|
167
|
+
const latest = await storage.getLatest();
|
|
168
|
+
if (latest && latest.rev >= request.rev) {
|
|
169
|
+
const transforms = [];
|
|
170
|
+
for await (const actionRev of storage.listRevisions(request.rev, latest.rev)) {
|
|
171
|
+
const transform = await storage.getTransaction(actionRev.actionId);
|
|
172
|
+
if (!transform) {
|
|
173
|
+
throw new Error(`Missing action ${actionRev.actionId} for block ${blockId}`);
|
|
174
|
+
}
|
|
175
|
+
transforms.push({
|
|
176
|
+
actionId: actionRev.actionId,
|
|
177
|
+
rev: actionRev.rev,
|
|
178
|
+
transform
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
missedCommits.push({ blockId, transforms }); // Push, even if transforms is empty, because we want to reject the older version
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (missedCommits.length) {
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
missing: perBlockActionTransformsToPerAction(missedCommits)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Check for missing pending actions
|
|
191
|
+
const missingPends = [];
|
|
192
|
+
for (const { blockId, storage } of blockStorages) {
|
|
193
|
+
const pendingAction = await storage.getPendingTransaction(request.actionId);
|
|
194
|
+
if (!pendingAction) {
|
|
195
|
+
missingPends.push({ blockId, actionId: request.actionId });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (missingPends.length) {
|
|
199
|
+
throw new Error(`Pending action ${request.actionId} not found for block(s): ${missingPends.map(p => p.blockId).join(', ')}`);
|
|
200
|
+
}
|
|
201
|
+
// Commit the action for each block
|
|
202
|
+
// This loop will execute atomically for all blocks due to the acquired locks
|
|
203
|
+
for (const { blockId, storage } of blockStorages) {
|
|
204
|
+
try {
|
|
205
|
+
// internalCommit will throw if it encounters an issue
|
|
206
|
+
await this.internalCommit(blockId, request.actionId, request.rev, storage);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
// TODO: Recover as best we can. Rollback or handle partial commit? For now, return failure.
|
|
210
|
+
return {
|
|
211
|
+
success: false,
|
|
212
|
+
reason: err instanceof Error ? err.message : 'Unknown error during commit'
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
// Release locks in reverse order of acquisition
|
|
219
|
+
releases.reverse().forEach(release => release());
|
|
220
|
+
}
|
|
221
|
+
return { success: true };
|
|
222
|
+
}
|
|
223
|
+
async internalCommit(blockId, actionId, rev, storage) {
|
|
224
|
+
// Note: This method is called within the locked critical section of commit()
|
|
225
|
+
// So, operations like getPendingTransaction, getLatest, getBlock, saveMaterializedBlock,
|
|
226
|
+
// saveRevision, promotePendingTransaction, setLatest are protected against
|
|
227
|
+
// concurrent commits for the *same blockId*.
|
|
228
|
+
const transform = await storage.getPendingTransaction(actionId);
|
|
229
|
+
// No need to check if !transform here, as the caller (commit) already verified this.
|
|
230
|
+
// If it's null here, it indicates a logic error or race condition bypassed the lock (unlikely).
|
|
231
|
+
if (!transform) {
|
|
232
|
+
throw new Error(`Consistency Error: Pending action ${actionId} disappeared for block ${blockId} within critical section.`);
|
|
233
|
+
}
|
|
234
|
+
// Get prior materialized block if it exists
|
|
235
|
+
const latest = await storage.getLatest();
|
|
236
|
+
const priorBlock = latest
|
|
237
|
+
? (await storage.getBlock(latest.rev))?.block
|
|
238
|
+
: undefined;
|
|
239
|
+
// Apply transform and save materialized block
|
|
240
|
+
// applyTransform handles undefined priorBlock correctly for inserts
|
|
241
|
+
const newBlock = applyTransform(priorBlock, transform);
|
|
242
|
+
if (newBlock) {
|
|
243
|
+
await storage.saveMaterializedBlock(actionId, newBlock);
|
|
244
|
+
}
|
|
245
|
+
// Save revision and promote action *before* updating latest
|
|
246
|
+
// This ensures that if the process crashes between these steps,
|
|
247
|
+
// the 'latest' pointer doesn't point to a revision that hasn't been fully recorded.
|
|
248
|
+
await storage.saveRevision(rev, actionId);
|
|
249
|
+
await storage.promotePendingTransaction(actionId);
|
|
250
|
+
// Update latest revision *last*
|
|
251
|
+
await storage.setLatest({ actionId, rev });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** Converts list of missing actions per block into a list of missing actions across blocks. */
|
|
255
|
+
function perBlockActionTransformsToPerAction(missing) {
|
|
256
|
+
const missingFlat = missing.flatMap(({ blockId, transforms }) => transforms.map(transform => ({ blockId, transform })));
|
|
257
|
+
const missingByActionId = groupBy(missingFlat, ({ transform }) => transform.actionId);
|
|
258
|
+
return Object.entries(missingByActionId).map(([actionId, items]) => items.reduce((acc, { blockId, transform }) => {
|
|
259
|
+
concatTransform(acc.transforms, blockId, transform.transform);
|
|
260
|
+
return acc;
|
|
261
|
+
}, {
|
|
262
|
+
actionId: actionId,
|
|
263
|
+
rev: items[0].transform.rev, // Assumption: all missing actionIds share the same revision
|
|
264
|
+
transforms: emptyTransforms()
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=storage-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-repo.js","sourceRoot":"","sources":["../../../src/storage/storage-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { BlockId, IBlock, ActionId, ActionRev, ActionTransform, ActionTransforms } from "@optimystic/db-core";
|
|
2
|
+
export type RevisionRange = [
|
|
3
|
+
/** Inclusive start */
|
|
4
|
+
startRev: number,
|
|
5
|
+
/** Exclusive end, or open-ended if undefined */
|
|
6
|
+
endRev?: number
|
|
7
|
+
];
|
|
8
|
+
export type BlockMetadata = {
|
|
9
|
+
ranges: RevisionRange[];
|
|
10
|
+
/** Latest revision - present if the repo is not empty */
|
|
11
|
+
latest?: ActionRev;
|
|
12
|
+
};
|
|
13
|
+
export type ArchiveRevisions = Record<number, {
|
|
14
|
+
action: ActionTransform;
|
|
15
|
+
block?: IBlock;
|
|
16
|
+
}>;
|
|
17
|
+
export type BlockArchive = {
|
|
18
|
+
blockId: BlockId;
|
|
19
|
+
/** Revisions in this archive */
|
|
20
|
+
revisions: ArchiveRevisions;
|
|
21
|
+
/** Explicit range covered by this archive since revisions may be sparse */
|
|
22
|
+
range: RevisionRange;
|
|
23
|
+
/** Pending actions - present if this range is open-ended */
|
|
24
|
+
pending?: Record<ActionId, ActionTransforms>;
|
|
25
|
+
};
|
|
26
|
+
/** Should return a BlockRepo with the given rev (materialized) if given,
|
|
27
|
+
* else (no rev) at least the latest revision and any given pending transactions */
|
|
28
|
+
export type RestoreCallback = (blockId: BlockId, rev?: number) => Promise<BlockArchive | undefined>;
|
|
29
|
+
//# sourceMappingURL=struct.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"struct.d.ts","sourceRoot":"","sources":["../../../src/storage/struct.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEnH,MAAM,MAAM,aAAa,GAAG;IAC3B,sBAAsB;IACtB,QAAQ,EAAE,MAAM;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAE3B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,yDAAyD;IACzD,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3F,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,2EAA2E;IAC3E,KAAK,EAAE,aAAa,CAAC;IACrB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;CAC7C,CAAA;AAED;mFACmF;AACnF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"struct.js","sourceRoot":"","sources":["../../../src/storage/struct.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PeerId } from '@libp2p/interface';
|
|
2
|
+
import type { IPeerNetwork } from '@optimystic/db-core';
|
|
3
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
4
|
+
import { type SyncRequest, type SyncResponse } from './protocol.js';
|
|
5
|
+
/**
|
|
6
|
+
* Client for sending sync requests to remote peers.
|
|
7
|
+
*
|
|
8
|
+
* Used by storage tiers to request missing blocks from other nodes in the network.
|
|
9
|
+
* Extends ProtocolClient for consistent error handling and timeout behavior.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SyncClient extends ProtocolClient {
|
|
12
|
+
private readonly protocol;
|
|
13
|
+
constructor(peerId: PeerId, peerNetwork: IPeerNetwork, protocolPrefix?: string);
|
|
14
|
+
/**
|
|
15
|
+
* Request a block from the remote peer.
|
|
16
|
+
*
|
|
17
|
+
* @param request - Sync request specifying block and options
|
|
18
|
+
* @returns Response with archive if successful
|
|
19
|
+
* @throws Error if request fails or times out
|
|
20
|
+
*/
|
|
21
|
+
requestBlock(request: SyncRequest): Promise<SyncResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* Get the protocol string used by this client.
|
|
24
|
+
*/
|
|
25
|
+
getProtocol(): string;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/sync/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEvF;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,cAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,YAAY,EACzB,cAAc,GAAE,MAAW;IAM5B;;;;;;OAMG;IACG,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAI/D;;OAEG;IACH,WAAW,IAAI,MAAM;CAGrB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
2
|
+
import { buildSyncProtocol } from './protocol.js';
|
|
3
|
+
/**
|
|
4
|
+
* Client for sending sync requests to remote peers.
|
|
5
|
+
*
|
|
6
|
+
* Used by storage tiers to request missing blocks from other nodes in the network.
|
|
7
|
+
* Extends ProtocolClient for consistent error handling and timeout behavior.
|
|
8
|
+
*/
|
|
9
|
+
export class SyncClient extends ProtocolClient {
|
|
10
|
+
protocol;
|
|
11
|
+
constructor(peerId, peerNetwork, protocolPrefix = '') {
|
|
12
|
+
super(peerId, peerNetwork);
|
|
13
|
+
this.protocol = buildSyncProtocol(protocolPrefix);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Request a block from the remote peer.
|
|
17
|
+
*
|
|
18
|
+
* @param request - Sync request specifying block and options
|
|
19
|
+
* @returns Response with archive if successful
|
|
20
|
+
* @throws Error if request fails or times out
|
|
21
|
+
*/
|
|
22
|
+
async requestBlock(request) {
|
|
23
|
+
return await this.processMessage(request, this.protocol);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get the protocol string used by this client.
|
|
27
|
+
*/
|
|
28
|
+
getProtocol() {
|
|
29
|
+
return this.protocol;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/sync/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAuC,MAAM,eAAe,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,OAAO,UAAW,SAAQ,cAAc;IAC5B,QAAQ,CAAS;IAElC,YACC,MAAc,EACd,WAAyB,EACzB,iBAAyB,EAAE;QAE3B,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,iBAAiB,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,OAAoB;QACtC,OAAO,MAAM,IAAI,CAAC,cAAc,CAAe,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACH,WAAW;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;CACD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { BlockId } from '@optimystic/db-core';
|
|
2
|
+
import type { BlockArchive } from '../storage/struct.js';
|
|
3
|
+
/**
|
|
4
|
+
* Request to sync a specific block or revision from a peer.
|
|
5
|
+
*
|
|
6
|
+
* This protocol is used for block restoration across storage tiers,
|
|
7
|
+
* allowing nodes to request missing blocks from cluster peers or storage rings.
|
|
8
|
+
*/
|
|
9
|
+
export interface SyncRequest {
|
|
10
|
+
/** Block ID to retrieve */
|
|
11
|
+
blockId: BlockId;
|
|
12
|
+
/**
|
|
13
|
+
* Optional specific revision to retrieve.
|
|
14
|
+
* If undefined, retrieve the latest available revision.
|
|
15
|
+
*/
|
|
16
|
+
rev?: number;
|
|
17
|
+
/**
|
|
18
|
+
* If true, include pending transactions in the response.
|
|
19
|
+
* Typically true when requesting latest state, false for historical revisions.
|
|
20
|
+
*/
|
|
21
|
+
includePending?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of revisions to return.
|
|
24
|
+
* Prevents excessive response sizes.
|
|
25
|
+
* @default 100
|
|
26
|
+
*/
|
|
27
|
+
maxRevisions?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Optional hint about which tier is requesting (for logging/metrics).
|
|
30
|
+
* Values: 'ring-zulu', 'ring-0', 'ring-N', etc.
|
|
31
|
+
*/
|
|
32
|
+
requestingTier?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Response containing block archive data.
|
|
36
|
+
*/
|
|
37
|
+
export interface SyncResponse {
|
|
38
|
+
/** True if the peer has the requested data */
|
|
39
|
+
success: boolean;
|
|
40
|
+
/** Block archive if found */
|
|
41
|
+
archive?: BlockArchive;
|
|
42
|
+
/** Error message if unsuccessful */
|
|
43
|
+
error?: string;
|
|
44
|
+
/** Peer ID of responder (for tracking/metrics) */
|
|
45
|
+
responderId?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Sync protocol prefix - namespaced under db-p2p */
|
|
48
|
+
export declare const SYNC_PROTOCOL_PREFIX = "/db-p2p/sync/";
|
|
49
|
+
/** Sync protocol version */
|
|
50
|
+
export declare const SYNC_PROTOCOL_VERSION = "1.0.0";
|
|
51
|
+
/**
|
|
52
|
+
* Builds the full protocol string for the sync protocol.
|
|
53
|
+
*
|
|
54
|
+
* @param protocolPrefix - Optional prefix (e.g., '/optimystic/testnet')
|
|
55
|
+
* @returns Full protocol string
|
|
56
|
+
*/
|
|
57
|
+
export declare const buildSyncProtocol: (protocolPrefix?: string) => string;
|
|
58
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/sync/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IAEjB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,4BAA4B;AAC5B,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,iBAAgB,MAAW,KAAG,MACG,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Sync protocol prefix - namespaced under db-p2p */
|
|
2
|
+
export const SYNC_PROTOCOL_PREFIX = '/db-p2p/sync/';
|
|
3
|
+
/** Sync protocol version */
|
|
4
|
+
export const SYNC_PROTOCOL_VERSION = '1.0.0';
|
|
5
|
+
/**
|
|
6
|
+
* Builds the full protocol string for the sync protocol.
|
|
7
|
+
*
|
|
8
|
+
* @param protocolPrefix - Optional prefix (e.g., '/optimystic/testnet')
|
|
9
|
+
* @returns Full protocol string
|
|
10
|
+
*/
|
|
11
|
+
export const buildSyncProtocol = (protocolPrefix = '') => `${protocolPrefix}${SYNC_PROTOCOL_PREFIX}${SYNC_PROTOCOL_VERSION}`;
|
|
12
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/sync/protocol.ts"],"names":[],"mappings":"AAwDA,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,4BAA4B;AAC5B,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,iBAAyB,EAAE,EAAU,EAAE,CACxE,GAAG,cAAc,GAAG,oBAAoB,GAAG,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ComponentLogger, Startable } from '@libp2p/interface';
|
|
2
|
+
import type { IRepo } from '@optimystic/db-core';
|
|
3
|
+
export interface SyncServiceInit {
|
|
4
|
+
protocolPrefix?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SyncServiceComponents {
|
|
7
|
+
logger: ComponentLogger;
|
|
8
|
+
registrar: {
|
|
9
|
+
handle: (...args: any[]) => Promise<void>;
|
|
10
|
+
unhandle: (...args: any[]) => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
repo: IRepo;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Service for handling incoming sync requests from other cluster peers.
|
|
16
|
+
*
|
|
17
|
+
* Listens on the sync protocol and responds to block requests by:
|
|
18
|
+
* 1. Extracting the block from local storage
|
|
19
|
+
* 2. Building a BlockArchive with requested revisions
|
|
20
|
+
* 3. Sending the response back to the requester
|
|
21
|
+
*
|
|
22
|
+
* This is the server-side of the block restoration mechanism.
|
|
23
|
+
*/
|
|
24
|
+
export declare class SyncService implements Startable {
|
|
25
|
+
private readonly components;
|
|
26
|
+
private running;
|
|
27
|
+
private readonly log;
|
|
28
|
+
private readonly protocol;
|
|
29
|
+
private readonly repo;
|
|
30
|
+
private readonly registrar;
|
|
31
|
+
constructor(components: SyncServiceComponents, init?: SyncServiceInit);
|
|
32
|
+
start(): Promise<void>;
|
|
33
|
+
stop(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Handle an incoming sync request stream.
|
|
36
|
+
*/
|
|
37
|
+
private handleSyncRequest;
|
|
38
|
+
/**
|
|
39
|
+
* Read and parse a sync request from the stream.
|
|
40
|
+
*/
|
|
41
|
+
private readRequest;
|
|
42
|
+
/**
|
|
43
|
+
* Send a sync response to the stream.
|
|
44
|
+
*/
|
|
45
|
+
private sendResponse;
|
|
46
|
+
/**
|
|
47
|
+
* Build a block archive from local storage.
|
|
48
|
+
*
|
|
49
|
+
* @param blockId - Block to retrieve
|
|
50
|
+
* @param rev - Optional specific revision
|
|
51
|
+
* @param includePending - Whether to include pending transactions
|
|
52
|
+
* @param maxRevisions - Maximum number of revisions to include
|
|
53
|
+
* @returns BlockArchive if found, undefined otherwise
|
|
54
|
+
*/
|
|
55
|
+
private buildArchive;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Factory function for creating a SyncService.
|
|
59
|
+
* Follows the libp2p service pattern.
|
|
60
|
+
*/
|
|
61
|
+
export declare const syncService: (init?: SyncServiceInit) => (components: SyncServiceComponents) => SyncService;
|
|
62
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/sync/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAU,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAOjD,MAAM,WAAW,eAAe;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACtG,IAAI,EAAE,KAAK,CAAC;CACZ;AAID;;;;;;;;;GASG;AACH,qBAAa,WAAY,YAAW,SAAS;IAQ3C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAP5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6F;gBAGrG,UAAU,EAAE,qBAAqB,EAClD,IAAI,GAAE,eAAoB;IAQrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;OAEG;YACW,iBAAiB;IA4D/B;;OAEG;YACW,WAAW;IAqBzB;;OAEG;YACW,YAAY;IAW1B;;;;;;;;OAQG;YACW,YAAY;CA6C1B;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,OAAM,eAAoB,MACpD,YAAY,qBAAqB,gBAAsC,CAAC"}
|