@interncom/diplomatic 0.2.6 → 0.3.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.
@@ -12,6 +12,11 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
12
12
  private transport;
13
13
  private crypto;
14
14
  private forceSkewHandlingByDefault;
15
+ /**
16
+ * When set (e.g. main-thread local writer next to a sync worker), called
17
+ * instead of running sync on this client. Use to hand off push to the worker.
18
+ */
19
+ private onScheduleSync?;
15
20
  connections: Map<string, DiplomaticClientAPI<Handle>>;
16
21
  /**
17
22
  * Serializes sync so doSync never overlaps, while coalescing stampedes:
@@ -19,6 +24,11 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
19
24
  * pass if more sync was requested mid-flight (see CoalesceTail).
20
25
  */
21
26
  private syncRuns;
27
+ /**
28
+ * Serializes application of archived msgs so concurrent apply /
29
+ * drainApplyQueue do not interleave markApplied (each job runs fully, in order).
30
+ */
31
+ private applyChain;
22
32
  clientState: IStateEmitter<IDiplomaticClientState>;
23
33
  xferState: IStateEmitter<IDiplomaticClientXferState>;
24
34
  /**
@@ -27,13 +37,56 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
27
37
  */
28
38
  maxPushBytes: number;
29
39
  maxPullBytes: number;
30
- constructor(clock: IClock, state: IStateManager, store: IStore<Handle>, transport: (host: IHostConnectionInfo<Handle>) => ITransport, crypto: ICrypto, forceSkewHandlingByDefault?: boolean, maxPushBytes?: number, maxPullBytes?: number);
31
- private readonly SYNC_DEBOUNCE_DELAY_MS;
32
- private syncTimeout;
40
+ /**
41
+ * Peek progress stride in heads (see `defaultPeekProgressEvery`).
42
+ * Emits on head 1, every N heads, and the last head.
43
+ */
44
+ peekProgressEvery: number;
45
+ /** Latest progress; part of xferState for snapshot + subscribe. */
46
+ private lastProgress;
47
+ /**
48
+ * Debounced sync after local writes (when not handing off via onScheduleSync).
49
+ */
50
+ private scheduledSync;
51
+ constructor(clock: IClock, state: IStateManager, store: IStore<Handle>, transport: (host: IHostConnectionInfo<Handle>) => ITransport, crypto: ICrypto, forceSkewHandlingByDefault?: boolean, maxPushBytes?: number, maxPullBytes?: number,
52
+ /**
53
+ * When set (e.g. main-thread local writer next to a sync worker), called
54
+ * instead of running sync on this client. Use to hand off push to the worker.
55
+ */
56
+ onScheduleSync?: (() => void) | undefined);
57
+ /** Record phase progress and notify xferState listeners. */
58
+ private emitProgress;
33
59
  setSeed(seed: MasterSeed): Promise<void>;
34
60
  private getClientState;
35
61
  private getXferState;
62
+ /**
63
+ * Persist msgs to the archive as unapplied (apld=false), apply via
64
+ * IStateManager, mark applied, then optionally enqueue upload.
65
+ *
66
+ * Order is intentional for crash safety:
67
+ * 1) durable archive 2) apply + apld=true 3) upload queue
68
+ * so we never upload something that never applied, and crash between
69
+ * 1–2 is recovered by drainApplyQueue.
70
+ */
36
71
  private apply;
72
+ private enqueueApplyJob;
73
+ /**
74
+ * Apply archived msgs that are still unapplied (crash recovery).
75
+ * Call after open / connect so a crash between store and apply is healed.
76
+ */
77
+ drainApplyQueue(): Promise<Status[]>;
78
+ private doDrainApplyQueue;
79
+ /** Apply specific archive keys via IStateManager and mark applied. */
80
+ private applyHashes;
81
+ /**
82
+ * Apply a batch of archived msgs via IStateManager and mark successes applied.
83
+ *
84
+ * TODO: may need to chunk large batches (memory / IDB / UI). Also test edge
85
+ * cases: state.apply returning stats.length !== msgs.length (short/long
86
+ * array, holes) — markApplied currently indexes stats[i] against stored[i]
87
+ * without validating length alignment.
88
+ */
89
+ private applyStored;
37
90
  insertRaw(bod: EncodedMessage): Promise<ValStat<IMessageHead>>;
38
91
  upsertRaw(eid: EntityID, bod: EncodedMessage | undefined, force?: boolean): Promise<ValStat<IMessageHead>>;
39
92
  insert<T = unknown>(op: IInsertParams<T>): Promise<ValStat<IMessageHead>>;
@@ -52,7 +105,13 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
52
105
  import: (file: File, options?: {
53
106
  onProgress?: (index: number, total: number, status: Status) => void;
54
107
  }) => Promise<Status>;
108
+ /**
109
+ * After local apply + upload enqueue: either hand off to a peer (worker via
110
+ * onScheduleSync — debounced there) or debounce sync on this client.
111
+ */
55
112
  private scheduleSync;
113
+ /** Encode the local message archive; used by worker path (main saves file). */
114
+ exportBytes(): Promise<ValStat<Uint8Array>>;
56
115
  export(filename: string): Promise<Status.Success | import("./shared/valstat").StatusNOK>;
57
116
  link(host: IHostConnectionInfo<Handle>, connect?: boolean): Promise<void>;
