@fluidframework/presence 2.74.0-370705 → 2.80.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/dist/alpha.d.ts +1 -0
- package/dist/beta.d.ts +1 -0
- package/dist/exposedInternalTypes.d.ts +1 -1
- package/dist/exposedInternalTypes.d.ts.map +1 -1
- package/dist/exposedInternalTypes.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internalTypes.d.ts +6 -0
- package/dist/internalTypes.d.ts.map +1 -1
- package/dist/internalTypes.js.map +1 -1
- package/dist/latestMapValueManager.d.ts +33 -14
- package/dist/latestMapValueManager.d.ts.map +1 -1
- package/dist/latestMapValueManager.js +33 -16
- package/dist/latestMapValueManager.js.map +1 -1
- package/dist/legacy.alpha.d.ts +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/presenceDatastoreManager.d.ts +7 -11
- package/dist/presenceDatastoreManager.d.ts.map +1 -1
- package/dist/presenceDatastoreManager.js +11 -62
- package/dist/presenceDatastoreManager.js.map +1 -1
- package/dist/presenceManager.d.ts.map +1 -1
- package/dist/presenceManager.js +68 -23
- package/dist/presenceManager.js.map +1 -1
- package/dist/stateDatastore.d.ts +2 -2
- package/dist/stateDatastore.d.ts.map +1 -1
- package/dist/stateDatastore.js.map +1 -1
- package/dist/systemWorkspace.d.ts +2 -1
- package/dist/systemWorkspace.d.ts.map +1 -1
- package/dist/systemWorkspace.js +95 -42
- package/dist/systemWorkspace.js.map +1 -1
- package/lib/alpha.d.ts +1 -0
- package/lib/beta.d.ts +1 -0
- package/lib/exposedInternalTypes.d.ts +1 -1
- package/lib/exposedInternalTypes.d.ts.map +1 -1
- package/lib/exposedInternalTypes.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/internalTypes.d.ts +6 -0
- package/lib/internalTypes.d.ts.map +1 -1
- package/lib/internalTypes.js.map +1 -1
- package/lib/latestMapValueManager.d.ts +33 -14
- package/lib/latestMapValueManager.d.ts.map +1 -1
- package/lib/latestMapValueManager.js +33 -16
- package/lib/latestMapValueManager.js.map +1 -1
- package/lib/legacy.alpha.d.ts +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/presenceDatastoreManager.d.ts +7 -11
- package/lib/presenceDatastoreManager.d.ts.map +1 -1
- package/lib/presenceDatastoreManager.js +11 -62
- package/lib/presenceDatastoreManager.js.map +1 -1
- package/lib/presenceManager.d.ts.map +1 -1
- package/lib/presenceManager.js +64 -19
- package/lib/presenceManager.js.map +1 -1
- package/lib/stateDatastore.d.ts +2 -2
- package/lib/stateDatastore.d.ts.map +1 -1
- package/lib/stateDatastore.js.map +1 -1
- package/lib/systemWorkspace.d.ts +2 -1
- package/lib/systemWorkspace.d.ts.map +1 -1
- package/lib/systemWorkspace.js +95 -42
- package/lib/systemWorkspace.js.map +1 -1
- package/package.json +25 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAE1F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAe/D,OAAO,KAAK,EACX,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAoB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,7 @@ class ValueMapImpl {
|
|
|
51
51
|
forEach(callbackfn, thisArg) {
|
|
52
52
|
for (const [key, item] of objectEntries(this.value.items)) {
|
|
53
53
|
if (item.value !== undefined) {
|
|
54
|
+
// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast
|
|
54
55
|
callbackfn(asDeeplyReadonlyDeserializedJson(item.value), key, this);
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -78,18 +79,26 @@ class ValueMapImpl {
|
|
|
78
79
|
const keys = [];
|
|
79
80
|
for (const [key, item] of objectEntries(this.value.items)) {
|
|
80
81
|
if (item.value !== undefined) {
|
|
82
|
+
// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast
|
|
81
83
|
keys.push(key);
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
return keys[Symbol.iterator]();
|
|
85
87
|
}
|
|
86
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Simply returns true for all given string keys.
|
|
91
|
+
*/
|
|
92
|
+
function anyKeyIsValid(unvalidatedKey) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
87
95
|
class LatestMapValueManagerImpl {
|
|
88
|
-
constructor(key, datastore, value, controlSettings, validator) {
|
|
96
|
+
constructor(key, datastore, value, controlSettings, validator, isValidKey) {
|
|
89
97
|
this.key = key;
|
|
90
98
|
this.datastore = datastore;
|
|
91
99
|
this.value = value;
|
|
92
100
|
this.validator = validator;
|
|
101
|
+
this.isValidKey = isValidKey;
|
|
93
102
|
this.events = createEmitter();
|
|
94
103
|
this.controls = new OptionalBroadcastControl(controlSettings);
|
|
95
104
|
this.local = new ValueMapImpl(value, this.events, (updates) => {
|
|
@@ -127,7 +136,7 @@ class LatestMapValueManagerImpl {
|
|
|
127
136
|
}
|
|
128
137
|
const items = new Map();
|
|
129
138
|
for (const [key, item] of objectEntries(clientStateMap.items)) {
|
|
130
|
-
if (isValueRequiredState(item)) {
|
|
139
|
+
if (this.isValidKey(key) && isValueRequiredState(item)) {
|
|
131
140
|
items.set(key, {
|
|
132
141
|
value: createValidatedGetter(item, validator),
|
|
133
142
|
metadata: { revision: item.rev, timestamp: item.timestamp },
|
|
@@ -143,19 +152,17 @@ class LatestMapValueManagerImpl {
|
|
|
143
152
|
// New attendee - prepare new attendee state directory
|
|
144
153
|
{
|
|
145
154
|
rev: value.rev,
|
|
146
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- items entries can't be optional per https://github.com/microsoft/TypeScript/issues/42810; so forced cast
|
|
147
155
|
items: {},
|
|
148
156
|
});
|
|
149
157
|
// Accumulate individual update keys
|
|
150
|
-
const
|
|
158
|
+
const updatedKeyItemPairs = [];
|
|
151
159
|
for (const [key, item] of objectEntries(value.items)) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
updatedItemKeys.push(validKey);
|
|
160
|
+
const currentItem = currentState.items[key];
|
|
161
|
+
if (currentItem === undefined || currentItem.rev < item.rev) {
|
|
162
|
+
updatedKeyItemPairs.push([key, item]);
|
|
156
163
|
}
|
|
157
164
|
}
|
|
158
|
-
if (
|
|
165
|
+
if (updatedKeyItemPairs.length === 0) {
|
|
159
166
|
return [];
|
|
160
167
|
}
|
|
161
168
|
// Store updates
|
|
@@ -167,10 +174,13 @@ class LatestMapValueManagerImpl {
|
|
|
167
174
|
items: new Map(),
|
|
168
175
|
};
|
|
169
176
|
const postUpdateActions = [];
|
|
170
|
-
for (const key of
|
|
171
|
-
const item = value.items[key];
|
|
177
|
+
for (const [key, item] of updatedKeyItemPairs) {
|
|
172
178
|
const hadPriorValue = currentState.items[key]?.value;
|
|
173
179
|
currentState.items[key] = item;
|
|
180
|
+
// Prepare update events, but only for valid keys.
|
|
181
|
+
if (!this.isValidKey(key)) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
174
184
|
const metadata = {
|
|
175
185
|
revision: item.rev,
|
|
176
186
|
timestamp: item.timestamp,
|
|
@@ -197,7 +207,11 @@ class LatestMapValueManagerImpl {
|
|
|
197
207
|
}
|
|
198
208
|
}
|
|
199
209
|
this.datastore.update(this.key, attendeeId, currentState);
|
|
200
|
-
|
|
210
|
+
// Only emit remoteUpdated if there are any individual updates, which
|
|
211
|
+
// accounts for the case where all updates were for invalid keys.
|
|
212
|
+
if (postUpdateActions.length > 0) {
|
|
213
|
+
postUpdateActions.push(() => this.events.emit("remoteUpdated", allUpdates));
|
|
214
|
+
}
|
|
201
215
|
return postUpdateActions;
|
|
202
216
|
}
|
|
203
217
|
}
|
|
@@ -209,21 +223,24 @@ export const latestMap = (args) => {
|
|
|
209
223
|
const settings = args?.settings;
|
|
210
224
|
const initialValues = args?.local;
|
|
211
225
|
const validator = args?.validator;
|
|
226
|
+
const isKeyValid = args?.keyValidator ?? anyKeyIsValid;
|
|
212
227
|
const timestamp = Date.now();
|
|
213
228
|
const value = { rev: 0, items: {} };
|
|
214
229
|
// LatestMapRaw takes ownership of values within initialValues.
|
|
215
230
|
if (initialValues !== undefined) {
|
|
216
|
-
for (const key of
|
|
217
|
-
|
|
231
|
+
for (const [key, item] of objectEntries(initialValues)) {
|
|
232
|
+
// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast
|
|
233
|
+
const assumedValidKey = key;
|
|
234
|
+
value.items[assumedValidKey] = {
|
|
218
235
|
rev: 0,
|
|
219
236
|
timestamp,
|
|
220
|
-
value: toOpaqueJson(
|
|
237
|
+
value: toOpaqueJson(item),
|
|
221
238
|
};
|
|
222
239
|
}
|
|
223
240
|
}
|
|
224
241
|
const factory = (key, datastoreHandle) => ({
|
|
225
242
|
initialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },
|
|
226
|
-
manager: brandIVM(new LatestMapValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, settings, validator)),
|
|
243
|
+
manager: brandIVM(new LatestMapValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, settings, validator, isKeyValid)),
|
|
227
244
|
});
|
|
228
245
|
return Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });
|
|
229
246
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.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\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport type {\n\tDeepReadonly,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type {\n\tPostUpdateAction,\n\tValidatableOptionalState,\n\tValueManager,\n} from \"./internalTypes.js\";\nimport {\n\tasDeeplyReadonly,\n\tasDeeplyReadonlyDeserializedJson,\n\tisValueRequiredState,\n\tobjectEntries,\n\tobjectKeys,\n\ttoOpaqueJson,\n} from \"./internalUtils.js\";\nimport { createValidatedGetter } from \"./latestValueTypes.js\";\nimport type {\n\tLatestClientData,\n\tLatestData,\n\tLatestMetadata,\n\tProxiedValueAccessor,\n\tRawValueAccessor,\n\tStateSchemaValidator,\n\tValueAccessor,\n} from \"./latestValueTypes.js\";\nimport type { AttendeeId, Attendee, Presence, SpecificAttendee } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * Collection of validatable optional values in a \"map\" structure.\n *\n * @remarks\n * Validatable equivalent of {@link InternalTypes.MapValueState}.\n */\ninterface ValidatableMapValueState<T, Keys extends string | number> {\n\trev: number;\n\titems: {\n\t\t// Caution: any particular item may or may not exist\n\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t[name in Keys]: ValidatableOptionalState<T>;\n\t};\n}\n\n/**\n * Collection of latest known values for a specific {@link Attendee}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapClientData<\n\tT,\n\tKeys extends string | number,\n\tTValueAccessor extends ValueAccessor<T>,\n\tSpecificAttendeeId extends AttendeeId = AttendeeId,\n> {\n\t/**\n\t * Associated {@link Attendee}.\n\t */\n\tattendee: Attendee<SpecificAttendeeId>;\n\n\t/**\n\t * Map of items for the state.\n\t *\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestData<T, TValueAccessor>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapItemUpdatedClientData<\n\tT,\n\tK extends string | number,\n\tTValueAccessor extends ValueAccessor<T>,\n> extends LatestClientData<T, TValueAccessor> {\n\t/**\n\t * Key of the updated item.\n\t */\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapItemRemovedClientData<K extends string | number> {\n\t/**\n\t * Associated {@link Attendee}.\n\t */\n\tattendee: Attendee;\n\t/**\n\t * Key of the removed item.\n\t */\n\tkey: K;\n\t/**\n\t * Metadata associated with the removal of the item.\n\t */\n\tmetadata: LatestMetadata;\n}\n\n/**\n * Events from {@link LatestMapRaw}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapEvents<\n\tT,\n\tK extends string | number,\n\tTRemoteValueAccessor extends ValueAccessor<T> = ProxiedValueAccessor<T>,\n> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tremoteUpdated: (updates: LatestMapClientData<T, K, TRemoteValueAccessor>) => void;\n\n\t/**\n\t * Raised when specific item's value of remote client is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemUpdated: (\n\t\tupdatedItem: LatestMapItemUpdatedClientData<T, K, TRemoteValueAccessor>,\n\t) => void;\n\n\t/**\n\t * Raised when specific item of remote client is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n\n\t/**\n\t * Raised when specific local item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemUpdated: (updatedItem: {\n\t\tvalue: DeepReadonly<JsonSerializable<T>>;\n\t\tkey: K;\n\t}) => void;\n\n\t/**\n\t * Raised when specific local item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemRemoved: (removedItem: {\n\t\tkey: K;\n\t}) => void;\n}\n\n/**\n * Events from {@link LatestMapRaw}.\n *\n * @sealed\n * @beta\n */\nexport type LatestMapRawEvents<T, K extends string | number> = LatestMapEvents<\n\tT,\n\tK,\n\tRawValueAccessor<T>\n>;\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @beta\n */\nexport interface StateMap<K extends string | number, V> {\n\t/**\n\t * ${@link StateMap.delete}s all elements in the StateMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * Removes the element with the specified key from the StateMap, if it exists.\n\t *\n\t * @returns true if an element in the StateMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the StateMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns the element with the specified key from the StateMap, if it exists.\n\t *\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): DeepReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * Checks if an element with the specified key exists in the StateMap.\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the StateMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V>): this;\n\n\t/**\n\t * The number of elements in the StateMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<DeepReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string | number> implements StateMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T, K>,\n\t\tprivate readonly emitter: IEmitter<\n\t\t\tPick<LatestMapEvents<T, K, ValueAccessor<T>>, \"localItemUpdated\" | \"localItemRemoved\">\n\t\t>,\n\t\tprivate readonly localUpdate: (\n\t\t\tupdates: InternalTypes.MapValueState<\n\t\t\t\tT,\n\t\t\t\t// This should be `K`, but will only work if properties are optional.\n\t\t\t\tstring | number\n\t\t\t>,\n\t\t) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\t/**\n\t * Note: caller must ensure key exists in this.value.items.\n\t */\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\t// Caller is required to ensure key exists.\n\t\tconst item = this.value.items[key];\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t\tthis.emitter.emit(\"localItemRemoved\", { key });\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tcallbackfn(asDeeplyReadonlyDeserializedJson(item.value), key, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): DeepReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn asDeeplyReadonlyDeserializedJson(this.value.items[key]?.value);\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, inValue: JsonSerializable<T>): this {\n\t\tconst value = toOpaqueJson<T>(inValue);\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\tthis.emitter.emit(\"localItemUpdated\", { key, value: asDeeplyReadonly(inValue) });\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tkeys.push(key);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * State that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMap<\n\tT,\n\tKeys extends string | number = string | number,\n\tTRemoteAccessor extends ValueAccessor<T> = ProxiedValueAccessor<T>,\n> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for LatestMap.\n\t */\n\treadonly events: Listenable<LatestMapEvents<T, Keys, TRemoteAccessor>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: StateMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tgetRemotes(): IterableIterator<LatestMapClientData<T, Keys, TRemoteAccessor>>;\n\t/**\n\t * Array of {@link Attendee}s that have provided states.\n\t */\n\tgetStateAttendees(): Attendee[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tgetRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T, TRemoteAccessor>>;\n}\n\n/**\n * State that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport type LatestMapRaw<T, Keys extends string | number = string | number> = LatestMap<\n\tT,\n\tKeys,\n\tRawValueAccessor<T>\n>;\n\nclass LatestMapValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string | number = string | number,\n> implements\n\t\tLatestMapRaw<T, Keys>,\n\t\tLatestMap<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T, Keys>>>\n{\n\tpublic readonly events = createEmitter<LatestMapEvents<T, Keys, ValueAccessor<T>>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>,\n\t\t\tValidatableMapValueState<T, Keys>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T, Keys>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t\tprivate readonly validator: StateSchemaValidator<T> | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\tthis.events,\n\t\t\t(updates: InternalTypes.MapValueState<T, Keys>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic readonly local: StateMap<Keys, T>;\n\n\tpublic *getRemotes(): IterableIterator<LatestMapClientData<T, Keys, ValueAccessor<T>>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const attendeeId of objectKeys(allKnownStates.states)) {\n\t\t\tif (attendeeId !== allKnownStates.self) {\n\t\t\t\tconst attendee = this.datastore.presence.attendees.getAttendee(attendeeId);\n\t\t\t\tconst items = this.getRemote(attendee);\n\t\t\t\tyield { attendee, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getStateAttendees(): Attendee[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn objectKeys(allKnownStates.states)\n\t\t\t.filter((attendeeId) => attendeeId !== allKnownStates.self)\n\t\t\t.map((attendeeId) => this.datastore.presence.attendees.getAttendee(attendeeId));\n\t}\n\n\tpublic getRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T, ValueAccessor<T>>> {\n\t\tconst validator = this.validator;\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId = attendee.attendeeId;\n\t\tconst clientStateMap = allKnownStates.states[attendeeId];\n\t\tif (clientStateMap === undefined) {\n\t\t\tthrow new Error(\"No entry for attendee\");\n\t\t}\n\t\tconst items = new Map<Keys, LatestData<T, ValueAccessor<T>>>();\n\t\tfor (const [key, item] of objectEntries(clientStateMap.items)) {\n\t\t\tif (isValueRequiredState(item)) {\n\t\t\t\titems.set(key, {\n\t\t\t\t\tvalue: createValidatedGetter(item, validator),\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificAttendeeId extends AttendeeId>(\n\t\tattendee: SpecificAttendee<SpecificAttendeeId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T, string | number>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId: SpecificAttendeeId = attendee.attendeeId;\n\t\tconst currentState = (allKnownStates.states[attendeeId] ??=\n\t\t\t// New attendee - prepare new attendee state directory\n\t\t\t{\n\t\t\t\trev: value.rev,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- items entries can't be optional per https://github.com/microsoft/TypeScript/issues/42810; so forced cast\n\t\t\t\titems: {} as ValidatableMapValueState<T, Keys>[\"items\"],\n\t\t\t});\n\t\t// Accumulate individual update keys\n\t\tconst updatedItemKeys: Keys[] = [];\n\t\tfor (const [key, item] of objectEntries(value.items)) {\n\t\t\t// TODO: Key validation needs to be added here.\n\t\t\tconst validKey = key as Keys;\n\t\t\tif (!(key in currentState.items) || currentState.items[validKey].rev < item.rev) {\n\t\t\t\tupdatedItemKeys.push(validKey);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedItemKeys.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tattendee,\n\t\t\titems: new Map<Keys, LatestData<T, ValueAccessor<T>>>(),\n\t\t};\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const key of updatedItemKeys) {\n\t\t\tconst item = value.items[key];\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\t\t\tconst metadata = {\n\t\t\t\trevision: item.rev,\n\t\t\t\ttimestamp: item.timestamp,\n\t\t\t};\n\t\t\tif (isValueRequiredState(item)) {\n\t\t\t\tconst updatedItem = {\n\t\t\t\t\tattendee,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: createValidatedGetter(item, this.validator),\n\t\t\t\t\tmetadata,\n\t\t\t\t} satisfies LatestMapItemUpdatedClientData<T, Keys, ValueAccessor<T>>;\n\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"remoteItemUpdated\", updatedItem));\n\t\t\t\tallUpdates.items.set(key, {\n\t\t\t\t\tvalue: updatedItem.value,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tpostUpdateActions.push(() =>\n\t\t\t\t\tthis.events.emit(\"remoteItemRemoved\", {\n\t\t\t\t\t\tattendee,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, attendeeId, currentState);\n\t\tpostUpdateActions.push(() => this.events.emit(\"remoteUpdated\", allUpdates));\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latestMap} function.\n *\n * @input\n * @beta\n */\nexport interface LatestMapArgumentsRaw<T, Keys extends string | number = string | number> {\n\t/**\n\t * The initial value of the local state.\n\t */\n\tlocal?: {\n\t\t[K in Keys]: JsonSerializable<T>;\n\t};\n\n\t/**\n\t * See {@link BroadcastControlSettings}.\n\t */\n\tsettings?: BroadcastControlSettings | undefined;\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latestMap} function.\n *\n * @input\n * @beta\n */\nexport interface LatestMapArguments<T, Keys extends string | number = string | number>\n\textends LatestMapArgumentsRaw<T, Keys> {\n\t/**\n\t * An optional function that will be called at runtime to validate the presence data. A runtime validator is strongly\n\t * recommended. See {@link StateSchemaValidator}.\n\t */\n\tvalidator: StateSchemaValidator<T>;\n}\n\n// #region factory function overloads\n// Overloads should be ordered from most specific to least specific when combined.\n\n/**\n * Factory for creating a {@link LatestMap} or {@link LatestMapRaw} State object.\n *\n * @beta\n * @sealed\n */\nexport interface LatestMapFactory {\n\t/**\n\t * Factory for creating a {@link LatestMap} State object.\n\t *\n\t * @remarks\n\t * This overload is used when called with {@link LatestMapArguments}.\n\t * That is, if a validator function is provided.\n\t */\n\t<T, Keys extends string | number = string | number, RegistrationKey extends string = string>(\n\t\targs: LatestMapArguments<T, Keys>,\n\t): InternalTypes.ManagerFactory<\n\t\tRegistrationKey,\n\t\tInternalTypes.MapValueState<T, Keys>,\n\t\tLatestMap<T, Keys>\n\t>;\n\n\t/**\n\t * Factory for creating a {@link LatestMapRaw} State object.\n\t *\n\t * @remarks\n\t * This overload is used when called with {@link LatestMapArgumentsRaw}.\n\t * That is, if a validator function is _not_ provided.\n\t */\n\t<T, Keys extends string | number = string | number, RegistrationKey extends string = string>(\n\t\targs?: LatestMapArgumentsRaw<T, Keys>,\n\t): InternalTypes.ManagerFactory<\n\t\tRegistrationKey,\n\t\tInternalTypes.MapValueState<T, Keys>,\n\t\tLatestMapRaw<T, Keys>\n\t>;\n}\n\n// #endregion\n\n/**\n * Factory for creating a {@link LatestMap} or {@link LatestMapRaw} State object.\n */\nexport const latestMap: LatestMapFactory = <\n\tT,\n\tKeys extends string | number = string | number,\n\tRegistrationKey extends string = string,\n>(\n\targs?: Partial<LatestMapArguments<T, Keys>>,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T, Keys>,\n\tLatestMapRaw<T, Keys> & LatestMap<T, Keys>\n> => {\n\tconst settings = args?.settings;\n\tconst initialValues = args?.local;\n\tconst validator = args?.validator;\n\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<\n\t\tT,\n\t\t// This should be `Keys`, but will only work if properties are optional.\n\t\tstring | number\n\t> = { rev: 0, items: {} };\n\t// LatestMapRaw takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const key of objectKeys(initialValues)) {\n\t\t\tvalue.items[key] = {\n\t\t\t\trev: 0,\n\t\t\t\ttimestamp,\n\t\t\t\tvalue: toOpaqueJson(initialValues[key]),\n\t\t\t};\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapRaw<T, Keys> & LatestMap<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>(\n\t\t\tnew LatestMapValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tsettings,\n\t\t\t\tvalidator,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.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\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport type {\n\tDeepReadonly,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type {\n\tPostUpdateAction,\n\tValidatableOptionalState,\n\tValueManager,\n} from \"./internalTypes.js\";\nimport {\n\tasDeeplyReadonly,\n\tasDeeplyReadonlyDeserializedJson,\n\tisValueRequiredState,\n\tobjectEntries,\n\tobjectKeys,\n\ttoOpaqueJson,\n} from \"./internalUtils.js\";\nimport { createValidatedGetter } from \"./latestValueTypes.js\";\nimport type {\n\tLatestClientData,\n\tLatestData,\n\tLatestMetadata,\n\tProxiedValueAccessor,\n\tRawValueAccessor,\n\tStateSchemaValidator,\n\tValueAccessor,\n} from \"./latestValueTypes.js\";\nimport type { AttendeeId, Attendee, Presence, SpecificAttendee } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * A validator function that can optionally be provided to do runtime validation\n * of the custom key listed in a {@link LatestMap}.\n *\n * @param unvalidatedKey - The unknown key that should be validated.\n *\n * @returns True if the key is valid.\n *\n * @beta\n */\nexport type KeySchemaValidator<Keys extends string> = (\n\tunvalidatedKey: string,\n) => unvalidatedKey is Keys;\n\n/**\n * Collection of validatable optional values in a \"map\" structure.\n *\n * @remarks\n * Validatable equivalent of {@link InternalTypes.MapValueState}.\n */\ninterface ValidatableMapValueState<T> {\n\trev: number;\n\titems: {\n\t\t// Caution: any particular item may or may not exist\n\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t[name in string]: ValidatableOptionalState<T>;\n\t};\n}\n\n/**\n * Collection of latest known values for a specific {@link Attendee}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapClientData<\n\tT,\n\tKeys extends string,\n\tTValueAccessor extends ValueAccessor<T>,\n\tSpecificAttendeeId extends AttendeeId = AttendeeId,\n> {\n\t/**\n\t * Associated {@link Attendee}.\n\t */\n\tattendee: Attendee<SpecificAttendeeId>;\n\n\t/**\n\t * Map of items for the state.\n\t *\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestData<T, TValueAccessor>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapItemUpdatedClientData<\n\tT,\n\tK extends string,\n\tTValueAccessor extends ValueAccessor<T>,\n> extends LatestClientData<T, TValueAccessor> {\n\t/**\n\t * Key of the updated item.\n\t */\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapItemRemovedClientData<K extends string> {\n\t/**\n\t * Associated {@link Attendee}.\n\t */\n\tattendee: Attendee;\n\t/**\n\t * Key of the removed item.\n\t */\n\tkey: K;\n\t/**\n\t * Metadata associated with the removal of the item.\n\t */\n\tmetadata: LatestMetadata;\n}\n\n/**\n * Events from {@link LatestMapRaw}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMapEvents<\n\tT,\n\tK extends string,\n\tTRemoteValueAccessor extends ValueAccessor<T> = ProxiedValueAccessor<T>,\n> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tremoteUpdated: (updates: LatestMapClientData<T, K, TRemoteValueAccessor>) => void;\n\n\t/**\n\t * Raised when specific item's value of remote client is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemUpdated: (\n\t\tupdatedItem: LatestMapItemUpdatedClientData<T, K, TRemoteValueAccessor>,\n\t) => void;\n\n\t/**\n\t * Raised when specific item of remote client is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tremoteItemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n\n\t/**\n\t * Raised when specific local item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemUpdated: (updatedItem: {\n\t\tvalue: DeepReadonly<JsonSerializable<T>>;\n\t\tkey: K;\n\t}) => void;\n\n\t/**\n\t * Raised when specific local item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\tlocalItemRemoved: (removedItem: {\n\t\tkey: K;\n\t}) => void;\n}\n\n/**\n * Events from {@link LatestMapRaw}.\n *\n * @sealed\n * @beta\n */\nexport type LatestMapRawEvents<T, K extends string> = LatestMapEvents<\n\tT,\n\tK,\n\tRawValueAccessor<T>\n>;\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @beta\n */\nexport interface StateMap<K extends string, V> {\n\t/**\n\t * ${@link StateMap.delete}s all elements in the StateMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * Removes the element with the specified key from the StateMap, if it exists.\n\t *\n\t * @returns true if an element in the StateMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the StateMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns the element with the specified key from the StateMap, if it exists.\n\t *\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): DeepReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * Checks if an element with the specified key exists in the StateMap.\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the StateMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V>): this;\n\n\t/**\n\t * The number of elements in the StateMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, DeepReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<DeepReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string> implements StateMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T, K>,\n\t\tprivate readonly emitter: IEmitter<\n\t\t\tPick<LatestMapEvents<T, K, ValueAccessor<T>>, \"localItemUpdated\" | \"localItemRemoved\">\n\t\t>,\n\t\tprivate readonly localUpdate: (\n\t\t\tupdates: InternalTypes.MapValueState<\n\t\t\t\tT,\n\t\t\t\t// This should be `K`, but will only work if properties are optional.\n\t\t\t\tstring\n\t\t\t>,\n\t\t) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\t/**\n\t * Note: caller must ensure key exists in this.value.items.\n\t */\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\t// Caller is required to ensure key exists.\n\t\tconst item = this.value.items[key];\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t\tthis.emitter.emit(\"localItemRemoved\", { key });\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: DeepReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: StateMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\t// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast\n\t\t\t\tcallbackfn(asDeeplyReadonlyDeserializedJson(item.value), key as unknown as K, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): DeepReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn asDeeplyReadonlyDeserializedJson(this.value.items[key]?.value);\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, inValue: JsonSerializable<T>): this {\n\t\tconst value = toOpaqueJson<T>(inValue);\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\tthis.emitter.emit(\"localItemUpdated\", { key, value: asDeeplyReadonly(inValue) });\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of objectEntries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\t// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast\n\t\t\t\tkeys.push(key as unknown as K);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * State that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMap<\n\tT,\n\tKeys extends string = string,\n\tTRemoteAccessor extends ValueAccessor<T> = ProxiedValueAccessor<T>,\n> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for LatestMap.\n\t */\n\treadonly events: Listenable<LatestMapEvents<T, Keys, TRemoteAccessor>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: StateMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tgetRemotes(): IterableIterator<LatestMapClientData<T, Keys, TRemoteAccessor>>;\n\t/**\n\t * Array of {@link Attendee}s that have provided states.\n\t */\n\tgetStateAttendees(): Attendee[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tgetRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T, TRemoteAccessor>>;\n}\n\n/**\n * State that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link StateFactory.latestMap} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport type LatestMapRaw<T, Keys extends string = string> = LatestMap<\n\tT,\n\tKeys,\n\tRawValueAccessor<T>\n>;\n\n/**\n * Simply returns true for all given string keys.\n */\nfunction anyKeyIsValid<Keys extends string>(unvalidatedKey: string): unvalidatedKey is Keys {\n\treturn true;\n}\n\nclass LatestMapValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string = string,\n> implements\n\t\tLatestMapRaw<T, Keys>,\n\t\tLatestMap<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T, Keys>>>\n{\n\tpublic readonly events = createEmitter<LatestMapEvents<T, Keys, ValueAccessor<T>>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>,\n\t\t\tValidatableMapValueState<T>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T, Keys>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t\tprivate readonly validator: StateSchemaValidator<T> | undefined,\n\t\tprivate readonly isValidKey: KeySchemaValidator<Keys>,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\tthis.events,\n\t\t\t(updates: InternalTypes.MapValueState<T, Keys>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic readonly local: StateMap<Keys, T>;\n\n\tpublic *getRemotes(): IterableIterator<LatestMapClientData<T, Keys, ValueAccessor<T>>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const attendeeId of objectKeys(allKnownStates.states)) {\n\t\t\tif (attendeeId !== allKnownStates.self) {\n\t\t\t\tconst attendee = this.datastore.presence.attendees.getAttendee(attendeeId);\n\t\t\t\tconst items = this.getRemote(attendee);\n\t\t\t\tyield { attendee, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getStateAttendees(): Attendee[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn objectKeys(allKnownStates.states)\n\t\t\t.filter((attendeeId) => attendeeId !== allKnownStates.self)\n\t\t\t.map((attendeeId) => this.datastore.presence.attendees.getAttendee(attendeeId));\n\t}\n\n\tpublic getRemote(attendee: Attendee): ReadonlyMap<Keys, LatestData<T, ValueAccessor<T>>> {\n\t\tconst validator = this.validator;\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId = attendee.attendeeId;\n\t\tconst clientStateMap = allKnownStates.states[attendeeId];\n\t\tif (clientStateMap === undefined) {\n\t\t\tthrow new Error(\"No entry for attendee\");\n\t\t}\n\t\tconst items = new Map<Keys, LatestData<T, ValueAccessor<T>>>();\n\t\tfor (const [key, item] of objectEntries(clientStateMap.items)) {\n\t\t\tif (this.isValidKey(key) && isValueRequiredState(item)) {\n\t\t\t\titems.set(key, {\n\t\t\t\t\tvalue: createValidatedGetter(item, validator),\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificAttendeeId extends AttendeeId>(\n\t\tattendee: SpecificAttendee<SpecificAttendeeId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T, string>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId: SpecificAttendeeId = attendee.attendeeId;\n\t\tconst currentState = (allKnownStates.states[attendeeId] ??=\n\t\t\t// New attendee - prepare new attendee state directory\n\t\t\t{\n\t\t\t\trev: value.rev,\n\t\t\t\titems: {},\n\t\t\t});\n\t\t// Accumulate individual update keys\n\t\tconst updatedKeyItemPairs: [string, InternalTypes.ValueOptionalState<T>][] = [];\n\t\tfor (const [key, item] of objectEntries(value.items)) {\n\t\t\tconst currentItem = currentState.items[key];\n\t\t\tif (currentItem === undefined || currentItem.rev < item.rev) {\n\t\t\t\tupdatedKeyItemPairs.push([key, item]);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedKeyItemPairs.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tattendee,\n\t\t\titems: new Map<Keys, LatestData<T, ValueAccessor<T>>>(),\n\t\t};\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [key, item] of updatedKeyItemPairs) {\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\n\t\t\t// Prepare update events, but only for valid keys.\n\t\t\tif (!this.isValidKey(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst metadata = {\n\t\t\t\trevision: item.rev,\n\t\t\t\ttimestamp: item.timestamp,\n\t\t\t};\n\t\t\tif (isValueRequiredState(item)) {\n\t\t\t\tconst updatedItem = {\n\t\t\t\t\tattendee,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: createValidatedGetter(item, this.validator),\n\t\t\t\t\tmetadata,\n\t\t\t\t} satisfies LatestMapItemUpdatedClientData<T, Keys, ValueAccessor<T>>;\n\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"remoteItemUpdated\", updatedItem));\n\t\t\t\tallUpdates.items.set(key, {\n\t\t\t\t\tvalue: updatedItem.value,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tpostUpdateActions.push(() =>\n\t\t\t\t\tthis.events.emit(\"remoteItemRemoved\", {\n\t\t\t\t\t\tattendee,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, attendeeId, currentState);\n\t\t// Only emit remoteUpdated if there are any individual updates, which\n\t\t// accounts for the case where all updates were for invalid keys.\n\t\tif (postUpdateActions.length > 0) {\n\t\t\tpostUpdateActions.push(() => this.events.emit(\"remoteUpdated\", allUpdates));\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latestMap} function.\n *\n * @input\n * @beta\n */\nexport interface LatestMapArgumentsRaw<T, Keys extends string = string> {\n\t/**\n\t * The initial value of the local state.\n\t */\n\tlocal?: {\n\t\t[K in Keys]: JsonSerializable<T>;\n\t};\n\n\t/**\n\t * See {@link BroadcastControlSettings}.\n\t */\n\tsettings?: BroadcastControlSettings | undefined;\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latestMap} function.\n *\n * @input\n * @beta\n */\nexport interface LatestMapArguments<T, Keys extends string = string>\n\textends LatestMapArgumentsRaw<T, Keys> {\n\t/**\n\t * An optional function that will be called at runtime to validate data value\n\t * under a key. A runtime validator is strongly recommended.\n\t * @see {@link StateSchemaValidator}.\n\t */\n\tvalidator: StateSchemaValidator<T>;\n\t/**\n\t * An optional function that will be called at runtime to validate the presence\n\t * data key. A runtime validator is strongly recommended when key type is not\n\t * simply `string`.\n\t * @see {@link KeySchemaValidator}.\n\t */\n\tkeyValidator?: KeySchemaValidator<Keys>;\n}\n\n// #region factory function overloads\n// Overloads should be ordered from most specific to least specific when combined.\n\n/**\n * Factory for creating a {@link LatestMap} or {@link LatestMapRaw} State object.\n *\n * @beta\n * @sealed\n */\nexport interface LatestMapFactory {\n\t/**\n\t * Factory for creating a {@link LatestMap} State object.\n\t *\n\t * @remarks\n\t * This overload is used when called with {@link LatestMapArguments}.\n\t * That is, if a validator function is provided.\n\t */\n\t<T, Keys extends string = string, RegistrationKey extends string = string>(\n\t\targs: LatestMapArguments<T, Keys>,\n\t): InternalTypes.ManagerFactory<\n\t\tRegistrationKey,\n\t\tInternalTypes.MapValueState<T, Keys>,\n\t\tLatestMap<T, Keys>\n\t>;\n\n\t/**\n\t * Factory for creating a {@link LatestMapRaw} State object.\n\t *\n\t * @remarks\n\t * This overload is used when called with {@link LatestMapArgumentsRaw}.\n\t * That is, if a validator function is _not_ provided.\n\t */\n\t<T, Keys extends string = string, RegistrationKey extends string = string>(\n\t\targs?: LatestMapArgumentsRaw<T, Keys>,\n\t): InternalTypes.ManagerFactory<\n\t\tRegistrationKey,\n\t\tInternalTypes.MapValueState<T, Keys>,\n\t\tLatestMapRaw<T, Keys>\n\t>;\n}\n\n// #endregion\n\n/**\n * Factory for creating a {@link LatestMap} or {@link LatestMapRaw} State object.\n */\nexport const latestMap: LatestMapFactory = <\n\tT,\n\tKeys extends string = string,\n\tRegistrationKey extends string = string,\n>(\n\targs?: Partial<LatestMapArguments<T, Keys>>,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T, Keys>,\n\tLatestMapRaw<T, Keys> & LatestMap<T, Keys>\n> => {\n\tconst settings = args?.settings;\n\tconst initialValues = args?.local;\n\tconst validator = args?.validator;\n\tconst isKeyValid = args?.keyValidator ?? anyKeyIsValid;\n\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<\n\t\tT,\n\t\t// This should be `Keys`, but will only work if properties are optional.\n\t\tstring\n\t> = { rev: 0, items: {} };\n\t// LatestMapRaw takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const [key, item] of objectEntries(initialValues)) {\n\t\t\t// TODO: AB#55932: try fixing typing of objectEntries to avoid this cast\n\t\t\tconst assumedValidKey = key as unknown as Keys;\n\t\t\tvalue.items[assumedValidKey] = {\n\t\t\t\trev: 0,\n\t\t\t\ttimestamp,\n\t\t\t\tvalue: toOpaqueJson(item),\n\t\t\t};\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapRaw<T, Keys> & LatestMap<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T, Keys>\n\t\t>(\n\t\t\tnew LatestMapValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tsettings,\n\t\t\t\tvalidator,\n\t\t\t\tisKeyValid,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });\n};\n"]}
|
package/lib/legacy.alpha.d.ts
CHANGED
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/presence";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.80.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,6BAA6B,CAAC;AAClD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,6BAA6B,CAAC;AAClD,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/presence\";\nexport const pkgVersion = \"2.80.0\";\n"]}
|
|
@@ -29,11 +29,13 @@ export declare function isValueDirectory<T>(obj: ValidatableValueDirectory<T> |
|
|
|
29
29
|
* High-level contract for manager of singleton Presence datastore
|
|
30
30
|
*/
|
|
31
31
|
export interface PresenceDatastoreManager {
|
|
32
|
-
joinSession(clientId: ClientConnectionId): void;
|
|
32
|
+
joinSession(clientId: ClientConnectionId, alternateProvider: ClientConnectionId | undefined): void;
|
|
33
33
|
onDisconnected(): void;
|
|
34
34
|
getWorkspace<TSchema extends StatesWorkspaceSchema>(internalWorkspaceAddress: `s:${WorkspaceAddress}`, requestedContent: TSchema, controls?: BroadcastControlSettings): StatesWorkspace<TSchema>;
|
|
35
35
|
getWorkspace<TSchema extends NotificationsWorkspaceSchema>(internalWorkspaceAddress: `n:${WorkspaceAddress}`, requestedContent: TSchema): NotificationsWorkspace<TSchema>;
|
|
36
|
-
processSignal(message: InboundExtensionMessage<SignalMessages
|
|
36
|
+
processSignal(message: InboundExtensionMessage<SignalMessages> & {
|
|
37
|
+
clientId: ClientConnectionId;
|
|
38
|
+
}, local: boolean, optional: boolean): void;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Delays used for broadcasting join responses to clients.
|
|
@@ -71,12 +73,6 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
|
|
|
71
73
|
private readonly sendMessageTimer;
|
|
72
74
|
private readonly workspaces;
|
|
73
75
|
private readonly targetedSignalSupport;
|
|
74
|
-
/**
|
|
75
|
-
* When defined, this client is not recognized in the session.
|
|
76
|
-
* Call when no longer caring about that condition. That way listeners are
|
|
77
|
-
* cleaned up.
|
|
78
|
-
*/
|
|
79
|
-
private stopWaitingForSelfInAudience;
|
|
80
76
|
/**
|
|
81
77
|
* Tracks whether this client has complete snapshot level knowledge and
|
|
82
78
|
* how that determination was reached.
|
|
@@ -110,8 +106,6 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
|
|
|
110
106
|
constructor(attendeeId: AttendeeId, runtime: IEphemeralRuntime, logger: ITelemetryLoggerExt | undefined, events: IEmitter<PresenceEvents>, presence: Presence, systemWorkspaceDatastore: SystemWorkspaceDatastore, systemWorkspace: AnyWorkspaceEntry<StatesWorkspaceSchema>);
|
|
111
107
|
private getAudienceInformation;
|
|
112
108
|
joinSession(selfClientId: ClientConnectionId, alternateProvider?: ClientConnectionId | undefined): void;
|
|
113
|
-
private listenForSelfInAudience;
|
|
114
|
-
private stopWaitingAndJoin;
|
|
115
109
|
onDisconnected(): void;
|
|
116
110
|
getWorkspace<TSchema extends StatesWorkspaceSchema>(internalWorkspaceAddress: InternalWorkspaceAddress, requestedContent: TSchema, controls?: BroadcastControlSettings): AnyWorkspace<TSchema>;
|
|
117
111
|
/**
|
|
@@ -138,7 +132,9 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
|
|
|
138
132
|
*/
|
|
139
133
|
private stripValidationFromValueData;
|
|
140
134
|
private broadcastAllKnownState;
|
|
141
|
-
processSignal(message: InboundExtensionMessage<SignalMessages
|
|
135
|
+
processSignal(message: InboundExtensionMessage<SignalMessages> & {
|
|
136
|
+
clientId: ClientConnectionId;
|
|
137
|
+
}, local: boolean, optional: boolean): void;
|
|
142
138
|
/**
|
|
143
139
|
* Broadcasts a join response (complete datastore update message)
|
|
144
140
|
* if there is an outstanding join response request.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -150,7 +150,6 @@ export class PresenceDatastoreManagerImpl {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
return {
|
|
153
|
-
audience,
|
|
154
153
|
selfPresent,
|
|
155
154
|
interactiveMembersExcludingSelf: {
|
|
156
155
|
all,
|
|
@@ -167,9 +166,9 @@ export class PresenceDatastoreManagerImpl {
|
|
|
167
166
|
// Lack of anyone likely means that this client is very freshly joined
|
|
168
167
|
// and has not received any Join Signals (type="join") from the service
|
|
169
168
|
// yet.
|
|
170
|
-
const {
|
|
171
|
-
if (
|
|
172
|
-
if (
|
|
169
|
+
const { selfPresent, interactiveMembersExcludingSelf } = this.getAudienceInformation(selfClientId);
|
|
170
|
+
if (selfPresent) {
|
|
171
|
+
if (interactiveMembersExcludingSelf.all.size === 0) {
|
|
173
172
|
// If there aren't any members connected except self, then this client
|
|
174
173
|
// must have complete information.
|
|
175
174
|
this.reasonForCompleteSnapshot = "alone";
|
|
@@ -180,12 +179,12 @@ export class PresenceDatastoreManagerImpl {
|
|
|
180
179
|
// ClientJoin soon rectifying that and covering for bad incomplete
|
|
181
180
|
// responses this client sent in the meantime.
|
|
182
181
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// When self is not represented, audience is an unreliable state,
|
|
185
|
+
// especially during a reconnect. An alternateProvider is expected
|
|
186
|
+
// to have been provided for this call to be useful (efficient).
|
|
187
|
+
assert(alternateProvider !== undefined, "Self is not in audience and no alternateProvider given");
|
|
189
188
|
}
|
|
190
189
|
// Broadcast join message to all clients
|
|
191
190
|
// Select primary update providers
|
|
@@ -224,46 +223,8 @@ export class PresenceDatastoreManagerImpl {
|
|
|
224
223
|
},
|
|
225
224
|
});
|
|
226
225
|
}
|
|
227
|
-
listenForSelfInAudience(selfClientId, audience) {
|
|
228
|
-
this.logger?.sendTelemetryEvent({
|
|
229
|
-
eventName: "JoinDeferred",
|
|
230
|
-
details: {
|
|
231
|
-
attendeeId: this.attendeeId,
|
|
232
|
-
connectionId: selfClientId,
|
|
233
|
-
},
|
|
234
|
-
});
|
|
235
|
-
// Prepare to join once self audience member joins.
|
|
236
|
-
// Alternatively, processSignal may force a join when a presence
|
|
237
|
-
// signal is received even without audience members (assumes
|
|
238
|
-
// audience signals were lost).
|
|
239
|
-
const joinWhenSelfAudienceMemberAdded = (addedClientId) => {
|
|
240
|
-
if (addedClientId !== selfClientId) {
|
|
241
|
-
// Keep listening
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
// No need to force here by providing alternate provider as self is
|
|
245
|
-
// now present.
|
|
246
|
-
// Do avoid forcing so that reasonForCompleteSnapshot is set correctly
|
|
247
|
-
// if no others have been added.
|
|
248
|
-
this.stopWaitingAndJoin(selfClientId, /* alternateProvider */ undefined);
|
|
249
|
-
};
|
|
250
|
-
audience.on("addMember", joinWhenSelfAudienceMemberAdded);
|
|
251
|
-
this.stopWaitingForSelfInAudience = () => {
|
|
252
|
-
audience.off("addMember", joinWhenSelfAudienceMemberAdded);
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
stopWaitingAndJoin(selfClientId, alternateProvider) {
|
|
256
|
-
this.stopWaitingForSelfInAudience?.();
|
|
257
|
-
this.stopWaitingForSelfInAudience = undefined;
|
|
258
|
-
// Confirm not currently disconnected
|
|
259
|
-
if (this.runtime.getJoinedStatus() !== "disconnected") {
|
|
260
|
-
this.joinSession(selfClientId, alternateProvider);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
226
|
onDisconnected() {
|
|
264
227
|
delete this.reasonForCompleteSnapshot;
|
|
265
|
-
this.stopWaitingForSelfInAudience?.();
|
|
266
|
-
this.stopWaitingForSelfInAudience = undefined;
|
|
267
228
|
}
|
|
268
229
|
getWorkspace(internalWorkspaceAddress, requestedContent, controls) {
|
|
269
230
|
const existing = this.workspaces.get(internalWorkspaceAddress);
|
|
@@ -478,7 +439,6 @@ export class PresenceDatastoreManagerImpl {
|
|
|
478
439
|
}
|
|
479
440
|
processSignal(message, local, optional) {
|
|
480
441
|
const received = Date.now();
|
|
481
|
-
assert(message.clientId !== null, 0xa3a /* Map received signal without clientId */);
|
|
482
442
|
if (!isPresenceMessage(message)) {
|
|
483
443
|
assert(optional, "Unrecognized message type in critical message");
|
|
484
444
|
return;
|
|
@@ -495,19 +455,6 @@ export class PresenceDatastoreManagerImpl {
|
|
|
495
455
|
this.returnedMessages;
|
|
496
456
|
return;
|
|
497
457
|
}
|
|
498
|
-
const selfClientId = this.runtime.getClientId();
|
|
499
|
-
assert(selfClientId !== undefined, "Received signal without clientId");
|
|
500
|
-
// Check for undesired case of receiving a remote presence signal
|
|
501
|
-
// without having been alerted to self audience join. (Perhaps join
|
|
502
|
-
// signal was dropped.)
|
|
503
|
-
// In practice it is commonly observed that local signals can be
|
|
504
|
-
// returned ahead of audience join notification. So, it is reasonable
|
|
505
|
-
// to expect that audience join notification may be delayed until after
|
|
506
|
-
// other presence signals are received. One is enough to get things
|
|
507
|
-
// rolling.
|
|
508
|
-
if (this.stopWaitingForSelfInAudience !== undefined) {
|
|
509
|
-
this.stopWaitingAndJoin(selfClientId, /* alternateProvider */ message.clientId);
|
|
510
|
-
}
|
|
511
458
|
const timeModifier = received -
|
|
512
459
|
(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);
|
|
513
460
|
const postUpdateActions = [];
|
|
@@ -525,6 +472,8 @@ export class PresenceDatastoreManagerImpl {
|
|
|
525
472
|
// Update join response requests that are now satisfied.
|
|
526
473
|
const joinResponseFor = message.content.joinResponseFor;
|
|
527
474
|
if (joinResponseFor) {
|
|
475
|
+
const selfClientId = this.runtime.getClientId();
|
|
476
|
+
assert(selfClientId !== undefined, "Received signal without clientId");
|
|
528
477
|
let justGainedCompleteSnapshot = false;
|
|
529
478
|
if (joinResponseFor.includes(selfClientId)) {
|
|
530
479
|
if (this.reasonForCompleteSnapshot) {
|