@superblocksteam/workspace-sync 0.0.0-stage → 2.0.178-next.0
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/LICENSE.txt +87 -0
- package/README.md +43 -2
- package/dist/atomic-write.d.ts +7 -0
- package/dist/atomic-write.d.ts.map +1 -0
- package/dist/atomic-write.js +33 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/branch-write-guard.d.ts +32 -0
- package/dist/branch-write-guard.d.ts.map +1 -0
- package/dist/branch-write-guard.js +38 -0
- package/dist/branch-write-guard.js.map +1 -0
- package/dist/control.d.ts +237 -0
- package/dist/control.d.ts.map +1 -0
- package/dist/control.js +242 -0
- package/dist/control.js.map +1 -0
- package/dist/dbfs-transport.d.ts +52 -0
- package/dist/dbfs-transport.d.ts.map +1 -0
- package/dist/dbfs-transport.js +21 -0
- package/dist/dbfs-transport.js.map +1 -0
- package/dist/download.d.ts +54 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +475 -0
- package/dist/download.js.map +1 -0
- package/dist/draft-helpers.d.ts +114 -0
- package/dist/draft-helpers.d.ts.map +1 -0
- package/dist/draft-helpers.js +760 -0
- package/dist/draft-helpers.js.map +1 -0
- package/dist/draft-journal-store.d.ts +30 -0
- package/dist/draft-journal-store.d.ts.map +1 -0
- package/dist/draft-journal-store.js +7 -0
- package/dist/draft-journal-store.js.map +1 -0
- package/dist/draft-state-report-metrics.d.ts +5 -0
- package/dist/draft-state-report-metrics.d.ts.map +1 -0
- package/dist/draft-state-report-metrics.js +36 -0
- package/dist/draft-state-report-metrics.js.map +1 -0
- package/dist/file-draft-journal-store.d.ts +26 -0
- package/dist/file-draft-journal-store.d.ts.map +1 -0
- package/dist/file-draft-journal-store.js +123 -0
- package/dist/file-draft-journal-store.js.map +1 -0
- package/dist/flush-scheduler.d.ts +24 -0
- package/dist/flush-scheduler.d.ts.map +1 -0
- package/dist/flush-scheduler.js +36 -0
- package/dist/flush-scheduler.js.map +1 -0
- package/dist/hash-cache.d.ts +16 -0
- package/dist/hash-cache.d.ts.map +1 -0
- package/dist/hash-cache.js +62 -0
- package/dist/hash-cache.js.map +1 -0
- package/dist/hash-dir-tree.d.ts +10 -0
- package/dist/hash-dir-tree.d.ts.map +1 -0
- package/dist/hash-dir-tree.js +53 -0
- package/dist/hash-dir-tree.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/list-dir.d.ts +31 -0
- package/dist/list-dir.d.ts.map +1 -0
- package/dist/list-dir.js +153 -0
- package/dist/list-dir.js.map +1 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +16 -0
- package/dist/logger.js.map +1 -0
- package/dist/native-draft-session.d.ts +28 -0
- package/dist/native-draft-session.d.ts.map +1 -0
- package/dist/native-draft-session.js +154 -0
- package/dist/native-draft-session.js.map +1 -0
- package/dist/rpc-client.d.ts +7 -0
- package/dist/rpc-client.d.ts.map +1 -0
- package/dist/rpc-client.js +2 -0
- package/dist/rpc-client.js.map +1 -0
- package/dist/safe-directory-reader.d.ts +28 -0
- package/dist/safe-directory-reader.d.ts.map +1 -0
- package/dist/safe-directory-reader.js +136 -0
- package/dist/safe-directory-reader.js.map +1 -0
- package/dist/server-tree.d.ts +56 -0
- package/dist/server-tree.d.ts.map +1 -0
- package/dist/server-tree.js +179 -0
- package/dist/server-tree.js.map +1 -0
- package/dist/session-draft-journal-store.d.ts +42 -0
- package/dist/session-draft-journal-store.d.ts.map +1 -0
- package/dist/session-draft-journal-store.js +177 -0
- package/dist/session-draft-journal-store.js.map +1 -0
- package/dist/snapshot/take-snapshot.d.ts +41 -0
- package/dist/snapshot/take-snapshot.d.ts.map +1 -0
- package/dist/snapshot/take-snapshot.js +244 -0
- package/dist/snapshot/take-snapshot.js.map +1 -0
- package/dist/snapshot/types.d.ts +25 -0
- package/dist/snapshot/types.d.ts.map +1 -0
- package/dist/snapshot/types.js +3 -0
- package/dist/snapshot/types.js.map +1 -0
- package/dist/snapshot/upload-snapshot.d.ts +33 -0
- package/dist/snapshot/upload-snapshot.d.ts.map +1 -0
- package/dist/snapshot/upload-snapshot.js +113 -0
- package/dist/snapshot/upload-snapshot.js.map +1 -0
- package/dist/socket-dbfs-transport.d.ts +32 -0
- package/dist/socket-dbfs-transport.d.ts.map +1 -0
- package/dist/socket-dbfs-transport.js +126 -0
- package/dist/socket-dbfs-transport.js.map +1 -0
- package/dist/sync-credential-provider.d.ts +27 -0
- package/dist/sync-credential-provider.d.ts.map +1 -0
- package/dist/sync-credential-provider.js +22 -0
- package/dist/sync-credential-provider.js.map +1 -0
- package/dist/sync-engine.d.ts +119 -0
- package/dist/sync-engine.d.ts.map +1 -0
- package/dist/sync-engine.js +358 -0
- package/dist/sync-engine.js.map +1 -0
- package/dist/sync-paths.d.ts +61 -0
- package/dist/sync-paths.d.ts.map +1 -0
- package/dist/sync-paths.js +107 -0
- package/dist/sync-paths.js.map +1 -0
- package/dist/sync-telemetry.d.ts +12 -0
- package/dist/sync-telemetry.d.ts.map +1 -0
- package/dist/sync-telemetry.js +33 -0
- package/dist/sync-telemetry.js.map +1 -0
- package/dist/testing.d.ts +66 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +180 -0
- package/dist/testing.js.map +1 -0
- package/dist/workspace-state-store.d.ts +52 -0
- package/dist/workspace-state-store.d.ts.map +1 -0
- package/dist/workspace-state-store.js +45 -0
- package/dist/workspace-state-store.js.map +1 -0
- package/package.json +59 -3
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The credential the sync engine's transport authenticates DBFS calls with. */
|
|
2
|
+
export interface SyncCredential {
|
|
3
|
+
token: string;
|
|
4
|
+
/** Epoch milliseconds after which the token is no longer accepted. */
|
|
5
|
+
expiresAt?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Supplies the current sync credential. The interim implementation is a narrow
|
|
9
|
+
* server token the edge pushes before expiry; AR-1074 hardens or replaces it.
|
|
10
|
+
*/
|
|
11
|
+
export interface SyncCredentialProvider {
|
|
12
|
+
/** The latest credential, or undefined before the first one arrives. */
|
|
13
|
+
current(): SyncCredential | undefined;
|
|
14
|
+
/** Calls `listener` with each new credential; returns an unsubscribe. */
|
|
15
|
+
onRefresh(listener: (credential: SyncCredential) => void): () => void;
|
|
16
|
+
}
|
|
17
|
+
/** A provider the host feeds, e.g. from the edge's state snapshots. */
|
|
18
|
+
export declare class PushedSyncCredentialProvider implements SyncCredentialProvider {
|
|
19
|
+
private credential;
|
|
20
|
+
private readonly listeners;
|
|
21
|
+
constructor(initial?: SyncCredential);
|
|
22
|
+
current(): SyncCredential | undefined;
|
|
23
|
+
onRefresh(listener: (credential: SyncCredential) => void): () => void;
|
|
24
|
+
/** Replaces the credential and notifies subscribers. */
|
|
25
|
+
push(credential: SyncCredential): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=sync-credential-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-credential-provider.d.ts","sourceRoot":"","sources":["../src/sync-credential-provider.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,OAAO,IAAI,cAAc,GAAG,SAAS,CAAC;IACtC,yEAAyE;IACzE,SAAS,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACvE;AAED,uEAAuE;AACvE,qBAAa,4BAA6B,YAAW,sBAAsB;IACzE,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmD;IAE7E,YAAY,OAAO,CAAC,EAAE,cAAc,EAEnC;IAED,OAAO,IAAI,cAAc,GAAG,SAAS,CAEpC;IAED,SAAS,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAGpE;IAED,wDAAwD;IACxD,IAAI,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAGrC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** A provider the host feeds, e.g. from the edge's state snapshots. */
|
|
2
|
+
export class PushedSyncCredentialProvider {
|
|
3
|
+
credential;
|
|
4
|
+
listeners = new Set();
|
|
5
|
+
constructor(initial) {
|
|
6
|
+
this.credential = initial;
|
|
7
|
+
}
|
|
8
|
+
current() {
|
|
9
|
+
return this.credential;
|
|
10
|
+
}
|
|
11
|
+
onRefresh(listener) {
|
|
12
|
+
this.listeners.add(listener);
|
|
13
|
+
return () => this.listeners.delete(listener);
|
|
14
|
+
}
|
|
15
|
+
/** Replaces the credential and notifies subscribers. */
|
|
16
|
+
push(credential) {
|
|
17
|
+
this.credential = credential;
|
|
18
|
+
for (const listener of this.listeners)
|
|
19
|
+
listener(credential);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=sync-credential-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-credential-provider.js","sourceRoot":"","sources":["../src/sync-credential-provider.ts"],"names":[],"mappings":"AAkBA,uEAAuE;AACvE,MAAM,OAAO,4BAA4B;IAC/B,UAAU,CAA6B;IAC9B,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;IAE7E,YAAY,OAAwB;QAClC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,SAAS,CAAC,QAA8C;QACtD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,wDAAwD;IACxD,IAAI,CAAC,UAA0B;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;CACF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Meter, Tracer } from "@opentelemetry/api";
|
|
2
|
+
import type { ApplicationHashChangeSource } from "@superblocksteam/shared";
|
|
3
|
+
import { type BranchWriteGuard } from "./branch-write-guard.js";
|
|
4
|
+
import type { DbfsTransport } from "./dbfs-transport.js";
|
|
5
|
+
import { HashCache } from "./hash-cache.js";
|
|
6
|
+
import type { NativeDraftJournal } from "./native-draft-session.js";
|
|
7
|
+
import { type DownloadStats } from "./server-tree.js";
|
|
8
|
+
import type { WorkspaceStateStore } from "./workspace-state-store.js";
|
|
9
|
+
/**
|
|
10
|
+
* Where a test can stop the engine to simulate the VM dying. A hook that
|
|
11
|
+
* throws aborts the operation at that point, leaving disk, DBFS and the state
|
|
12
|
+
* store exactly as a kill would.
|
|
13
|
+
*/
|
|
14
|
+
export type FaultPoint =
|
|
15
|
+
/** A write landed in the tree; nothing has been flushed or committed. */
|
|
16
|
+
"after-write-before-flush"
|
|
17
|
+
/** Blobs are in DBFS; the branch hash has not moved. */
|
|
18
|
+
| "after-put-before-set"
|
|
19
|
+
/** The branch hash moved; the state store still holds the old hash. */
|
|
20
|
+
| "after-set-before-state";
|
|
21
|
+
export type FaultPoints = Partial<Record<FaultPoint, () => void | Promise<void>>>;
|
|
22
|
+
export interface WorkspaceSyncEngineOptions {
|
|
23
|
+
/** The application tree. */
|
|
24
|
+
root: string;
|
|
25
|
+
transport: DbfsTransport;
|
|
26
|
+
state: WorkspaceStateStore;
|
|
27
|
+
/** The native draft journal, when the host runs native sessions. */
|
|
28
|
+
journal?: NativeDraftJournal;
|
|
29
|
+
guard: BranchWriteGuard;
|
|
30
|
+
tracer?: Tracer;
|
|
31
|
+
meter?: Meter;
|
|
32
|
+
faults?: FaultPoints;
|
|
33
|
+
/** Seeded on rehydrate; a host may share one with other uploaders. */
|
|
34
|
+
hashCache?: HashCache;
|
|
35
|
+
/** Whether the tree holds unaccepted drafts. Defaults to its swap files. */
|
|
36
|
+
hasDraft?: () => Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
export interface CommitOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Finalize the draft journal before the snapshot (the turn ended). Pass
|
|
41
|
+
* false for a read-your-writes commit while a native session is still
|
|
42
|
+
* running; the journal then stays open. Defaults to true.
|
|
43
|
+
*/
|
|
44
|
+
finalizeJournal?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface CommitResult {
|
|
47
|
+
dbfsHash: string;
|
|
48
|
+
commitId?: string;
|
|
49
|
+
/** False when the tree already matched the stored hash. */
|
|
50
|
+
moved: boolean;
|
|
51
|
+
/** Paths the journal reconcile found changed, when a journal is active. */
|
|
52
|
+
journalChangedPaths?: string[];
|
|
53
|
+
}
|
|
54
|
+
export interface FlushResult {
|
|
55
|
+
/** Hash of the tree whose blobs were uploaded. */
|
|
56
|
+
hash: string;
|
|
57
|
+
/** putMany items sent; zero when DBFS already had everything. */
|
|
58
|
+
uploadedItems: number;
|
|
59
|
+
}
|
|
60
|
+
export type RehydrateKind = "fresh" | "resumed" | "replayed" | "reloaded";
|
|
61
|
+
export interface RehydrateOutcome {
|
|
62
|
+
outcome: RehydrateKind;
|
|
63
|
+
/** The hash the state store holds afterwards. */
|
|
64
|
+
dbfsHash: string;
|
|
65
|
+
/** True when the local tree was replaced from DBFS. */
|
|
66
|
+
filesChanged: boolean;
|
|
67
|
+
/** `reloaded`: where the local diff that lost to the server was kept. */
|
|
68
|
+
orphanedPath?: string;
|
|
69
|
+
/**
|
|
70
|
+
* `replayed`: false when the guard refused the replay commit (typically the
|
|
71
|
+
* lock is not held yet at boot). The workspace stays unsynced and the next
|
|
72
|
+
* `commit` replays it.
|
|
73
|
+
*/
|
|
74
|
+
replayCommitted?: boolean;
|
|
75
|
+
/** Set when a running journal (a killed native session) was reconciled. */
|
|
76
|
+
interruptedJournal?: {
|
|
77
|
+
changedPaths: string[];
|
|
78
|
+
};
|
|
79
|
+
/** The files written from DBFS and their bytes; zero when none were. */
|
|
80
|
+
downloaded: DownloadStats;
|
|
81
|
+
}
|
|
82
|
+
export interface RehydrateOptions {
|
|
83
|
+
/** Hash-change source for the replay commit. */
|
|
84
|
+
replaySource?: ApplicationHashChangeSource;
|
|
85
|
+
}
|
|
86
|
+
export interface WorkspaceSyncEvents {
|
|
87
|
+
committed: {
|
|
88
|
+
dbfsHash: string;
|
|
89
|
+
commitId?: string;
|
|
90
|
+
};
|
|
91
|
+
"unsynced-changed": {
|
|
92
|
+
unsynced: boolean;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export interface WorkspaceSyncEngine {
|
|
96
|
+
/** Reconciles the local tree, the stored hash and the server on boot. */
|
|
97
|
+
rehydrate(options?: RehydrateOptions): Promise<RehydrateOutcome>;
|
|
98
|
+
/** Uploads blobs for the current tree. Never moves the branch hash. */
|
|
99
|
+
interimFlush(): Promise<FlushResult>;
|
|
100
|
+
/** The turn-end commit. */
|
|
101
|
+
commit(source: ApplicationHashChangeSource, options?: CommitOptions): Promise<CommitResult>;
|
|
102
|
+
/** True while the tree has changes the branch hash does not include. */
|
|
103
|
+
readonly unsynced: boolean;
|
|
104
|
+
/** The hash last committed or loaded, once known. */
|
|
105
|
+
readonly dbfsHash: string | undefined;
|
|
106
|
+
/** Cheap write notification for file watchers; no hashing. */
|
|
107
|
+
markDirty(): void;
|
|
108
|
+
readonly hashCache: HashCache;
|
|
109
|
+
on<E extends keyof WorkspaceSyncEvents>(event: E, listener: (payload: WorkspaceSyncEvents[E]) => void): () => void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates the sync engine for one workspace. DBFS is the commit point: the
|
|
113
|
+
* engine moves the branch hash only in {@link WorkspaceSyncEngine.commit} (and
|
|
114
|
+
* the rehydrate replay), and the state store is a cache of the last hash it
|
|
115
|
+
* committed or loaded. Every operation is serialized, and each step is
|
|
116
|
+
* ordered so a kill at any point is recovered by `rehydrate`.
|
|
117
|
+
*/
|
|
118
|
+
export declare function createWorkspaceSyncEngine(options: WorkspaceSyncEngineOptions): WorkspaceSyncEngine;
|
|
119
|
+
//# sourceMappingURL=sync-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../src/sync-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as fsp from "node:fs/promises";
|
|
2
|
+
import { BranchWriteRejectedError, } from "./branch-write-guard.js";
|
|
3
|
+
import { hasSwapFiles } from "./draft-helpers.js";
|
|
4
|
+
import { HashCache } from "./hash-cache.js";
|
|
5
|
+
import { hashLocalDirectory } from "./hash-dir-tree.js";
|
|
6
|
+
import { downloadServerTree, flattenTree, readServerTree, } from "./server-tree.js";
|
|
7
|
+
import { snapshotLocalDirectory, snapshotLocalDirectoryWithDrafts, } from "./snapshot/take-snapshot.js";
|
|
8
|
+
import { collectSnapshotUploadItems, uploadSnapshotItems, } from "./snapshot/upload-snapshot.js";
|
|
9
|
+
import { createSyncTelemetry, inSpan, } from "./sync-telemetry.js";
|
|
10
|
+
const BLOB_BATCH = 64;
|
|
11
|
+
const NOTHING_DOWNLOADED = { files: 0, bytes: 0 };
|
|
12
|
+
/**
|
|
13
|
+
* Creates the sync engine for one workspace. DBFS is the commit point: the
|
|
14
|
+
* engine moves the branch hash only in {@link WorkspaceSyncEngine.commit} (and
|
|
15
|
+
* the rehydrate replay), and the state store is a cache of the last hash it
|
|
16
|
+
* committed or loaded. Every operation is serialized, and each step is
|
|
17
|
+
* ordered so a kill at any point is recovered by `rehydrate`.
|
|
18
|
+
*/
|
|
19
|
+
export function createWorkspaceSyncEngine(options) {
|
|
20
|
+
return new SyncEngine(options);
|
|
21
|
+
}
|
|
22
|
+
class SyncEngine {
|
|
23
|
+
options;
|
|
24
|
+
hashCache;
|
|
25
|
+
telemetry;
|
|
26
|
+
listeners = new Map();
|
|
27
|
+
queue = Promise.resolve();
|
|
28
|
+
committedHash;
|
|
29
|
+
localHash;
|
|
30
|
+
writes = 0;
|
|
31
|
+
committedWrites = 0;
|
|
32
|
+
lastUnsynced = false;
|
|
33
|
+
reportedDraft;
|
|
34
|
+
constructor(options) {
|
|
35
|
+
this.options = options;
|
|
36
|
+
this.hashCache = options.hashCache ?? new HashCache();
|
|
37
|
+
this.telemetry = createSyncTelemetry(options.tracer, options.meter);
|
|
38
|
+
this.telemetry.unsynced.record(0);
|
|
39
|
+
}
|
|
40
|
+
get unsynced() {
|
|
41
|
+
return (this.writes !== this.committedWrites ||
|
|
42
|
+
(this.localHash !== undefined && this.localHash !== this.committedHash));
|
|
43
|
+
}
|
|
44
|
+
get dbfsHash() {
|
|
45
|
+
return this.committedHash;
|
|
46
|
+
}
|
|
47
|
+
markDirty() {
|
|
48
|
+
this.writes++;
|
|
49
|
+
this.updateUnsynced();
|
|
50
|
+
}
|
|
51
|
+
on(event, listener) {
|
|
52
|
+
let set = this.listeners.get(event);
|
|
53
|
+
if (!set)
|
|
54
|
+
this.listeners.set(event, (set = new Set()));
|
|
55
|
+
set.add(listener);
|
|
56
|
+
return () => set.delete(listener);
|
|
57
|
+
}
|
|
58
|
+
interimFlush() {
|
|
59
|
+
return this.serialize(() => inSpan(this.telemetry.tracer, "workspace.flush", async (span) => {
|
|
60
|
+
await this.fault("after-write-before-flush");
|
|
61
|
+
const snapshot = await snapshotLocalDirectoryWithDrafts(this.options.root);
|
|
62
|
+
const uploadedItems = await this.upload(snapshot);
|
|
63
|
+
this.localHash = snapshot.hash;
|
|
64
|
+
this.updateUnsynced();
|
|
65
|
+
span.setAttribute("workspace.sync.uploaded_items", uploadedItems);
|
|
66
|
+
return { hash: snapshot.hash, uploadedItems };
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
commit(source, options = {}) {
|
|
70
|
+
return this.serialize(() => this.commitNow(source, options.finalizeJournal === false ? "keep" : "finalize"));
|
|
71
|
+
}
|
|
72
|
+
rehydrate(options = {}) {
|
|
73
|
+
return this.serialize(() => inSpan(this.telemetry.tracer, "workspace.rehydrate", async (span) => {
|
|
74
|
+
const outcome = await this.rehydrateNow(options);
|
|
75
|
+
span.setAttribute("workspace.sync.outcome", outcome.outcome);
|
|
76
|
+
span.setAttribute("workspace.sync.files_downloaded", outcome.downloaded.files);
|
|
77
|
+
span.setAttribute("workspace.sync.bytes_downloaded", outcome.downloaded.bytes);
|
|
78
|
+
this.telemetry.rehydrateOutcome.add(1, { outcome: outcome.outcome });
|
|
79
|
+
return outcome;
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
async rehydrateNow({ replaySource = "ai:generate:post", }) {
|
|
83
|
+
const { root, transport, state, journal } = this.options;
|
|
84
|
+
const serverHash = await transport.getServerHash();
|
|
85
|
+
const storedHash = (await state.read())?.dbfsHash;
|
|
86
|
+
const local = await this.hashLocalTree();
|
|
87
|
+
const writesAtStart = this.writes;
|
|
88
|
+
let result;
|
|
89
|
+
if (local === undefined) {
|
|
90
|
+
const tree = await readServerTree(transport, serverHash);
|
|
91
|
+
const downloaded = await downloadServerTree({
|
|
92
|
+
transport,
|
|
93
|
+
tree,
|
|
94
|
+
local: undefined,
|
|
95
|
+
root,
|
|
96
|
+
});
|
|
97
|
+
await this.storeLoaded(serverHash, tree);
|
|
98
|
+
result = {
|
|
99
|
+
outcome: "fresh",
|
|
100
|
+
dbfsHash: serverHash,
|
|
101
|
+
filesChanged: true,
|
|
102
|
+
downloaded,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
else if (local.hash === serverHash) {
|
|
106
|
+
this.hashCache.add_directory_recursive(await readServerTree(transport, serverHash));
|
|
107
|
+
if (storedHash !== serverHash)
|
|
108
|
+
await state.write({ dbfsHash: serverHash });
|
|
109
|
+
this.committedHash = serverHash;
|
|
110
|
+
this.localHash = serverHash;
|
|
111
|
+
result = {
|
|
112
|
+
outcome: "resumed",
|
|
113
|
+
dbfsHash: serverHash,
|
|
114
|
+
filesChanged: false,
|
|
115
|
+
downloaded: NOTHING_DOWNLOADED,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
else if (storedHash === serverHash) {
|
|
119
|
+
// The kill landed after a write and before the commit finished: the
|
|
120
|
+
// server never moved past this workspace, so the local tree wins.
|
|
121
|
+
this.hashCache.add_directory_recursive(await readServerTree(transport, serverHash));
|
|
122
|
+
this.committedHash = serverHash;
|
|
123
|
+
this.localHash = local.hash;
|
|
124
|
+
let replayCommitted = true;
|
|
125
|
+
try {
|
|
126
|
+
await this.commitNow(replaySource, "skip");
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (!(error instanceof BranchWriteRejectedError) ||
|
|
130
|
+
error.reason !== "lock_not_held")
|
|
131
|
+
throw error;
|
|
132
|
+
replayCommitted = false;
|
|
133
|
+
}
|
|
134
|
+
result = {
|
|
135
|
+
outcome: "replayed",
|
|
136
|
+
dbfsHash: this.committedHash ?? serverHash,
|
|
137
|
+
filesChanged: false,
|
|
138
|
+
replayCommitted,
|
|
139
|
+
downloaded: NOTHING_DOWNLOADED,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// The server moved (or this workspace never recorded a hash): keep the
|
|
144
|
+
// local difference where an operator or agent can find it, then load
|
|
145
|
+
// the server tree.
|
|
146
|
+
const tree = await readServerTree(transport, serverHash);
|
|
147
|
+
const orphanedPath = await this.keepOrphan(serverHash, storedHash, tree);
|
|
148
|
+
const downloaded = await downloadServerTree({
|
|
149
|
+
transport,
|
|
150
|
+
tree,
|
|
151
|
+
local,
|
|
152
|
+
root,
|
|
153
|
+
});
|
|
154
|
+
await this.storeLoaded(serverHash, tree);
|
|
155
|
+
result = {
|
|
156
|
+
outcome: "reloaded",
|
|
157
|
+
dbfsHash: serverHash,
|
|
158
|
+
filesChanged: true,
|
|
159
|
+
orphanedPath,
|
|
160
|
+
downloaded,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (journal && (await journal.phase()) === "running") {
|
|
164
|
+
const reconciled = await journal.reconcile(false);
|
|
165
|
+
if (reconciled) {
|
|
166
|
+
result.interruptedJournal = { changedPaths: reconciled.changedPaths };
|
|
167
|
+
if (reconciled.changedPaths.length > 0)
|
|
168
|
+
await this.reportDraftState();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (result.outcome !== "replayed" || result.replayCommitted)
|
|
172
|
+
this.committedWrites = writesAtStart;
|
|
173
|
+
this.updateUnsynced();
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
async commitNow(source, journalMode) {
|
|
177
|
+
const { root, transport, state, journal, guard } = this.options;
|
|
178
|
+
const started = performance.now();
|
|
179
|
+
let outcome = "error";
|
|
180
|
+
try {
|
|
181
|
+
return await inSpan(this.telemetry.tracer, "workspace.commit", async (span) => {
|
|
182
|
+
span.setAttribute("workspace.sync.source", source);
|
|
183
|
+
const writesAtStart = this.writes;
|
|
184
|
+
let journalChangedPaths;
|
|
185
|
+
if (journal && journalMode !== "skip") {
|
|
186
|
+
const reconciled = await journal.reconcile(journalMode === "finalize");
|
|
187
|
+
journalChangedPaths = reconciled?.changedPaths;
|
|
188
|
+
}
|
|
189
|
+
await this.fault("after-write-before-flush");
|
|
190
|
+
const snapshot = await snapshotLocalDirectoryWithDrafts(root);
|
|
191
|
+
const hash = snapshot.hash;
|
|
192
|
+
this.localHash = hash;
|
|
193
|
+
const baseHash = (await state.read())?.dbfsHash;
|
|
194
|
+
if (hash === baseHash) {
|
|
195
|
+
this.committedHash = baseHash;
|
|
196
|
+
await journal?.retireUploaded(hash);
|
|
197
|
+
await this.reportDraftState();
|
|
198
|
+
this.committedWrites = writesAtStart;
|
|
199
|
+
this.updateUnsynced();
|
|
200
|
+
outcome = "unchanged";
|
|
201
|
+
span.setAttribute("workspace.sync.outcome", outcome);
|
|
202
|
+
return {
|
|
203
|
+
dbfsHash: hash,
|
|
204
|
+
moved: false,
|
|
205
|
+
...(journalChangedPaths && { journalChangedPaths }),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const uploadedItems = await this.upload(snapshot);
|
|
209
|
+
span.setAttribute("workspace.sync.uploaded_items", uploadedItems);
|
|
210
|
+
await this.fault("after-put-before-set");
|
|
211
|
+
try {
|
|
212
|
+
await guard.assertCanCommit(baseHash);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (error instanceof BranchWriteRejectedError) {
|
|
216
|
+
outcome = "rejected";
|
|
217
|
+
span.setAttribute("workspace.sync.rejection", error.reason);
|
|
218
|
+
}
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
const result = await transport.setHash({ hash, baseHash, source });
|
|
222
|
+
await this.fault("after-set-before-state");
|
|
223
|
+
await state.write({ dbfsHash: hash });
|
|
224
|
+
this.committedHash = hash;
|
|
225
|
+
await journal?.retireUploaded(hash);
|
|
226
|
+
await this.reportDraftState();
|
|
227
|
+
this.committedWrites = writesAtStart;
|
|
228
|
+
this.updateUnsynced();
|
|
229
|
+
outcome = "committed";
|
|
230
|
+
span.setAttribute("workspace.sync.outcome", outcome);
|
|
231
|
+
this.emit("committed", {
|
|
232
|
+
dbfsHash: hash,
|
|
233
|
+
...(result.commitId && { commitId: result.commitId }),
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
dbfsHash: hash,
|
|
237
|
+
moved: true,
|
|
238
|
+
...(result.commitId && { commitId: result.commitId }),
|
|
239
|
+
...(journalChangedPaths && { journalChangedPaths }),
|
|
240
|
+
};
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
finally {
|
|
244
|
+
this.telemetry.commitDuration.record((performance.now() - started) / 1000, { outcome });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/** Puts what DBFS lacks for `snapshot`; returns the items sent. */
|
|
248
|
+
async upload(snapshot) {
|
|
249
|
+
const { transport } = this.options;
|
|
250
|
+
const sent = await uploadSnapshotItems({
|
|
251
|
+
validateMany: (items) => transport.validateMany(items),
|
|
252
|
+
putMany: async (items) => {
|
|
253
|
+
await transport.putMany(items);
|
|
254
|
+
},
|
|
255
|
+
}, collectSnapshotUploadItems(snapshot, this.hashCache));
|
|
256
|
+
this.hashCache.add_directory_recursive(snapshot);
|
|
257
|
+
return sent;
|
|
258
|
+
}
|
|
259
|
+
/** The local tree's hashed state, or undefined when it has no synced entries. */
|
|
260
|
+
async hashLocalTree() {
|
|
261
|
+
try {
|
|
262
|
+
await fsp.access(this.options.root);
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
const local = await hashLocalDirectory(this.options.root);
|
|
268
|
+
return local.contents.length === 0 ? undefined : local;
|
|
269
|
+
}
|
|
270
|
+
async storeLoaded(hash, tree) {
|
|
271
|
+
await this.options.state.write({ dbfsHash: hash });
|
|
272
|
+
this.hashCache.add_directory_recursive(tree);
|
|
273
|
+
this.committedHash = hash;
|
|
274
|
+
this.localHash = hash;
|
|
275
|
+
}
|
|
276
|
+
async keepOrphan(serverHash, storedHash, tree) {
|
|
277
|
+
const snapshot = await snapshotLocalDirectory(this.options.root);
|
|
278
|
+
const serverFiles = flattenTree(tree);
|
|
279
|
+
const localFiles = flattenTree(snapshot);
|
|
280
|
+
const contents = new Map();
|
|
281
|
+
const collect = (entries, prefix = "") => {
|
|
282
|
+
for (const entry of entries) {
|
|
283
|
+
if (entry.type === "d")
|
|
284
|
+
collect(entry.contents, `${prefix}${entry.name}/`);
|
|
285
|
+
else if (entry.type === "-")
|
|
286
|
+
contents.set(entry.hash, entry.contents);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
collect(snapshot.contents);
|
|
290
|
+
const changed = [];
|
|
291
|
+
for (const [entryPath, entry] of localFiles) {
|
|
292
|
+
const server = serverFiles.get(entryPath);
|
|
293
|
+
const same = server !== undefined &&
|
|
294
|
+
(entry.type === "l"
|
|
295
|
+
? server.type === "l" && server.target === entry.target
|
|
296
|
+
: server.type === "-" &&
|
|
297
|
+
server.hash === entry.hash &&
|
|
298
|
+
server.executable === entry.executable);
|
|
299
|
+
if (!same)
|
|
300
|
+
changed.push({ path: entryPath, ...entry });
|
|
301
|
+
}
|
|
302
|
+
const deleted = [...serverFiles.keys()].filter((entryPath) => !localFiles.has(entryPath));
|
|
303
|
+
const blobs = [];
|
|
304
|
+
const seen = new Set();
|
|
305
|
+
for (const entry of changed) {
|
|
306
|
+
if (entry.type !== "-" || seen.has(entry.hash))
|
|
307
|
+
continue;
|
|
308
|
+
seen.add(entry.hash);
|
|
309
|
+
if (this.hashCache.check_file_content(entry.hash))
|
|
310
|
+
continue;
|
|
311
|
+
blobs.push({
|
|
312
|
+
type: "fileContents",
|
|
313
|
+
contents: contents.get(entry.hash).toString("base64"),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
for (let idx = 0; idx < blobs.length; idx += BLOB_BATCH)
|
|
317
|
+
await this.options.transport.putMany(blobs.slice(idx, idx + BLOB_BATCH));
|
|
318
|
+
for (const hash of seen)
|
|
319
|
+
this.hashCache.add_file_content(hash);
|
|
320
|
+
return this.options.state.writeOrphan({
|
|
321
|
+
createdAt: new Date().toISOString(),
|
|
322
|
+
serverHash,
|
|
323
|
+
storedHash,
|
|
324
|
+
localHash: snapshot.hash,
|
|
325
|
+
changed,
|
|
326
|
+
deleted,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
async reportDraftState() {
|
|
330
|
+
const hasDraft = await (this.options.hasDraft?.() ??
|
|
331
|
+
hasSwapFiles(this.options.root));
|
|
332
|
+
if (hasDraft === this.reportedDraft)
|
|
333
|
+
return;
|
|
334
|
+
await this.options.transport.setDraftState(hasDraft);
|
|
335
|
+
this.reportedDraft = hasDraft;
|
|
336
|
+
}
|
|
337
|
+
async fault(point) {
|
|
338
|
+
await this.options.faults?.[point]?.();
|
|
339
|
+
}
|
|
340
|
+
updateUnsynced() {
|
|
341
|
+
const unsynced = this.unsynced;
|
|
342
|
+
if (unsynced === this.lastUnsynced)
|
|
343
|
+
return;
|
|
344
|
+
this.lastUnsynced = unsynced;
|
|
345
|
+
this.telemetry.unsynced.record(unsynced ? 1 : 0);
|
|
346
|
+
this.emit("unsynced-changed", { unsynced });
|
|
347
|
+
}
|
|
348
|
+
emit(event, payload) {
|
|
349
|
+
for (const listener of this.listeners.get(event) ?? [])
|
|
350
|
+
listener(payload);
|
|
351
|
+
}
|
|
352
|
+
serialize(run) {
|
|
353
|
+
const result = this.queue.then(run, run);
|
|
354
|
+
this.queue = result.catch(() => undefined);
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=sync-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../src/sync-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path rules that decide what the DBFS sync uploads. Moved here from
|
|
3
|
+
* `vite-plugin-file-sync/src/file-system-helpers.ts`, which re-exports them.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* App-root names that hold private configuration (credentials, registry
|
|
7
|
+
* tokens, package-manager hooks). The native sandbox denies the agent access
|
|
8
|
+
* to them. Matched case-insensitively.
|
|
9
|
+
*/
|
|
10
|
+
export declare const PRIVATE_CONFIG_NAMES: readonly string[];
|
|
11
|
+
export declare const PRIVATE_CONFIG_PREFIXES: readonly string[];
|
|
12
|
+
export declare function isPrivateConfigName(name: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Names no upload snapshot includes. `pnpm-workspace.yaml` is read-only to
|
|
15
|
+
* native tools but still persisted, because it holds the app's pnpm overrides.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isSnapshotExcludedName(name: string): boolean;
|
|
18
|
+
/** Native system skills are generated per pod and never synced. */
|
|
19
|
+
export declare const NATIVE_SYSTEM_SKILLS_ROOT = "skills/system";
|
|
20
|
+
export declare const CHECKLIST_PERSISTED_RELATIVE_PATH = ".superblocks/ai/checklist.json";
|
|
21
|
+
/**
|
|
22
|
+
* Sentinel written at the end of the CLI-side brownfield migration that
|
|
23
|
+
* strips public-host `resolved` URLs from `package-lock.json` and repopulates
|
|
24
|
+
* them via `npm install` against the active private registry. Lives under
|
|
25
|
+
* `.superblocks/` (otherwise excluded from sync) but is explicitly persisted
|
|
26
|
+
* so the migration survives across pod cycles. Path is stable because both
|
|
27
|
+
* the CLI (writer) and the sync allowlist (reader) need to agree.
|
|
28
|
+
*/
|
|
29
|
+
export declare const PRIVATE_REGISTRY_MIGRATION_SENTINEL_RELATIVE_PATH = ".superblocks/private-registry-migrated";
|
|
30
|
+
/**
|
|
31
|
+
* What the CLI's npm-to-pnpm app migration keeps so it can turn a converted
|
|
32
|
+
* app back into an npm app once pnpm is off for its org: the npm lockfile it
|
|
33
|
+
* replaced and what it changed. Persisted like the sentinel above, because the
|
|
34
|
+
* rollback happens on a later pod.
|
|
35
|
+
*/
|
|
36
|
+
export declare const NPM_TO_PNPM_STATE_RELATIVE_PATH = ".superblocks/npm-to-pnpm.json";
|
|
37
|
+
/** The template ranges whose upgrade failed, so later pods don't retry them. */
|
|
38
|
+
export declare const TEMPLATE_DEPENDENCIES_STATE_RELATIVE_PATH = ".superblocks/template-dependencies.json";
|
|
39
|
+
export declare const codeModeExcludedFiles: string[];
|
|
40
|
+
/**
|
|
41
|
+
* Suffix of the incremental build-info cache files TypeScript writes in build
|
|
42
|
+
* mode (`tsc -b`). The prefix varies per project (e.g. `tsconfig.tsbuildinfo`,
|
|
43
|
+
* `tsconfig.client.tsbuildinfo`), so exclusion must be suffix-based rather than
|
|
44
|
+
* exact-name based.
|
|
45
|
+
*/
|
|
46
|
+
export declare const TSBUILDINFO_FILE_SUFFIX = ".tsbuildinfo";
|
|
47
|
+
/**
|
|
48
|
+
* Whether a file (by basename) should be excluded from the dbfs sync. Covers
|
|
49
|
+
* the enumerated `codeModeExcludedFiles` plus any `*.tsbuildinfo` build cache
|
|
50
|
+
* emitted by `tsc -b`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function isCodeModeExcludedFile(name: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Allowlist for files that live under `.superblocks/` but must still round-
|
|
55
|
+
* trip through DBFS sync. The directory is otherwise excluded from upload
|
|
56
|
+
* (see `listLocalDirectory`); anything that needs to persist across pod
|
|
57
|
+
* cycles has to be enumerated here.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isPersistedSuperblocksFile(relativePath: string): boolean;
|
|
60
|
+
export declare function isPersistedChecklistPathOrAncestor(relativePath: string): boolean;
|
|
61
|
+
//# sourceMappingURL=sync-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-paths.d.ts","sourceRoot":"","sources":["../src/sync-paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAkBjD,CAAC;AACF,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAyB,CAAC;AAE/E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMzD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,mEAAmE;AACnE,eAAO,MAAM,yBAAyB,kBAAkB,CAAC;AAEzD,eAAO,MAAM,iCAAiC,mCACZ,CAAC;AAGnC;;;;;;;GAOG;AACH,eAAO,MAAM,iDAAiD,2CACpB,CAAC;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,kCAAkC,CAAC;AAE/E,gFAAgF;AAChF,eAAO,MAAM,yCAAyC,4CACX,CAAC;AAE5C,eAAO,MAAM,qBAAqB,UAAqB,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK5D;AAUD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAOxE;AASD,wBAAgB,kCAAkC,CAChD,YAAY,EAAE,MAAM,GACnB,OAAO,CAKT"}
|