@interncom/diplomatic 0.4.4 → 0.5.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.
@@ -1,7 +1,7 @@
1
1
  import { Status } from "../../shared/consts";
2
2
  import { ICrypto } from "../../shared/types";
3
3
  import { EntityID, Hash } from "../../shared/types";
4
- import { IMessageStore, IStorableMessage, IStoredMessage } from "../../types";
4
+ import { ApldState, IMessageStore, IStorableMessage, IStoredMessage } from "../../types";
5
5
  export declare class IDBMessageStore implements IMessageStore {
6
6
  private crypto;
7
7
  db: IDBDatabase;
@@ -9,11 +9,13 @@ export declare class IDBMessageStore implements IMessageStore {
9
9
  add(messages: IStorableMessage[]): Promise<Status[]>;
10
10
  del(keys: Iterable<Hash>): Promise<void>;
11
11
  get(key: Hash): Promise<IStoredMessage | undefined>;
12
- getMany(keys: Iterable<Hash>): Promise<(IStoredMessage | undefined)[]>;
13
12
  has(key: Hash): Promise<boolean>;
14
- list(): Promise<Iterable<IStoredMessage>>;
13
+ list(apld?: ApldState): Promise<IStoredMessage[]>;
15
14
  last(eid: EntityID): Promise<IStoredMessage | undefined>;
16
- listUnapplied(): Promise<IStoredMessage[]>;
17
15
  markApplied(keys: Iterable<Hash>): Promise<void>;
16
+ markFailed(entries: Iterable<{
17
+ key: Hash;
18
+ err: Status;
19
+ }>): Promise<void>;
18
20
  wipe(): Promise<void>;
19
21
  }
@@ -11,8 +11,9 @@ export declare const UPLOAD_QUEUE_TABLE = "uploadQueue";
11
11
  export declare const DOWNLOAD_QUEUE_TABLE = "downloadQueue";
12
12
  export declare const MESSAGES_TABLE = "messages";
13
13
  /**
14
- * Index on messages.apld. Values are "f" (pending) / "t" (applied)
15
- * booleans are not valid IndexedDB keys; single-char strings keep keys compact.
14
+ * Index on messages.apld ({@link APLD_PENDING} / {@link APLD_APPLIED} /
15
+ * {@link APLD_ERROR}). Booleans are not valid IndexedDB keys; single-char
16
+ * strings keep keys compact.
16
17
  */
17
18
  export declare const MESSAGES_APLD_INDEX = "apld";
18
19
  /** Schema version: v3 adds messages.apld index for the apply queue. */
@@ -1,11 +1,11 @@
1
1
  import { Hash } from "../../shared/types";
2
- import { IUploadEntry, IUploadQueue } from "../../types";
2
+ import { IUploadQueue } from "../../types";
3
3
  export declare class IDBUploadQueue implements IUploadQueue {
4
4
  db: IDBDatabase;
5
5
  constructor(db: IDBDatabase);
6
- enq(host: string, entries: Iterable<IUploadEntry>): Promise<void>;
6
+ enq(host: string, hshs: Iterable<Hash>): Promise<void>;
7
7
  deq(host: string, hshs: Iterable<Hash>): Promise<void>;
8
- list(host: string): Promise<IUploadEntry[]>;
8
+ list(host: string): Promise<Hash[]>;
9
9
  count(): Promise<number>;
10
10
  wipe(): Promise<void>;
11
11
  }
@@ -1,6 +1,6 @@
1
1
  import { ICrypto } from "../../shared/types";
2
2
  import { EntityID, Hash } from "../../shared/types";
3
- import { IMessageStore, IStorableMessage, IStoredMessage, IStoredMessageData } from "../../types";
3
+ import { ApldState, IMessageStore, IStorableMessage, IStoredMessage, IStoredMessageData } from "../../types";
4
4
  import { Status } from "../../shared/consts";
5
5
  export declare class MemoryMessageStore implements IMessageStore {
6
6
  private crypto;
@@ -9,11 +9,13 @@ export declare class MemoryMessageStore implements IMessageStore {
9
9
  add(messages: IStorableMessage[]): Promise<Status[]>;
10
10
  del(keys: Iterable<Hash>): Promise<void>;
11
11
  get(key: Hash): Promise<IStoredMessage | undefined>;
12
- getMany(keys: Iterable<Hash>): Promise<(IStoredMessage | undefined)[]>;
13
12
  has(key: Hash): Promise<boolean>;
14
- list(): Promise<Iterable<IStoredMessage>>;
13
+ list(apld?: ApldState): Promise<IStoredMessage[]>;
15
14
  last(eid: EntityID): Promise<IStoredMessage | undefined>;
16
- listUnapplied(): Promise<IStoredMessage[]>;
17
15
  markApplied(keys: Iterable<Hash>): Promise<void>;
16
+ markFailed(entries: Iterable<{
17
+ key: Hash;
18
+ err: Status;
19
+ }>): Promise<void>;
18
20
  wipe(): Promise<void>;
19
21
  }
@@ -1,11 +1,10 @@
1
1
  import { Hash } from "../../shared/types";
2
- import { IUploadEntry, IUploadQueue } from "../../types";
2
+ import { IUploadQueue } from "../../types";
3
3
  export declare class MemoryUploadQueue implements IUploadQueue {
4
- /** host → (hashHex → bodyLen) */
5
- queue: Map<string, Map<string, number>>;
6
- enq(host: string, entries: Iterable<IUploadEntry>): Promise<void>;
4
+ queue: Map<string, Set<string>>;
5
+ enq(host: string, hshs: Iterable<Hash>): Promise<void>;
7
6
  deq(host: string, hshs: Iterable<Hash>): Promise<void>;
8
- list(host: string): Promise<IUploadEntry[]>;
7
+ list(host: string): Promise<Hash[]>;
9
8
  count(): Promise<number>;
10
9
  wipe(): Promise<void>;
11
10
  }
@@ -62,13 +62,8 @@ export declare function openPulled<Handle extends HostHandle>(store: IStore<Hand
62
62
  export declare function deqDownloadsForHeadHashes<Handle extends HostHandle>(store: Pick<IStore<Handle>, "downloads">, hashes: Iterable<Hash>, crypto: ICrypto): Promise<void>;
63
63
  /** Discover unseen bags and enqueue download work; advance host lastSeq. */
64
64
  export declare function syncPeek<Handle extends HostHandle>({ conn, store, enclave, host, crypto, onProgress, peekProgressEvery, peekConcurrency, }: ISyncParams<Handle>): Promise<Status>;
65
- /**
66
- * Soft max plaintext body bytes per messages.getMany (IDB load bound).
67
- * Sealed bags are larger; push still uses maxPushBytes on bag size.
68
- */
69
- export declare const defaultMaxGetBodyBytes: number;
70
65
  /** Seal and upload pending msgs; list once so concurrent enqs wait for next sync. */
71
- export declare function syncPush<Handle extends HostHandle>({ conn, store, host, maxPushBytes, onProgress, }: ISyncParams<Handle>): Promise<Status>;
66
+ export declare function syncPush<Handle extends HostHandle>({ conn, store, host, maxPushBytes, onProgress }: ISyncParams<Handle>): Promise<Status>;
72
67
  /**
73
68
  * Pull + open for one host, depth-1 pipelined:
74
69
  * await pull(i); start pull(i+1); open(i); afterOpen? (exec)
@@ -45,16 +45,10 @@ export interface IHostStore<Handle extends HostHandle> {
45
45
  wipe: () => Promise<void>;
46
46
  touch: (label: string, seq: number) => Promise<void>;
47
47
  }
48
- /** Pending upload: archive key + plaintext body size for IDB get batching. */
49
- export interface IUploadEntry {
50
- hash: Hash;
51
- /** Body byte length (0 if unknown / empty). */
52
- bodyLen: number;
53
- }
54
48
  export interface IUploadQueue {
55
- enq: (host: string, entries: Iterable<IUploadEntry>) => Promise<void>;
49
+ enq: (host: string, hshs: Iterable<Hash>) => Promise<void>;
56
50
  deq: (host: string, hshs: Iterable<Hash>) => Promise<void>;
57
- list: (host: string) => Promise<IUploadEntry[]>;
51
+ list: (host: string) => Promise<Hash[]>;
58
52
  count: () => Promise<number>;
59
53
  wipe(): Promise<void>;
60
54
  }
@@ -80,10 +74,18 @@ export interface IDownloadQueue {
80
74
  count: () => Promise<number>;
81
75
  wipe(): Promise<void>;
82
76
  }
77
+ /**
78
+ * Apply lifecycle values for archive rows (IDB-indexable single-char strings;
79
+ * booleans are not valid IndexedDB keys). Defined first so {@link ApldState}
80
+ * is only those three literals.
81
+ */
82
+ export declare const APLD_PENDING: "f";
83
+ export declare const APLD_APPLIED: "t";
84
+ export declare const APLD_ERROR: "e";
85
+ /** Only {@link APLD_PENDING}, {@link APLD_APPLIED}, or {@link APLD_ERROR}. */
86
+ export type ApldState = typeof APLD_PENDING | typeof APLD_APPLIED | typeof APLD_ERROR;
83
87
  /**
84
88
  * Archive fields shared by read and write.
85
- * `apld`: true once the msg has been applied by the application state manager;
86
- * false while still pending apply.
87
89
  */
88
90
  export interface IStoredMessageFields {
89
91
  eid: EntityID;
@@ -93,19 +95,23 @@ export interface IStoredMessageFields {
93
95
  }
94
96
  /**
95
97
  * What may come back from storage (pre-apld rows can omit the field).
96
- * IDB stores "t"|"f" (booleans are not valid IndexedDB index keys).
97
- * Prefer {@link normalizeStoredMessageData} before use.
98
+ * Typed rows use only {@link ApldState}; {@link apldFromStored} coerces
99
+ * legacy boolean / unknown values at the storage boundary.
98
100
  */
99
101
  export interface IStoredMessageData extends IStoredMessageFields {
100
- apld?: boolean | "t" | "f";
102
+ apld?: ApldState;
103
+ /** Status code when apld is {@link APLD_ERROR}. */
104
+ err?: number;
101
105
  }
102
106
  /**
103
107
  * Required shape for every put into the message archive (app/API layer).
104
- * Callers must set `apld` (false until applied, then true).
105
- * The IDB adapter persists this as "t"|"f" for indexing.
108
+ * `apld` is required and must be one of the three {@link ApldState} values.
109
+ * Omit optional fields (`off`, `ctr`, `body`, `err`) rather than storing empties.
106
110
  */
107
111
  export type IStoredMessageWrite = IStoredMessageFields & {
108
- apld: boolean;
112
+ apld: ApldState;
113
+ /** Status code when apld is {@link APLD_ERROR}. */
114
+ err?: number;
109
115
  };
110
116
  export interface IStorableMessage {
111
117
  key: Hash;
@@ -115,34 +121,51 @@ export interface IStoredMessage {
115
121
  hash: Hash;
116
122
  head: IMessageHead;
117
123
  body?: EncodedMessage;
118
- applied: boolean;
124
+ /** Apply lifecycle — same {@link ApldState} as the archive row. */
125
+ apld: ApldState;
126
+ /** Status code when apld is {@link APLD_ERROR}. */
127
+ err?: number;
119
128
  }
129
+ /** True only for the three legal {@link ApldState} values. */
130
+ export declare function isApldState(v: unknown): v is ApldState;
120
131
  /**
121
- * Coerce stored `apld` to boolean.
122
- * Applied: true | "t". Pending: false | "f" | missing.
132
+ * Coerce raw storage values to {@link ApldState}.
133
+ * Applied: true | APLD_APPLIED. Failed: APLD_ERROR.
134
+ * Pending: false | APLD_PENDING | missing | anything else.
123
135
  */
124
- export declare function apldFromStored(v: unknown): boolean;
125
- /** Coerce storage rows to the write shape with boolean apld. */
126
- export declare function normalizeStoredMessageData(data: IStoredMessageData): IStoredMessageWrite;
127
- /** Pending apply when not yet marked applied. */
136
+ export declare function apldFromStored(v: unknown): ApldState;
137
+ /** Pending apply when not yet applied or terminally failed. */
128
138
  export declare function isPendingApply(data: IStoredMessageData): boolean;
139
+ /**
140
+ * Apply failures that should not be retried (poison / protocol / shape).
141
+ * Transient storage errors stay pending ({@link APLD_PENDING}) for a later drain.
142
+ */
143
+ export declare function isTerminalApplyFailure(st: Status): boolean;
144
+ /**
145
+ * Mutate a stored row's apply state in place (no copy).
146
+ * Clears `err` unless setting {@link APLD_ERROR}.
147
+ */
148
+ export declare function setApld(data: IStoredMessageData, apld: ApldState, err?: Status): void;
129
149
  export declare function toStoredMessage(hash: Hash, data: IStoredMessageData, crypto: ICrypto): Promise<IStoredMessage>;
130
150
  export interface IMessageStore {
131
151
  add: (messages: IStorableMessage[]) => Promise<Status[]>;
132
152
  get: (key: Hash) => Promise<IStoredMessage | undefined>;
133
- /**
134
- * Batch load by archive keys (one store round-trip when possible).
135
- * Result aligned with input order; missing keys are undefined.
136
- */
137
- getMany: (keys: Iterable<Hash>) => Promise<(IStoredMessage | undefined)[]>;
138
153
  has: (key: Hash) => Promise<boolean>;
139
154
  del: (keys: Iterable<Hash>) => Promise<void>;
140
- list: () => Promise<Iterable<IStoredMessage>>;
155
+ /**
156
+ * List archive rows. Pass {@link ApldState} to filter by apply lifecycle
157
+ * (e.g. {@link APLD_PENDING} for the apply queue, {@link APLD_ERROR} for
158
+ * diagnostics). Omit for all messages.
159
+ */
160
+ list: (apld?: ApldState) => Promise<IStoredMessage[]>;
141
161
  last: (eid: EntityID) => Promise<IStoredMessage | undefined>;
142
- /** Messages stored but not yet applied (apld === false). */
143
- listUnapplied: () => Promise<IStoredMessage[]>;
144
- /** Mark archive rows as applied (apld = true). */
162
+ /** Mark archive rows as applied ({@link APLD_APPLIED}). */
145
163
  markApplied: (keys: Iterable<Hash>) => Promise<void>;
164
+ /** Mark archive rows as terminal apply failure ({@link APLD_ERROR}). */
165
+ markFailed: (entries: Iterable<{
166
+ key: Hash;
167
+ err: Status;
168
+ }>) => Promise<void>;
146
169
  wipe(): Promise<void>;
147
170
  }
148
171
  export interface IStore<Handle extends HostHandle> {