@fluid-experimental/pact-map 2.0.0-internal.7.3.0 → 2.0.0-internal.7.4.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.
@@ -11,8 +11,7 @@ import { SharedObject } from '@fluidframework/shared-object-base';
11
11
 
12
12
  /**
13
13
  * Details of the accepted pact.
14
- *
15
- * @public
14
+ * @internal
16
15
  */
17
16
  export declare interface IAcceptedPact<T> {
18
17
  /**
@@ -35,8 +34,7 @@ export declare interface IAcceptedPact<T> {
35
34
  * 1. "pending" state where the proposal has been sequenced, but there are still outstanding acceptances
36
35
  * 2. "accepted" state where all clients who were connected at the time the proposal was made have either accepted
37
36
  * or disconnected.
38
- *
39
- * @public
37
+ * @internal
40
38
  */
41
39
  export declare interface IPactMap<T = unknown> extends ISharedObject<IPactMapEvents> {
42
40
  /**
@@ -77,8 +75,7 @@ export declare interface IPactMap<T = unknown> extends ISharedObject<IPactMapEve
77
75
 
78
76
  /**
79
77
  * Events emitted by {@link IPactMap}.
80
- *
81
- * @public
78
+ * @internal
82
79
  */
83
80
  export declare interface IPactMapEvents extends ISharedObjectEvents {
84
81
  /**
@@ -144,8 +141,7 @@ export declare interface IPactMapEvents extends ISharedObjectEvents {
144
141
  * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);
145
142
  * });
146
143
  * ```
147
- *
148
- * @public
144
+ * @internal
149
145
  */
150
146
  export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implements IPactMap<T> {
151
147
  /**
@@ -210,27 +206,22 @@ export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> i
210
206
  * Create a summary for the PactMap
211
207
  *
212
208
  * @returns the summary of the current state of the PactMap
213
- * @internal
214
209
  */
215
210
  protected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats;
216
211
  /**
217
212
  * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
218
- * @internal
219
213
  */
220
214
  protected loadCore(storage: IChannelStorageService): Promise<void>;
221
215
  /**
222
216
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}
223
- * @internal
224
217
  */
225
218
  protected initializeLocalCore(): void;
226
219
  /**
227
220
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}
228
- * @internal
229
221
  */
230
222
  protected onDisconnect(): void;
231
223
  /**
232
224
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}
233
- * @internal
234
225
  */
235
226
  protected reSubmitCore(content: unknown, localOpMetadata: unknown): void;
236
227
  /**
@@ -240,7 +231,6 @@ export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> i
240
231
  * @param local - whether the message was sent by the local client
241
232
  * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
242
233
  * For messages from a remote client, this will be undefined.
243
- * @internal
244
234
  */
245
235
  protected processCore(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void;
246
236
  applyStashedOp(): void;
package/lib/pactMap.d.ts CHANGED
@@ -6,7 +6,7 @@ import { type ISequencedDocumentMessage } from "@fluidframework/protocol-definit
6
6
  import { type IChannelAttributes, type IFluidDataStoreRuntime, type IChannelStorageService, type IChannelFactory } from "@fluidframework/datastore-definitions";
7
7
  import { type ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
8
8
  import { type IFluidSerializer, SharedObject } from "@fluidframework/shared-object-base";
9
- import { type IAcceptedPact, type IPactMap, type IPactMapEvents } from "./interfaces";
9
+ import { type IAcceptedPact, type IPactMap, type IPactMapEvents } from "./interfaces.mjs";
10
10
  /**
11
11
  * The PactMap distributed data structure provides key/value storage with a cautious conflict resolution strategy.
12
12
  * This strategy optimizes for all clients being aware of the change prior to considering the value as accepted.
@@ -64,8 +64,7 @@ import { type IAcceptedPact, type IPactMap, type IPactMapEvents } from "./interf
64
64
  * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);
65
65
  * });
66
66
  * ```
67
- *
68
- * @public
67
+ * @internal
69
68
  */
70
69
  export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implements IPactMap<T> {
71
70
  /**
@@ -130,27 +129,22 @@ export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> i
130
129
  * Create a summary for the PactMap
131
130
  *
132
131
  * @returns the summary of the current state of the PactMap
133
- * @internal
134
132
  */
135
133
  protected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats;
136
134
  /**
137
135
  * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
138
- * @internal
139
136
  */
140
137
  protected loadCore(storage: IChannelStorageService): Promise<void>;
141
138
  /**
142
139
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}
143
- * @internal
144
140
  */
145
141
  protected initializeLocalCore(): void;
146
142
  /**
147
143
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}
148
- * @internal
149
144
  */
150
145
  protected onDisconnect(): void;
151
146
  /**
152
147
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}
153
- * @internal
154
148
  */
155
149
  protected reSubmitCore(content: unknown, localOpMetadata: unknown): void;
156
150
  /**
@@ -160,7 +154,6 @@ export declare class PactMap<T = unknown> extends SharedObject<IPactMapEvents> i
160
154
  * @param local - whether the message was sent by the local client
161
155
  * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
162
156
  * For messages from a remote client, this will be undefined.
163
- * @internal
164
157
  */
165
158
  protected processCore(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void;
166
159
  applyStashedOp(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"pactMap.d.ts","sourceRoot":"","sources":["../src/pactMap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,EAAE,KAAK,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AACnG,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAEjF,OAAO,EAEN,KAAK,gBAAgB,EACrB,YAAY,EACZ,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAyEtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,qBAAa,OAAO,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC,cAAc,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IAC5F;;;;;;OAMG;WACW,MAAM,CAAC,OAAO,EAAE,sBAAsB,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAI3E;;;;OAIG;WACW,UAAU,IAAI,eAAe;IAI3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAE/D;;;;;;OAMG;gBAEF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,EAC/B,UAAU,EAAE,kBAAkB;IAU/B;;OAEG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAItC;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS;IAahE;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC;;OAEG;IACI,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI7C;;OAEG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IA4BnD;;OAEG;IACI,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBhC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAsDhC;IAEF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CA0BnC;IAEF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAsBvC;IAEF;;;;;OAKG;IACH,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,qBAAqB;IAK5E;;;OAGG;cACa,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxE;;;OAGG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI;IAErC;;;OAGG;IACH,SAAS,CAAC,YAAY,IAAI,IAAI;IAE9B;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,GAAG,IAAI;IAuBxE;;;;;;;;OAQG;IACH,SAAS,CAAC,WAAW,CACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,OAAO,GACtB,IAAI;IAkCA,cAAc,IAAI,IAAI;CAG7B"}
1
+ {"version":3,"file":"pactMap.d.ts","sourceRoot":"","sources":["../src/pactMap.ts"],"names":[],"mappings":"AAAA;;;GAGG;OASI,EAAE,KAAK,yBAAyB,EAAe,MAAM,sCAAsC;OAC3F,EACN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,MAAM,uCAAuC;OACvC,EAAE,KAAK,qBAAqB,EAAE,MAAM,qCAAqC;OAEzE,EAEN,KAAK,gBAAgB,EACrB,YAAY,EACZ,MAAM,oCAAoC;OAEpC,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE;AAyEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,qBAAa,OAAO,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,YAAY,CAAC,cAAc,CAAE,YAAW,QAAQ,CAAC,CAAC,CAAC;IAC5F;;;;;;OAMG;WACW,MAAM,CAAC,OAAO,EAAE,sBAAsB,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAI3E;;;;OAIG;WACW,UAAU,IAAI,eAAe;IAI3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAE/D;;;;;;OAMG;gBAEF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,EAC/B,UAAU,EAAE,kBAAkB;IAU/B;;OAEG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAItC;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS;IAahE;;OAEG;IACI,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAItC;;OAEG;IACI,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI7C;;OAEG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,GAAG,IAAI;IA4BnD;;OAEG;IACI,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBhC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAsDhC;IAEF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CA0BnC;IAEF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAsBvC;IAEF;;;;OAIG;IACH,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,qBAAqB;IAK5E;;OAEG;cACa,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxE;;OAEG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI;IAErC;;OAEG;IACH,SAAS,CAAC,YAAY,IAAI,IAAI;IAE9B;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,GAAG,IAAI;IAuBxE;;;;;;;OAOG;IACH,SAAS,CAAC,WAAW,CACpB,OAAO,EAAE,yBAAyB,EAClC,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,OAAO,GACtB,IAAI;IAkCA,cAAc,IAAI,IAAI;CAG7B"}
package/lib/pactMap.mjs CHANGED
@@ -66,8 +66,7 @@ const snapshotFileName = "header";
66
66
  * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);
67
67
  * });
68
68
  * ```
69
- *
70
- * @public
69
+ * @internal
71
70
  */
72
71
  export class PactMap extends SharedObject {
73
72
  /**
@@ -272,7 +271,6 @@ export class PactMap extends SharedObject {
272
271
  * Create a summary for the PactMap
273
272
  *
274
273
  * @returns the summary of the current state of the PactMap
275
- * @internal
276
274
  */
277
275
  summarizeCore(serializer) {
278
276
  const allEntries = [...this.values.entries()];
@@ -280,7 +278,6 @@ export class PactMap extends SharedObject {
280
278
  }
281
279
  /**
282
280
  * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
283
- * @internal
284
281
  */
285
282
  async loadCore(storage) {
286
283
  const content = await readAndParse(storage, snapshotFileName);
@@ -290,17 +287,14 @@ export class PactMap extends SharedObject {
290
287
  }
291
288
  /**
292
289
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}
293
- * @internal
294
290
  */
295
291
  initializeLocalCore() { }
296
292
  /**
297
293
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}
298
- * @internal
299
294
  */
300
295
  onDisconnect() { }
301
296
  /**
302
297
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}
303
- * @internal
304
298
  */
305
299
  reSubmitCore(content, localOpMetadata) {
306
300
  const pactMapOp = content;
@@ -327,7 +321,6 @@ export class PactMap extends SharedObject {
327
321
  * @param local - whether the message was sent by the local client
328
322
  * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
329
323
  * For messages from a remote client, this will be undefined.
330
- * @internal
331
324
  */
332
325
  processCore(message, local, localOpMetadata) {
333
326
  // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
@@ -1 +1 @@
1
- {"version":3,"file":"pactMap.mjs","sourceRoot":"","sources":["../src/pactMap.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable unicorn/numeric-separators-style */\n\n// False positive: this is an import from the `events` package, not from Node.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { EventEmitter } from \"events\";\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { type ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype IChannelAttributes,\n\ttype IFluidDataStoreRuntime,\n\ttype IChannelStorageService,\n\ttype IChannelFactory,\n} from \"@fluidframework/datastore-definitions\";\nimport { type ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport {\n\tcreateSingleBlobSummary,\n\ttype IFluidSerializer,\n\tSharedObject,\n} from \"@fluidframework/shared-object-base\";\nimport { PactMapFactory } from \"./pactMapFactory\";\nimport { type IAcceptedPact, type IPactMap, type IPactMapEvents } from \"./interfaces\";\n\n/**\n * The accepted pact information, if any.\n */\ninterface IAcceptedPactInternal<T> {\n\t/**\n\t * The accepted value of the given type or undefined (typically in case of delete).\n\t */\n\tvalue: T | undefined;\n\n\t/**\n\t * The sequence number when the value was accepted, which will normally coincide with one of two possibilities:\n\t * - The sequence number of the \"accept\" op from the final client we expected signoff from\n\t * - The sequence number of the ClientLeave of the final client we expected signoff from\n\t *\n\t * For values set in detached state, it will be 0.\n\t */\n\tsequenceNumber: number;\n}\n\n/**\n * The pending pact information, if any.\n */\ninterface IPendingPact<T> {\n\t/**\n\t * The pending value of the given type or undefined (typically in case of delete).\n\t */\n\tvalue: T | undefined;\n\t/**\n\t * The list of clientIds that we expect \"accept\" ops from. Clients are also removed from this list if they\n\t * disconnect without accepting. When this list empties, the pending value transitions to accepted.\n\t */\n\texpectedSignoffs: string[];\n}\n\n/**\n * Internal format of the values stored in the PactMap.\n */\ntype Pact<T> =\n\t| { accepted: IAcceptedPactInternal<T>; pending: undefined }\n\t| { accepted: undefined; pending: IPendingPact<T> }\n\t| { accepted: IAcceptedPactInternal<T>; pending: IPendingPact<T> };\n\n/**\n * PactMap operation formats\n */\ninterface IPactMapSetOperation<T> {\n\ttype: \"set\";\n\tkey: string;\n\tvalue: T | undefined;\n\n\t/**\n\t * A \"set\" is only valid if it is made with knowledge of the most-recent accepted proposal - its reference\n\t * sequence number is greater than or equal to the sequence number when that prior value was accepted.\n\t *\n\t * However, we can't trust the built-in referenceSequenceNumber of the op because of resubmit on reconnect,\n\t * which will update the referenceSequenceNumber on our behalf.\n\t *\n\t * Instead we need to separately stamp the real reference sequence number on the op itself.\n\t */\n\trefSeq: number;\n}\n\ninterface IPactMapAcceptOperation {\n\ttype: \"accept\";\n\tkey: string;\n}\n\ntype IPactMapOperation<T> = IPactMapSetOperation<T> | IPactMapAcceptOperation;\n\nconst snapshotFileName = \"header\";\n\n/**\n * The PactMap distributed data structure provides key/value storage with a cautious conflict resolution strategy.\n * This strategy optimizes for all clients being aware of the change prior to considering the value as accepted.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * To create a `PactMap`, call the static create method:\n *\n * ```typescript\n * const pactMap = PactMap.create(this.runtime, id);\n * ```\n *\n * ### Usage\n *\n * Setting and reading values is somewhat similar to a `SharedMap`. However, because the acceptance strategy\n * cannot be resolved until other clients have witnessed the set, the new value will only be reflected in the data\n * after the consensus is reached.\n *\n * ```typescript\n * pactMap.on(\"pending\", (key: string) => {\n * console.log(pactMap.getPending(key));\n * });\n * pactMap.on(\"accepted\", (key: string) => {\n * console.log(pactMap.get(key));\n * });\n * pactMap.set(\"myKey\", \"myValue\");\n *\n * // Reading from the pact map prior to the async operation's completion will still return the old value.\n * console.log(pactMap.get(\"myKey\"));\n * ```\n *\n * The acceptance process has two stages. When an op indicating a client's attempt to set a value is sequenced,\n * we first verify that it was set with knowledge of the most recently accepted value (consensus-like FWW). If it\n * meets this bar, then the value is \"pending\". During this time, clients may observe the pending value and act\n * upon it, but should be aware that not all other clients may have witnessed the value yet. Once all clients\n * that were connected at the time of the value being set have explicitly acknowledged the new value, the value\n * becomes \"accepted\". Once the value is accepted, it once again becomes possible to set the value, again with\n * consensus-like FWW resolution.\n *\n * Since all connected clients must explicitly accept the new value, it is important that all connected clients\n * have the PactMap loaded, including e.g. the summarizing client. Otherwise, those clients who have not loaded\n * the PactMap will not be responding to proposals and delay their acceptance (until they disconnect, which implicitly\n * removes them from consideration). The easiest way to ensure all clients load the PactMap is to instantiate it\n * as part of instantiating the IRuntime for the container (containerHasInitialized if using Aqueduct).\n *\n * ### Eventing\n *\n * `PactMap` is an `EventEmitter`, and will emit events when a new value is accepted for a key.\n *\n * ```typescript\n * pactMap.on(\"accept\", (key: string) => {\n * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);\n * });\n * ```\n *\n * @public\n */\nexport class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implements IPactMap<T> {\n\t/**\n\t * Create a new PactMap\n\t *\n\t * @param runtime - data store runtime the new PactMap belongs to\n\t * @param id - optional name of the PactMap\n\t * @returns newly created PactMap (but not attached yet)\n\t */\n\tpublic static create(runtime: IFluidDataStoreRuntime, id?: string): PactMap {\n\t\treturn runtime.createChannel(id, PactMapFactory.Type) as PactMap;\n\t}\n\n\t/**\n\t * Get a factory for PactMap to register with the data store.\n\t *\n\t * @returns a factory that creates and loads PactMaps\n\t */\n\tpublic static getFactory(): IChannelFactory {\n\t\treturn new PactMapFactory();\n\t}\n\n\tprivate readonly values = new Map<string, Pact<T>>();\n\n\tprivate readonly incomingOp: EventEmitter = new EventEmitter();\n\n\t/**\n\t * Constructs a new PactMap. If the object is non-local an id and service interfaces will\n\t * be provided\n\t *\n\t * @param runtime - data store runtime the PactMap belongs to\n\t * @param id - optional name of the PactMap\n\t */\n\tpublic constructor(\n\t\tid: string,\n\t\truntime: IFluidDataStoreRuntime,\n\t\tattributes: IChannelAttributes,\n\t) {\n\t\tsuper(id, runtime, attributes, \"fluid_pactMap_\");\n\n\t\tthis.incomingOp.on(\"set\", this.handleIncomingSet);\n\t\tthis.incomingOp.on(\"accept\", this.handleIncomingAccept);\n\n\t\tthis.runtime.getQuorum().on(\"removeMember\", this.handleQuorumRemoveMember);\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.get}\n\t */\n\tpublic get(key: string): T | undefined {\n\t\treturn this.values.get(key)?.accepted?.value;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.getWithDetails}\n\t */\n\tpublic getWithDetails(key: string): IAcceptedPact<T> | undefined {\n\t\t// Note: We return type `IAcceptedPact` instead of `IAcceptedPactInternal` since we may want to diverge\n\t\t// the interfaces in the future.\n\t\tconst acceptedPact = this.values.get(key)?.accepted;\n\t\tif (acceptedPact === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tvalue: acceptedPact.value,\n\t\t\tacceptedSequenceNumber: acceptedPact.sequenceNumber,\n\t\t};\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.isPending}\n\t */\n\tpublic isPending(key: string): boolean {\n\t\treturn this.values.get(key)?.pending !== undefined;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.getPending}\n\t */\n\tpublic getPending(key: string): T | undefined {\n\t\treturn this.values.get(key)?.pending?.value;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.set}\n\t */\n\tpublic set(key: string, value: T | undefined): void {\n\t\tconst currentValue = this.values.get(key);\n\t\t// Early-exit if we can't submit a valid proposal (there's already a pending proposal)\n\t\tif (currentValue?.pending !== undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If not attached, we basically pretend we got an ack immediately.\n\t\tif (!this.isAttached()) {\n\t\t\t// Queueing as a microtask to permit callers to complete their callstacks before the result of the set\n\t\t\t// takes effect. This more closely resembles the pattern in the attached state, where the ack will not\n\t\t\t// be received synchronously.\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthis.handleIncomingSet(key, value, 0 /* refSeq */, 0 /* setSequenceNumber */);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst setOp: IPactMapSetOperation<T> = {\n\t\t\ttype: \"set\",\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\trefSeq: this.runtime.deltaManager.lastSequenceNumber,\n\t\t};\n\n\t\tthis.submitLocalMessage(setOp);\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.delete}\n\t */\n\tpublic delete(key: string): void {\n\t\tconst currentValue = this.values.get(key);\n\t\t// Early-exit if:\n\t\tif (\n\t\t\t// there's nothing to delete\n\t\t\tcurrentValue === undefined ||\n\t\t\t// if something is pending (and so our proposal won't be valid)\n\t\t\tcurrentValue.pending !== undefined ||\n\t\t\t// or if the accepted value is undefined which is equivalent to already being deleted\n\t\t\tcurrentValue.accepted.value === undefined\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.set(key, undefined);\n\t}\n\n\t/**\n\t * Get a point-in-time list of clients who must sign off on values coming in for them to move from \"pending\" to\n\t * \"accepted\" state. This list is finalized for a value at the moment it goes pending (i.e. if more clients\n\t * join later, they are not added to the list of signoffs).\n\t * @returns The list of clientIds for clients who must sign off to accept the incoming pending value\n\t */\n\tprivate getSignoffClients(): string[] {\n\t\t// If detached, we don't need anyone to sign off. Otherwise, we need all currently connected clients.\n\t\treturn this.isAttached() ? [...this.runtime.getQuorum().getMembers().keys()] : [];\n\t}\n\n\tprivate readonly handleIncomingSet = (\n\t\tkey: string,\n\t\tvalue: T | undefined,\n\t\trefSeq: number,\n\t\tsetSequenceNumber: number,\n\t): void => {\n\t\tconst currentValue = this.values.get(key);\n\t\t// We use a consensus-like approach here, so a proposal is valid if the value is unset or if there is no\n\t\t// pending change and it was made with knowledge of the most recently accepted value. We'll drop invalid\n\t\t// proposals on the ground.\n\t\tconst proposalValid =\n\t\t\tcurrentValue === undefined ||\n\t\t\t(currentValue.pending === undefined && currentValue.accepted.sequenceNumber <= refSeq);\n\t\tif (!proposalValid) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst accepted = currentValue?.accepted;\n\n\t\t// We expect signoffs from all connected clients at the time the set was sequenced (including the client who\n\t\t// sent the set).\n\t\tconst expectedSignoffs = this.getSignoffClients();\n\n\t\tconst newPact: Pact<T> = {\n\t\t\taccepted,\n\t\t\tpending: {\n\t\t\t\tvalue,\n\t\t\t\texpectedSignoffs,\n\t\t\t},\n\t\t};\n\n\t\tthis.values.set(key, newPact);\n\n\t\tthis.emit(\"pending\", key);\n\n\t\tif (expectedSignoffs.length === 0) {\n\t\t\t// At least the submitting client should be amongst the expectedSignoffs, but keeping this check around\n\t\t\t// as extra protection and in case we bring back the \"submitting client implicitly accepts\" optimization.\n\t\t\tthis.values.set(key, {\n\t\t\t\taccepted: { value, sequenceNumber: setSequenceNumber },\n\t\t\t\tpending: undefined,\n\t\t\t});\n\t\t\tthis.emit(\"accepted\", key);\n\t\t} else if (\n\t\t\tthis.runtime.clientId !== undefined &&\n\t\t\texpectedSignoffs.includes(this.runtime.clientId)\n\t\t) {\n\t\t\t// Emit an accept upon a new key entering pending state if our accept is expected.\n\t\t\tconst acceptOp: IPactMapAcceptOperation = {\n\t\t\t\ttype: \"accept\",\n\t\t\t\tkey,\n\t\t\t};\n\t\t\tthis.submitLocalMessage(acceptOp);\n\t\t}\n\t};\n\n\tprivate readonly handleIncomingAccept = (\n\t\tkey: string,\n\t\tclientId: string,\n\t\tsequenceNumber: number,\n\t): void => {\n\t\tconst pending = this.values.get(key)?.pending;\n\t\t// We don't resubmit accepts on reconnect so this should only run for expected accepts.\n\t\tassert(pending !== undefined, 0x2f8 /* Unexpected accept op, nothing pending */);\n\t\tassert(\n\t\t\tpending.expectedSignoffs.includes(clientId),\n\t\t\t0x2f9 /* Unexpected accept op, client not in expectedSignoffs */,\n\t\t);\n\n\t\t// Remove the client from the expected signoffs\n\t\tpending.expectedSignoffs = pending.expectedSignoffs.filter(\n\t\t\t(expectedClientId) => expectedClientId !== clientId,\n\t\t);\n\n\t\tif (pending.expectedSignoffs.length === 0) {\n\t\t\t// The pending value has settled\n\t\t\tthis.values.set(key, {\n\t\t\t\taccepted: { value: pending.value, sequenceNumber },\n\t\t\t\tpending: undefined,\n\t\t\t});\n\t\t\tthis.emit(\"accepted\", key);\n\t\t}\n\t};\n\n\tprivate readonly handleQuorumRemoveMember = (clientId: string): void => {\n\t\tfor (const [key, { pending }] of this.values) {\n\t\t\tif (pending !== undefined) {\n\t\t\t\tpending.expectedSignoffs = pending.expectedSignoffs.filter(\n\t\t\t\t\t(expectedClientId) => expectedClientId !== clientId,\n\t\t\t\t);\n\n\t\t\t\tif (pending.expectedSignoffs.length === 0) {\n\t\t\t\t\t// The pending value has settled\n\t\t\t\t\tconst clientLeaveSequenceNumber = this.runtime.deltaManager.lastSequenceNumber;\n\t\t\t\t\tthis.values.set(key, {\n\t\t\t\t\t\taccepted: {\n\t\t\t\t\t\t\tvalue: pending.value,\n\t\t\t\t\t\t\t// The sequence number of the ClientLeave message.\n\t\t\t\t\t\t\tsequenceNumber: clientLeaveSequenceNumber,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpending: undefined,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"accepted\", key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Create a summary for the PactMap\n\t *\n\t * @returns the summary of the current state of the PactMap\n\t * @internal\n\t */\n\tprotected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats {\n\t\tconst allEntries = [...this.values.entries()];\n\t\treturn createSingleBlobSummary(snapshotFileName, JSON.stringify(allEntries));\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}\n\t * @internal\n\t */\n\tprotected async loadCore(storage: IChannelStorageService): Promise<void> {\n\t\tconst content = await readAndParse<[string, Pact<T>][]>(storage, snapshotFileName);\n\t\tfor (const [key, value] of content) {\n\t\t\tthis.values.set(key, value);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}\n\t * @internal\n\t */\n\tprotected initializeLocalCore(): void {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}\n\t * @internal\n\t */\n\tprotected onDisconnect(): void {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}\n\t * @internal\n\t */\n\tprotected reSubmitCore(content: unknown, localOpMetadata: unknown): void {\n\t\tconst pactMapOp = content as IPactMapOperation<T>;\n\t\t// Filter out accept messages - if we're coming back from a disconnect, our acceptance is never required\n\t\t// because we're implicitly removed from the list of expected accepts.\n\t\tif (pactMapOp.type === \"accept\") {\n\t\t\treturn;\n\t\t}\n\n\t\t// Filter out set messages that have no chance of being accepted because there's another value pending\n\t\t// or another value was accepted while we were disconnected.\n\t\tconst currentValue = this.values.get(pactMapOp.key);\n\t\tif (\n\t\t\tcurrentValue !== undefined &&\n\t\t\t(currentValue.pending !== undefined ||\n\t\t\t\tpactMapOp.refSeq < currentValue.accepted?.sequenceNumber)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise we can resubmit\n\t\tthis.submitLocalMessage(pactMapOp, localOpMetadata);\n\t}\n\n\t/**\n\t * Process a PactMap operation\n\t *\n\t * @param message - the message to prepare\n\t * @param local - whether the message was sent by the local client\n\t * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.\n\t * For messages from a remote client, this will be undefined.\n\t * @internal\n\t */\n\tprotected processCore(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n\t\tif (message.type === MessageType.Operation) {\n\t\t\tconst op = message.contents as IPactMapOperation<T>;\n\n\t\t\tswitch (op.type) {\n\t\t\t\tcase \"set\": {\n\t\t\t\t\tthis.incomingOp.emit(\n\t\t\t\t\t\t\"set\",\n\t\t\t\t\t\top.key,\n\t\t\t\t\t\top.value,\n\t\t\t\t\t\top.refSeq,\n\t\t\t\t\t\tmessage.sequenceNumber,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"accept\": {\n\t\t\t\t\tthis.incomingOp.emit(\n\t\t\t\t\t\t\"accept\",\n\t\t\t\t\t\top.key,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t\tmessage.sequenceNumber,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault: {\n\t\t\t\t\tthrow new Error(\"Unknown operation\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic applyStashedOp(): void {\n\t\tthrow new Error(\"not implemented\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"pactMap.mjs","sourceRoot":"","sources":["../src/pactMap.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable unicorn/numeric-separators-style */\n\n// False positive: this is an import from the `events` package, not from Node.\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport { EventEmitter } from \"events\";\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { type ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport {\n\ttype IChannelAttributes,\n\ttype IFluidDataStoreRuntime,\n\ttype IChannelStorageService,\n\ttype IChannelFactory,\n} from \"@fluidframework/datastore-definitions\";\nimport { type ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { readAndParse } from \"@fluidframework/driver-utils\";\nimport {\n\tcreateSingleBlobSummary,\n\ttype IFluidSerializer,\n\tSharedObject,\n} from \"@fluidframework/shared-object-base\";\nimport { PactMapFactory } from \"./pactMapFactory\";\nimport { type IAcceptedPact, type IPactMap, type IPactMapEvents } from \"./interfaces\";\n\n/**\n * The accepted pact information, if any.\n */\ninterface IAcceptedPactInternal<T> {\n\t/**\n\t * The accepted value of the given type or undefined (typically in case of delete).\n\t */\n\tvalue: T | undefined;\n\n\t/**\n\t * The sequence number when the value was accepted, which will normally coincide with one of two possibilities:\n\t * - The sequence number of the \"accept\" op from the final client we expected signoff from\n\t * - The sequence number of the ClientLeave of the final client we expected signoff from\n\t *\n\t * For values set in detached state, it will be 0.\n\t */\n\tsequenceNumber: number;\n}\n\n/**\n * The pending pact information, if any.\n */\ninterface IPendingPact<T> {\n\t/**\n\t * The pending value of the given type or undefined (typically in case of delete).\n\t */\n\tvalue: T | undefined;\n\t/**\n\t * The list of clientIds that we expect \"accept\" ops from. Clients are also removed from this list if they\n\t * disconnect without accepting. When this list empties, the pending value transitions to accepted.\n\t */\n\texpectedSignoffs: string[];\n}\n\n/**\n * Internal format of the values stored in the PactMap.\n */\ntype Pact<T> =\n\t| { accepted: IAcceptedPactInternal<T>; pending: undefined }\n\t| { accepted: undefined; pending: IPendingPact<T> }\n\t| { accepted: IAcceptedPactInternal<T>; pending: IPendingPact<T> };\n\n/**\n * PactMap operation formats\n */\ninterface IPactMapSetOperation<T> {\n\ttype: \"set\";\n\tkey: string;\n\tvalue: T | undefined;\n\n\t/**\n\t * A \"set\" is only valid if it is made with knowledge of the most-recent accepted proposal - its reference\n\t * sequence number is greater than or equal to the sequence number when that prior value was accepted.\n\t *\n\t * However, we can't trust the built-in referenceSequenceNumber of the op because of resubmit on reconnect,\n\t * which will update the referenceSequenceNumber on our behalf.\n\t *\n\t * Instead we need to separately stamp the real reference sequence number on the op itself.\n\t */\n\trefSeq: number;\n}\n\ninterface IPactMapAcceptOperation {\n\ttype: \"accept\";\n\tkey: string;\n}\n\ntype IPactMapOperation<T> = IPactMapSetOperation<T> | IPactMapAcceptOperation;\n\nconst snapshotFileName = \"header\";\n\n/**\n * The PactMap distributed data structure provides key/value storage with a cautious conflict resolution strategy.\n * This strategy optimizes for all clients being aware of the change prior to considering the value as accepted.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * To create a `PactMap`, call the static create method:\n *\n * ```typescript\n * const pactMap = PactMap.create(this.runtime, id);\n * ```\n *\n * ### Usage\n *\n * Setting and reading values is somewhat similar to a `SharedMap`. However, because the acceptance strategy\n * cannot be resolved until other clients have witnessed the set, the new value will only be reflected in the data\n * after the consensus is reached.\n *\n * ```typescript\n * pactMap.on(\"pending\", (key: string) => {\n * console.log(pactMap.getPending(key));\n * });\n * pactMap.on(\"accepted\", (key: string) => {\n * console.log(pactMap.get(key));\n * });\n * pactMap.set(\"myKey\", \"myValue\");\n *\n * // Reading from the pact map prior to the async operation's completion will still return the old value.\n * console.log(pactMap.get(\"myKey\"));\n * ```\n *\n * The acceptance process has two stages. When an op indicating a client's attempt to set a value is sequenced,\n * we first verify that it was set with knowledge of the most recently accepted value (consensus-like FWW). If it\n * meets this bar, then the value is \"pending\". During this time, clients may observe the pending value and act\n * upon it, but should be aware that not all other clients may have witnessed the value yet. Once all clients\n * that were connected at the time of the value being set have explicitly acknowledged the new value, the value\n * becomes \"accepted\". Once the value is accepted, it once again becomes possible to set the value, again with\n * consensus-like FWW resolution.\n *\n * Since all connected clients must explicitly accept the new value, it is important that all connected clients\n * have the PactMap loaded, including e.g. the summarizing client. Otherwise, those clients who have not loaded\n * the PactMap will not be responding to proposals and delay their acceptance (until they disconnect, which implicitly\n * removes them from consideration). The easiest way to ensure all clients load the PactMap is to instantiate it\n * as part of instantiating the IRuntime for the container (containerHasInitialized if using Aqueduct).\n *\n * ### Eventing\n *\n * `PactMap` is an `EventEmitter`, and will emit events when a new value is accepted for a key.\n *\n * ```typescript\n * pactMap.on(\"accept\", (key: string) => {\n * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);\n * });\n * ```\n * @internal\n */\nexport class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implements IPactMap<T> {\n\t/**\n\t * Create a new PactMap\n\t *\n\t * @param runtime - data store runtime the new PactMap belongs to\n\t * @param id - optional name of the PactMap\n\t * @returns newly created PactMap (but not attached yet)\n\t */\n\tpublic static create(runtime: IFluidDataStoreRuntime, id?: string): PactMap {\n\t\treturn runtime.createChannel(id, PactMapFactory.Type) as PactMap;\n\t}\n\n\t/**\n\t * Get a factory for PactMap to register with the data store.\n\t *\n\t * @returns a factory that creates and loads PactMaps\n\t */\n\tpublic static getFactory(): IChannelFactory {\n\t\treturn new PactMapFactory();\n\t}\n\n\tprivate readonly values = new Map<string, Pact<T>>();\n\n\tprivate readonly incomingOp: EventEmitter = new EventEmitter();\n\n\t/**\n\t * Constructs a new PactMap. If the object is non-local an id and service interfaces will\n\t * be provided\n\t *\n\t * @param runtime - data store runtime the PactMap belongs to\n\t * @param id - optional name of the PactMap\n\t */\n\tpublic constructor(\n\t\tid: string,\n\t\truntime: IFluidDataStoreRuntime,\n\t\tattributes: IChannelAttributes,\n\t) {\n\t\tsuper(id, runtime, attributes, \"fluid_pactMap_\");\n\n\t\tthis.incomingOp.on(\"set\", this.handleIncomingSet);\n\t\tthis.incomingOp.on(\"accept\", this.handleIncomingAccept);\n\n\t\tthis.runtime.getQuorum().on(\"removeMember\", this.handleQuorumRemoveMember);\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.get}\n\t */\n\tpublic get(key: string): T | undefined {\n\t\treturn this.values.get(key)?.accepted?.value;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.getWithDetails}\n\t */\n\tpublic getWithDetails(key: string): IAcceptedPact<T> | undefined {\n\t\t// Note: We return type `IAcceptedPact` instead of `IAcceptedPactInternal` since we may want to diverge\n\t\t// the interfaces in the future.\n\t\tconst acceptedPact = this.values.get(key)?.accepted;\n\t\tif (acceptedPact === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tvalue: acceptedPact.value,\n\t\t\tacceptedSequenceNumber: acceptedPact.sequenceNumber,\n\t\t};\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.isPending}\n\t */\n\tpublic isPending(key: string): boolean {\n\t\treturn this.values.get(key)?.pending !== undefined;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.getPending}\n\t */\n\tpublic getPending(key: string): T | undefined {\n\t\treturn this.values.get(key)?.pending?.value;\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.set}\n\t */\n\tpublic set(key: string, value: T | undefined): void {\n\t\tconst currentValue = this.values.get(key);\n\t\t// Early-exit if we can't submit a valid proposal (there's already a pending proposal)\n\t\tif (currentValue?.pending !== undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If not attached, we basically pretend we got an ack immediately.\n\t\tif (!this.isAttached()) {\n\t\t\t// Queueing as a microtask to permit callers to complete their callstacks before the result of the set\n\t\t\t// takes effect. This more closely resembles the pattern in the attached state, where the ack will not\n\t\t\t// be received synchronously.\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthis.handleIncomingSet(key, value, 0 /* refSeq */, 0 /* setSequenceNumber */);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst setOp: IPactMapSetOperation<T> = {\n\t\t\ttype: \"set\",\n\t\t\tkey,\n\t\t\tvalue,\n\t\t\trefSeq: this.runtime.deltaManager.lastSequenceNumber,\n\t\t};\n\n\t\tthis.submitLocalMessage(setOp);\n\t}\n\n\t/**\n\t * {@inheritDoc IPactMap.delete}\n\t */\n\tpublic delete(key: string): void {\n\t\tconst currentValue = this.values.get(key);\n\t\t// Early-exit if:\n\t\tif (\n\t\t\t// there's nothing to delete\n\t\t\tcurrentValue === undefined ||\n\t\t\t// if something is pending (and so our proposal won't be valid)\n\t\t\tcurrentValue.pending !== undefined ||\n\t\t\t// or if the accepted value is undefined which is equivalent to already being deleted\n\t\t\tcurrentValue.accepted.value === undefined\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.set(key, undefined);\n\t}\n\n\t/**\n\t * Get a point-in-time list of clients who must sign off on values coming in for them to move from \"pending\" to\n\t * \"accepted\" state. This list is finalized for a value at the moment it goes pending (i.e. if more clients\n\t * join later, they are not added to the list of signoffs).\n\t * @returns The list of clientIds for clients who must sign off to accept the incoming pending value\n\t */\n\tprivate getSignoffClients(): string[] {\n\t\t// If detached, we don't need anyone to sign off. Otherwise, we need all currently connected clients.\n\t\treturn this.isAttached() ? [...this.runtime.getQuorum().getMembers().keys()] : [];\n\t}\n\n\tprivate readonly handleIncomingSet = (\n\t\tkey: string,\n\t\tvalue: T | undefined,\n\t\trefSeq: number,\n\t\tsetSequenceNumber: number,\n\t): void => {\n\t\tconst currentValue = this.values.get(key);\n\t\t// We use a consensus-like approach here, so a proposal is valid if the value is unset or if there is no\n\t\t// pending change and it was made with knowledge of the most recently accepted value. We'll drop invalid\n\t\t// proposals on the ground.\n\t\tconst proposalValid =\n\t\t\tcurrentValue === undefined ||\n\t\t\t(currentValue.pending === undefined && currentValue.accepted.sequenceNumber <= refSeq);\n\t\tif (!proposalValid) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst accepted = currentValue?.accepted;\n\n\t\t// We expect signoffs from all connected clients at the time the set was sequenced (including the client who\n\t\t// sent the set).\n\t\tconst expectedSignoffs = this.getSignoffClients();\n\n\t\tconst newPact: Pact<T> = {\n\t\t\taccepted,\n\t\t\tpending: {\n\t\t\t\tvalue,\n\t\t\t\texpectedSignoffs,\n\t\t\t},\n\t\t};\n\n\t\tthis.values.set(key, newPact);\n\n\t\tthis.emit(\"pending\", key);\n\n\t\tif (expectedSignoffs.length === 0) {\n\t\t\t// At least the submitting client should be amongst the expectedSignoffs, but keeping this check around\n\t\t\t// as extra protection and in case we bring back the \"submitting client implicitly accepts\" optimization.\n\t\t\tthis.values.set(key, {\n\t\t\t\taccepted: { value, sequenceNumber: setSequenceNumber },\n\t\t\t\tpending: undefined,\n\t\t\t});\n\t\t\tthis.emit(\"accepted\", key);\n\t\t} else if (\n\t\t\tthis.runtime.clientId !== undefined &&\n\t\t\texpectedSignoffs.includes(this.runtime.clientId)\n\t\t) {\n\t\t\t// Emit an accept upon a new key entering pending state if our accept is expected.\n\t\t\tconst acceptOp: IPactMapAcceptOperation = {\n\t\t\t\ttype: \"accept\",\n\t\t\t\tkey,\n\t\t\t};\n\t\t\tthis.submitLocalMessage(acceptOp);\n\t\t}\n\t};\n\n\tprivate readonly handleIncomingAccept = (\n\t\tkey: string,\n\t\tclientId: string,\n\t\tsequenceNumber: number,\n\t): void => {\n\t\tconst pending = this.values.get(key)?.pending;\n\t\t// We don't resubmit accepts on reconnect so this should only run for expected accepts.\n\t\tassert(pending !== undefined, 0x2f8 /* Unexpected accept op, nothing pending */);\n\t\tassert(\n\t\t\tpending.expectedSignoffs.includes(clientId),\n\t\t\t0x2f9 /* Unexpected accept op, client not in expectedSignoffs */,\n\t\t);\n\n\t\t// Remove the client from the expected signoffs\n\t\tpending.expectedSignoffs = pending.expectedSignoffs.filter(\n\t\t\t(expectedClientId) => expectedClientId !== clientId,\n\t\t);\n\n\t\tif (pending.expectedSignoffs.length === 0) {\n\t\t\t// The pending value has settled\n\t\t\tthis.values.set(key, {\n\t\t\t\taccepted: { value: pending.value, sequenceNumber },\n\t\t\t\tpending: undefined,\n\t\t\t});\n\t\t\tthis.emit(\"accepted\", key);\n\t\t}\n\t};\n\n\tprivate readonly handleQuorumRemoveMember = (clientId: string): void => {\n\t\tfor (const [key, { pending }] of this.values) {\n\t\t\tif (pending !== undefined) {\n\t\t\t\tpending.expectedSignoffs = pending.expectedSignoffs.filter(\n\t\t\t\t\t(expectedClientId) => expectedClientId !== clientId,\n\t\t\t\t);\n\n\t\t\t\tif (pending.expectedSignoffs.length === 0) {\n\t\t\t\t\t// The pending value has settled\n\t\t\t\t\tconst clientLeaveSequenceNumber = this.runtime.deltaManager.lastSequenceNumber;\n\t\t\t\t\tthis.values.set(key, {\n\t\t\t\t\t\taccepted: {\n\t\t\t\t\t\t\tvalue: pending.value,\n\t\t\t\t\t\t\t// The sequence number of the ClientLeave message.\n\t\t\t\t\t\t\tsequenceNumber: clientLeaveSequenceNumber,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpending: undefined,\n\t\t\t\t\t});\n\t\t\t\t\tthis.emit(\"accepted\", key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Create a summary for the PactMap\n\t *\n\t * @returns the summary of the current state of the PactMap\n\t */\n\tprotected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats {\n\t\tconst allEntries = [...this.values.entries()];\n\t\treturn createSingleBlobSummary(snapshotFileName, JSON.stringify(allEntries));\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}\n\t */\n\tprotected async loadCore(storage: IChannelStorageService): Promise<void> {\n\t\tconst content = await readAndParse<[string, Pact<T>][]>(storage, snapshotFileName);\n\t\tfor (const [key, value] of content) {\n\t\t\tthis.values.set(key, value);\n\t\t}\n\t}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}\n\t */\n\tprotected initializeLocalCore(): void {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}\n\t */\n\tprotected onDisconnect(): void {}\n\n\t/**\n\t * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}\n\t */\n\tprotected reSubmitCore(content: unknown, localOpMetadata: unknown): void {\n\t\tconst pactMapOp = content as IPactMapOperation<T>;\n\t\t// Filter out accept messages - if we're coming back from a disconnect, our acceptance is never required\n\t\t// because we're implicitly removed from the list of expected accepts.\n\t\tif (pactMapOp.type === \"accept\") {\n\t\t\treturn;\n\t\t}\n\n\t\t// Filter out set messages that have no chance of being accepted because there's another value pending\n\t\t// or another value was accepted while we were disconnected.\n\t\tconst currentValue = this.values.get(pactMapOp.key);\n\t\tif (\n\t\t\tcurrentValue !== undefined &&\n\t\t\t(currentValue.pending !== undefined ||\n\t\t\t\tpactMapOp.refSeq < currentValue.accepted?.sequenceNumber)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise we can resubmit\n\t\tthis.submitLocalMessage(pactMapOp, localOpMetadata);\n\t}\n\n\t/**\n\t * Process a PactMap operation\n\t *\n\t * @param message - the message to prepare\n\t * @param local - whether the message was sent by the local client\n\t * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.\n\t * For messages from a remote client, this will be undefined.\n\t */\n\tprotected processCore(\n\t\tmessage: ISequencedDocumentMessage,\n\t\tlocal: boolean,\n\t\tlocalOpMetadata: unknown,\n\t): void {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n\t\tif (message.type === MessageType.Operation) {\n\t\t\tconst op = message.contents as IPactMapOperation<T>;\n\n\t\t\tswitch (op.type) {\n\t\t\t\tcase \"set\": {\n\t\t\t\t\tthis.incomingOp.emit(\n\t\t\t\t\t\t\"set\",\n\t\t\t\t\t\top.key,\n\t\t\t\t\t\top.value,\n\t\t\t\t\t\top.refSeq,\n\t\t\t\t\t\tmessage.sequenceNumber,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"accept\": {\n\t\t\t\t\tthis.incomingOp.emit(\n\t\t\t\t\t\t\"accept\",\n\t\t\t\t\t\top.key,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t\tmessage.sequenceNumber,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault: {\n\t\t\t\t\tthrow new Error(\"Unknown operation\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic applyStashedOp(): void {\n\t\tthrow new Error(\"not implemented\");\n\t}\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { type IChannelAttributes, type IFluidDataStoreRuntime, type IChannelServices, type IChannelFactory } from "@fluidframework/datastore-definitions";
6
- import { type IPactMap } from "./interfaces";
6
+ import { type IPactMap } from "./interfaces.mjs";
7
7
  /**
8
8
  * The factory that produces the PactMap
9
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"pactMapFactory.d.ts","sourceRoot":"","sources":["../src/pactMapFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACrD,gBAAuB,IAAI,gDAAgD;IAE3E,gBAAuB,UAAU,EAAE,kBAAkB,CAInD;IAEF,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,UAAU,IAAI,kBAAkB,CAE1C;IAED;;OAEG;IACU,IAAI,CAChB,OAAO,EAAE,sBAAsB,EAC/B,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,kBAAkB,GAC5B,OAAO,CAAC,QAAQ,CAAC;IAMb,MAAM,CAAC,QAAQ,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ;CAKrE"}
1
+ {"version":3,"file":"pactMapFactory.d.ts","sourceRoot":"","sources":["../src/pactMapFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EACN,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,uCAAuC;OAEvC,EAAE,KAAK,QAAQ,EAAE;AAGxB;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACrD,gBAAuB,IAAI,gDAAgD;IAE3E,gBAAuB,UAAU,EAAE,kBAAkB,CAInD;IAEF,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,UAAU,IAAI,kBAAkB,CAE1C;IAED;;OAEG;IACU,IAAI,CAChB,OAAO,EAAE,sBAAsB,EAC/B,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,kBAAkB,GAC5B,OAAO,CAAC,QAAQ,CAAC;IAMb,MAAM,CAAC,QAAQ,EAAE,sBAAsB,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ;CAKrE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/pact-map",
3
- "version": "2.0.0-internal.7.3.0",
3
+ "version": "2.0.0-internal.7.4.1",
4
4
  "description": "Distributed data structure for key-value pairs using pact consensus",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -11,18 +11,6 @@
11
11
  "license": "MIT",
12
12
  "author": "Microsoft and contributors",
13
13
  "sideEffects": false,
14
- "exports": {
15
- ".": {
16
- "import": {
17
- "types": "./lib/index.d.ts",
18
- "default": "./lib/index.mjs"
19
- },
20
- "require": {
21
- "types": "./dist/index.d.ts",
22
- "default": "./dist/index.cjs"
23
- }
24
- }
25
- },
26
14
  "main": "dist/index.cjs",
27
15
  "module": "lib/index.mjs",
28
16
  "types": "dist/index.d.ts",
@@ -47,26 +35,26 @@
47
35
  "temp-directory": "nyc/.nyc_output"
48
36
  },
49
37
  "dependencies": {
50
- "@fluidframework/core-interfaces": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
51
- "@fluidframework/core-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
52
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
53
- "@fluidframework/driver-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
38
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
39
+ "@fluidframework/core-utils": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
40
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
41
+ "@fluidframework/driver-utils": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
54
42
  "@fluidframework/protocol-definitions": "^3.0.0",
55
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
56
- "@fluidframework/shared-object-base": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
43
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
44
+ "@fluidframework/shared-object-base": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
57
45
  "events": "^3.1.0"
58
46
  },
59
47
  "devDependencies": {
60
- "@fluid-private/test-dds-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
48
+ "@fluid-private/test-dds-utils": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
61
49
  "@fluidframework/build-common": "^2.0.3",
62
50
  "@fluidframework/build-tools": "^0.28.0",
63
51
  "@fluidframework/eslint-config-fluid": "^3.1.0",
64
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
65
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
52
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
53
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.7.4.1 <2.0.0-internal.7.5.0",
66
54
  "@microsoft/api-extractor": "^7.38.3",
67
55
  "@types/events": "^3.0.0",
68
56
  "@types/mocha": "^9.1.1",
69
- "@types/node": "^16.18.38",
57
+ "@types/node": "^18.19.0",
70
58
  "c8": "^7.7.1",
71
59
  "copyfiles": "^2.4.1",
72
60
  "cross-env": "^7.0.3",
@@ -108,15 +96,16 @@
108
96
  "build:esnext": "tsc-multi --config ../../../common/build/build-common/tsc-multi.esm.json",
109
97
  "build:genver": "gen-version",
110
98
  "build:test": "tsc-multi --config ./tsc-multi.test.json",
99
+ "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
111
100
  "ci:build:docs": "api-extractor run",
112
101
  "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
113
102
  "eslint": "eslint --format stylish src",
114
103
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
115
104
  "format": "npm run prettier:fix",
116
- "lint": "npm run prettier && npm run eslint",
105
+ "lint": "npm run prettier && npm run check:release-tags && npm run eslint",
117
106
  "lint:fix": "npm run prettier:fix && npm run eslint:fix",
118
- "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
119
- "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
107
+ "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
108
+ "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
120
109
  "test": "npm run test:mocha",
121
110
  "test:coverage": "c8 npm test",
122
111
  "test:mocha": "mocha --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup",
package/src/interfaces.ts CHANGED
@@ -7,8 +7,7 @@ import { type ISharedObject, type ISharedObjectEvents } from "@fluidframework/sh
7
7
 
8
8
  /**
9
9
  * Events emitted by {@link IPactMap}.
10
- *
11
- * @public
10
+ * @internal
12
11
  */
13
12
  export interface IPactMapEvents extends ISharedObjectEvents {
14
13
  /**
@@ -19,8 +18,7 @@ export interface IPactMapEvents extends ISharedObjectEvents {
19
18
 
20
19
  /**
21
20
  * Details of the accepted pact.
22
- *
23
- * @public
21
+ * @internal
24
22
  */
25
23
  export interface IAcceptedPact<T> {
26
24
  /**
@@ -44,8 +42,7 @@ export interface IAcceptedPact<T> {
44
42
  * 1. "pending" state where the proposal has been sequenced, but there are still outstanding acceptances
45
43
  * 2. "accepted" state where all clients who were connected at the time the proposal was made have either accepted
46
44
  * or disconnected.
47
- *
48
- * @public
45
+ * @internal
49
46
  */
50
47
  export interface IPactMap<T = unknown> extends ISharedObject<IPactMapEvents> {
51
48
  /**
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluid-experimental/pact-map";
9
- export const pkgVersion = "2.0.0-internal.7.3.0";
9
+ export const pkgVersion = "2.0.0-internal.7.4.1";
package/src/pactMap.ts CHANGED
@@ -155,8 +155,7 @@ const snapshotFileName = "header";
155
155
  * console.log(`New value was accepted for key: ${ key }, value: ${ pactMap.get(key) }`);
156
156
  * });
157
157
  * ```
158
- *
159
- * @public
158
+ * @internal
160
159
  */
161
160
  export class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implements IPactMap<T> {
162
161
  /**
@@ -414,7 +413,6 @@ export class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implement
414
413
  * Create a summary for the PactMap
415
414
  *
416
415
  * @returns the summary of the current state of the PactMap
417
- * @internal
418
416
  */
419
417
  protected summarizeCore(serializer: IFluidSerializer): ISummaryTreeWithStats {
420
418
  const allEntries = [...this.values.entries()];
@@ -423,7 +421,6 @@ export class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implement
423
421
 
424
422
  /**
425
423
  * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
426
- * @internal
427
424
  */
428
425
  protected async loadCore(storage: IChannelStorageService): Promise<void> {
429
426
  const content = await readAndParse<[string, Pact<T>][]>(storage, snapshotFileName);
@@ -434,19 +431,16 @@ export class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implement
434
431
 
435
432
  /**
436
433
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.initializeLocalCore}
437
- * @internal
438
434
  */
439
435
  protected initializeLocalCore(): void {}
440
436
 
441
437
  /**
442
438
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.onDisconnect}
443
- * @internal
444
439
  */
445
440
  protected onDisconnect(): void {}
446
441
 
447
442
  /**
448
443
  * {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.reSubmitCore}
449
- * @internal
450
444
  */
451
445
  protected reSubmitCore(content: unknown, localOpMetadata: unknown): void {
452
446
  const pactMapOp = content as IPactMapOperation<T>;
@@ -478,7 +472,6 @@ export class PactMap<T = unknown> extends SharedObject<IPactMapEvents> implement
478
472
  * @param local - whether the message was sent by the local client
479
473
  * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
480
474
  * For messages from a remote client, this will be undefined.
481
- * @internal
482
475
  */
483
476
  protected processCore(
484
477
  message: ISequencedDocumentMessage,