58
117
  unlink(label: string): Promise<void>;
@@ -18,5 +18,35 @@ export declare class CoalesceTail<T> {
18
18
  private inflight;
19
19
  private again;
20
20
  run(work: () => Promise<T>): Promise<T>;
21
+ /** Wait for any in-flight drain to finish (does not request a new pass). */
22
+ flush(): Promise<void>;
21
23
  private drain;
22
24
  }
25
+ /** Default quiet period before a scheduled sync after local writes. */
26
+ export declare const defaultSyncDebounceMs = 100;
27
+ /**
28
+ * Debounce async work: each `schedule()` resets a timer; when the quiet period
29
+ * elapses, `work` runs via {@link CoalesceTail} so stampeding fires do not
30
+ * overlap (trailing pass if more demand arrives mid-run).
31
+ *
32
+ * - `delayMs <= 0`: run on the next microtask path immediately (no timer).
33
+ * - `flush()`: cancel the timer, start work if a run was pending, await drain.
34
+ * - `cancel()`: drop the pending timer without running (in-flight continues).
35
+ */
36
+ export declare class Debounced<T = void> {
37
+ private timer;
38
+ private readonly delayMs;
39
+ private readonly work;
40
+ private readonly tail;
41
+ constructor(delayMs: number, work: () => Promise<T>);
42
+ /** Request a run after the debounce quiet period (resets the timer). */
43
+ schedule(): void;
44
+ /**
45
+ * Run any pending debounced work now and wait until the drain finishes.
46
+ * No-op if nothing is pending or in flight.
47
+ */
48
+ flush(): Promise<void>;
49
+ /** Drop a pending timer without starting work. In-flight work is untouched. */
50
+ cancel(): void;
51
+ private fire;
52
+ }
@@ -17,10 +17,16 @@ import { nullStateManager, StateManager } from "./state";
17
17
  import { IDBStore, openIDBStore } from "./stores/idb/store";
18
18
  import { MemoryStore } from "./stores/memory/store";
19
19
  import { SingletonStateManager } from "./shared/singleton";
20
- import type { Applier, IDiplomaticClientState, IStore, IStoredMessage, IStoredMessageData } from "./types";
20
+ import type { Applier, IClient, IDiplomaticClientState, IStore, IStoredMessage, IStoredMessageData, IStoredMessageWrite } from "./types";
21
+ import { isPendingApply, normalizeStoredMessageData } from "./types";
22
+ import type { SyncProgressEvent } from "./progress";
23
+ import { defaultPeekProgressEvery, idleProgress, shouldEmitItemProgress } from "./progress";
24
+ import { openDiplomaticClient, type OpenDiplomaticClientMainOptions, type OpenDiplomaticClientOptions, type OpenDiplomaticClientWorkerOptions, type OpenedDiplomaticClient } from "./openClient";
25
+ import { WorkerClient } from "./worker/client";
26
+ import type { WorkerClientOptions } from "./worker/client";
21
27
  export declare function genWebClient(stateMgr: IStateManager, url: URL): Promise<{
22
28
  client: SyncClient<URL>;
23
29
  setSeed: (seedHex: string) => Promise<void>;
24
30
  }>;
25
- export { btoh, Clock, crypto, Decoder, eidCodec, Encoder, EntDBMemory, EntIDB, EntitiesQuery, EntityID, entStateManager, genSingletonEID, GroupID, hostHTTPTransport, htob, HTTPTransport, IDBStore, IEntDB, IEntity, IStore, MasterSeed, MemoryStore, nullEntDB, nullStateManager, openEntIDB, openIDBStore, SingletonStateManager, StateManager, Status, SyncClient, TypedEventEmitter, useClient, useClientState, useClientXferState, useStateWatcher, useStateWatcherSuspense, useSyncOnResume, };
26
- export type { Applier, HostHandle, ICrypto, IDiplomaticClientState, IHostConnectionInfo, IMessage, IMutateOp, IOp, IStateManager, IStoredMessage, IStoredMessageData, ITransport, };
31
+ export { btoh, Clock, crypto, Decoder, defaultPeekProgressEvery, eidCodec, Encoder, EntDBMemory, EntIDB, EntitiesQuery, EntityID, entStateManager, genSingletonEID, GroupID, hostHTTPTransport, htob, HTTPTransport, IDBStore, idleProgress, IEntDB, IEntity, isPendingApply, IStore, MasterSeed, MemoryStore, normalizeStoredMessageData, nullEntDB, nullStateManager, openDiplomaticClient, openEntIDB, openIDBStore, shouldEmitItemProgress, SingletonStateManager, StateManager, Status, SyncClient, TypedEventEmitter, useClient, useClientState, useClientXferState, useStateWatcher, useStateWatcherSuspense, useSyncOnResume, WorkerClient, };
32
+ export type { Applier, HostHandle, IClient, ICrypto, IDiplomaticClientState, IHostConnectionInfo, IMessage, IMutateOp, IOp, IStateManager, IStoredMessage, IStoredMessageData, IStoredMessageWrite, ITransport, OpenDiplomaticClientMainOptions, OpenDiplomaticClientOptions, OpenDiplomaticClientWorkerOptions, OpenedDiplomaticClient, SyncProgressEvent, WorkerClientOptions, };