@fluidframework/presence 2.41.0-338401 → 2.41.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/README.md +6 -10
- package/dist/alpha.d.ts +18 -14
- package/dist/baseTypes.d.ts +1 -1
- package/dist/baseTypes.js.map +1 -1
- package/dist/beta.d.ts +53 -0
- package/dist/broadcastControls.d.ts +2 -2
- package/dist/broadcastControls.js.map +1 -1
- package/dist/datastorePresenceManagerFactory.d.ts +4 -1
- package/dist/datastorePresenceManagerFactory.d.ts.map +1 -1
- package/dist/datastorePresenceManagerFactory.js +23 -3
- package/dist/datastorePresenceManagerFactory.js.map +1 -1
- package/dist/experimentalAccess.d.ts +12 -4
- package/dist/experimentalAccess.d.ts.map +1 -1
- package/dist/experimentalAccess.js +24 -17
- package/dist/experimentalAccess.js.map +1 -1
- package/dist/exposedInternalTypes.d.ts +1 -1
- package/dist/exposedInternalTypes.js +1 -1
- package/dist/exposedInternalTypes.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/internalTypes.d.ts +25 -6
- package/dist/internalTypes.d.ts.map +1 -1
- package/dist/internalTypes.js.map +1 -1
- package/dist/internalUtils.d.ts +9 -4
- package/dist/internalUtils.d.ts.map +1 -1
- package/dist/internalUtils.js +5 -0
- package/dist/internalUtils.js.map +1 -1
- package/dist/latestMapValueManager.d.ts +8 -8
- package/dist/latestMapValueManager.js +1 -1
- package/dist/latestMapValueManager.js.map +1 -1
- package/dist/latestValueManager.d.ts +4 -4
- package/dist/latestValueManager.js +1 -1
- package/dist/latestValueManager.js.map +1 -1
- package/dist/latestValueTypes.d.ts +3 -3
- package/dist/latestValueTypes.js.map +1 -1
- package/dist/notificationsManager.d.ts +1 -1
- package/dist/notificationsManager.d.ts.map +1 -1
- package/dist/notificationsManager.js.map +1 -1
- package/dist/package.json +5 -4
- package/dist/presence.d.ts +19 -8
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +1 -1
- package/dist/presence.js.map +1 -1
- package/dist/presenceDatastoreManager.d.ts +6 -37
- package/dist/presenceDatastoreManager.d.ts.map +1 -1
- package/dist/presenceDatastoreManager.js +33 -31
- package/dist/presenceDatastoreManager.js.map +1 -1
- package/dist/presenceManager.d.ts +5 -5
- package/dist/presenceManager.d.ts.map +1 -1
- package/dist/presenceManager.js +12 -10
- package/dist/presenceManager.js.map +1 -1
- package/dist/presenceStates.d.ts +1 -1
- package/dist/presenceStates.d.ts.map +1 -1
- package/dist/presenceStates.js.map +1 -1
- package/dist/protocol.d.ts +74 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +16 -0
- package/dist/protocol.js.map +1 -0
- package/dist/stateDatastore.d.ts +1 -1
- package/dist/stateDatastore.d.ts.map +1 -1
- package/dist/stateDatastore.js.map +1 -1
- package/dist/stateFactory.d.ts +1 -1
- package/dist/stateFactory.js +1 -1
- package/dist/stateFactory.js.map +1 -1
- package/dist/systemWorkspace.js.map +1 -1
- package/dist/types.d.ts +9 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/lib/alpha.d.ts +18 -14
- package/lib/baseTypes.d.ts +1 -1
- package/lib/baseTypes.js.map +1 -1
- package/lib/beta.d.ts +53 -0
- package/lib/broadcastControls.d.ts +2 -2
- package/lib/broadcastControls.js.map +1 -1
- package/lib/datastorePresenceManagerFactory.d.ts +4 -1
- package/lib/datastorePresenceManagerFactory.d.ts.map +1 -1
- package/lib/datastorePresenceManagerFactory.js +23 -3
- package/lib/datastorePresenceManagerFactory.js.map +1 -1
- package/lib/experimentalAccess.d.ts +12 -4
- package/lib/experimentalAccess.d.ts.map +1 -1
- package/lib/experimentalAccess.js +22 -15
- package/lib/experimentalAccess.js.map +1 -1
- package/lib/exposedInternalTypes.d.ts +1 -1
- package/lib/exposedInternalTypes.js +1 -1
- package/lib/exposedInternalTypes.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/internalTypes.d.ts +25 -6
- package/lib/internalTypes.d.ts.map +1 -1
- package/lib/internalTypes.js.map +1 -1
- package/lib/internalUtils.d.ts +9 -4
- package/lib/internalUtils.d.ts.map +1 -1
- package/lib/internalUtils.js +5 -0
- package/lib/internalUtils.js.map +1 -1
- package/lib/latestMapValueManager.d.ts +8 -8
- package/lib/latestMapValueManager.js +1 -1
- package/lib/latestMapValueManager.js.map +1 -1
- package/lib/latestValueManager.d.ts +4 -4
- package/lib/latestValueManager.js +1 -1
- package/lib/latestValueManager.js.map +1 -1
- package/lib/latestValueTypes.d.ts +3 -3
- package/lib/latestValueTypes.js.map +1 -1
- package/lib/notificationsManager.d.ts +1 -1
- package/lib/notificationsManager.d.ts.map +1 -1
- package/lib/notificationsManager.js.map +1 -1
- package/lib/presence.d.ts +19 -8
- package/lib/presence.d.ts.map +1 -1
- package/lib/presence.js +1 -1
- package/lib/presence.js.map +1 -1
- package/lib/presenceDatastoreManager.d.ts +6 -37
- package/lib/presenceDatastoreManager.d.ts.map +1 -1
- package/lib/presenceDatastoreManager.js +32 -30
- package/lib/presenceDatastoreManager.js.map +1 -1
- package/lib/presenceManager.d.ts +5 -5
- package/lib/presenceManager.d.ts.map +1 -1
- package/lib/presenceManager.js +12 -10
- package/lib/presenceManager.js.map +1 -1
- package/lib/presenceStates.d.ts +1 -1
- package/lib/presenceStates.d.ts.map +1 -1
- package/lib/presenceStates.js.map +1 -1
- package/lib/protocol.d.ts +74 -0
- package/lib/protocol.d.ts.map +1 -0
- package/lib/protocol.js +13 -0
- package/lib/protocol.js.map +1 -0
- package/lib/stateDatastore.d.ts +1 -1
- package/lib/stateDatastore.d.ts.map +1 -1
- package/lib/stateDatastore.js.map +1 -1
- package/lib/stateFactory.d.ts +1 -1
- package/lib/stateFactory.js +1 -1
- package/lib/stateFactory.js.map +1 -1
- package/lib/systemWorkspace.js.map +1 -1
- package/lib/types.d.ts +9 -8
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/package.json +30 -23
- package/dist/container-definitions/containerExtensions.d.ts +0 -137
- package/dist/container-definitions/containerExtensions.d.ts.map +0 -1
- package/dist/container-definitions/containerExtensions.js +0 -7
- package/dist/container-definitions/containerExtensions.js.map +0 -1
- package/dist/container-definitions/index.d.ts +0 -7
- package/dist/container-definitions/index.d.ts.map +0 -1
- package/dist/container-definitions/index.js +0 -7
- package/dist/container-definitions/index.js.map +0 -1
- package/dist/container-definitions/runtime.d.ts +0 -12
- package/dist/container-definitions/runtime.d.ts.map +0 -1
- package/dist/container-definitions/runtime.js +0 -7
- package/dist/container-definitions/runtime.js.map +0 -1
- package/lib/container-definitions/containerExtensions.d.ts +0 -137
- package/lib/container-definitions/containerExtensions.d.ts.map +0 -1
- package/lib/container-definitions/containerExtensions.js +0 -6
- package/lib/container-definitions/containerExtensions.js.map +0 -1
- package/lib/container-definitions/index.d.ts +0 -7
- package/lib/container-definitions/index.d.ts.map +0 -1
- package/lib/container-definitions/index.js +0 -6
- package/lib/container-definitions/index.js.map +0 -1
- package/lib/container-definitions/runtime.d.ts +0 -12
- package/lib/container-definitions/runtime.d.ts.map +0 -1
- package/lib/container-definitions/runtime.js +0 -6
- package/lib/container-definitions/runtime.js.map +0 -1
package/dist/presence.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type { NotificationsWorkspace, NotificationsWorkspaceSchema, StatesWorksp
|
|
|
17
17
|
* identify clients in a session. {@link Attendee.attendeeId} will provide
|
|
18
18
|
* the session ID.
|
|
19
19
|
*
|
|
20
|
-
* @
|
|
20
|
+
* @beta
|
|
21
21
|
*/
|
|
22
22
|
export type AttendeeId = SessionId & {
|
|
23
23
|
readonly AttendeeId: "AttendeeId";
|
|
@@ -25,7 +25,7 @@ export type AttendeeId = SessionId & {
|
|
|
25
25
|
/**
|
|
26
26
|
* The connection status of the {@link Attendee}.
|
|
27
27
|
*
|
|
28
|
-
* @
|
|
28
|
+
* @beta
|
|
29
29
|
*/
|
|
30
30
|
export declare const AttendeeStatus: {
|
|
31
31
|
/**
|
|
@@ -47,7 +47,7 @@ export declare const AttendeeStatus: {
|
|
|
47
47
|
* - State changes are kept locally and communicated to others upon reconnect.
|
|
48
48
|
* - Notification requests are discarded (silently).
|
|
49
49
|
*
|
|
50
|
-
* @
|
|
50
|
+
* @beta
|
|
51
51
|
*/
|
|
52
52
|
export type AttendeeStatus = (typeof AttendeeStatus)[keyof typeof AttendeeStatus];
|
|
53
53
|
/**
|
|
@@ -66,7 +66,7 @@ export type AttendeeStatus = (typeof AttendeeStatus)[keyof typeof AttendeeStatus
|
|
|
66
66
|
* Audience, and Quorum representations of clients and users.
|
|
67
67
|
*
|
|
68
68
|
* @sealed
|
|
69
|
-
* @
|
|
69
|
+
* @beta
|
|
70
70
|
*/
|
|
71
71
|
export interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {
|
|
72
72
|
/**
|
|
@@ -101,7 +101,7 @@ export interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {
|
|
|
101
101
|
export type SpecificAttendee<SpecificAttendeeId extends AttendeeId> = string extends SpecificAttendeeId ? never : Attendee<SpecificAttendeeId>;
|
|
102
102
|
/**
|
|
103
103
|
* @sealed
|
|
104
|
-
* @
|
|
104
|
+
* @beta
|
|
105
105
|
*/
|
|
106
106
|
export interface AttendeesEvents {
|
|
107
107
|
/**
|
|
@@ -119,7 +119,7 @@ export interface AttendeesEvents {
|
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* @sealed
|
|
122
|
-
* @
|
|
122
|
+
* @beta
|
|
123
123
|
*/
|
|
124
124
|
export interface PresenceEvents {
|
|
125
125
|
/**
|
|
@@ -137,10 +137,10 @@ export interface PresenceEvents {
|
|
|
137
137
|
workspaceActivated: (workspaceAddress: WorkspaceAddress, type: "States" | "Notifications" | "Unknown") => void;
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
140
|
-
* Presence represents known clients within a session and their custom states
|
|
140
|
+
* Presence represents known clients within a session and their custom states.
|
|
141
141
|
*
|
|
142
142
|
* @sealed
|
|
143
|
-
* @
|
|
143
|
+
* @beta
|
|
144
144
|
*/
|
|
145
145
|
export interface Presence {
|
|
146
146
|
/**
|
|
@@ -184,6 +184,17 @@ export interface Presence {
|
|
|
184
184
|
*/
|
|
185
185
|
getWorkspace<StatesSchema extends StatesWorkspaceSchema>(workspaceAddress: WorkspaceAddress, requestedStates: StatesSchema, controls?: BroadcastControlSettings): StatesWorkspace<StatesSchema>;
|
|
186
186
|
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Presence represents known clients within a session and their custom states and notifications.
|
|
190
|
+
*
|
|
191
|
+
* @remarks
|
|
192
|
+
* To access this alpha API, cast any `{@link Presence}` to `PresenceWithNotifications`.
|
|
193
|
+
*
|
|
194
|
+
* @sealed
|
|
195
|
+
* @alpha
|
|
196
|
+
*/
|
|
197
|
+
export interface PresenceWithNotifications extends Presence {
|
|
187
198
|
readonly notifications: {
|
|
188
199
|
/**
|
|
189
200
|
* Acquires a Notifications workspace from store or adds new one.
|
package/dist/presence.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EACX,sBAAsB,EACtB,4BAA4B,EAC5B,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,cAAc;IAC1B;;OAEG;;IAGH;;OAEG;;CAEM,CAAC;AAEX;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAElF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,QAAQ,CAAC,kBAAkB,SAAS,UAAU,GAAG,UAAU;IAC3E;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC;;;;;;;;;OASG;IACH,eAAe,IAAI,kBAAkB,CAAC;IAEtC;;;;;OAKG;IACH,mBAAmB,IAAI,cAAc,CAAC;CACtC;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,CAAC,kBAAkB,SAAS,UAAU,IACjE,MAAM,SAAS,kBAAkB,GAAG,KAAK,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAE1E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAEhD;;;;OAIG;IACH,oBAAoB,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;;;;;;OAWG;IACH,kBAAkB,EAAE,CACnB,gBAAgB,EAAE,gBAAgB,EAClC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,SAAS,KACxC,IAAI,CAAC;CACV;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACxB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC;IAE5C,QAAQ,CAAC,SAAS,EAAE;QACnB;;WAEG;QACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;QAE7C;;;;;;WAMG;QACH,YAAY,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEtC;;;;WAIG;QACH,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,UAAU,GAAG,QAAQ,CAAC;QAEjE;;;;WAIG;QACH,SAAS,IAAI,QAAQ,CAAC;KACtB,CAAC;IAEF,QAAQ,CAAC,MAAM,EAAE;QAChB;;;;;;;WAOG;QACH,YAAY,CAAC,YAAY,SAAS,qBAAqB,EACtD,gBAAgB,EAAE,gBAAgB,EAClC,eAAe,EAAE,YAAY,EAC7B,QAAQ,CAAC,EAAE,wBAAwB,GACjC,eAAe,CAAC,YAAY,CAAC,CAAC;KACjC,CAAC;
|
|
1
|
+
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"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"}
|
package/dist/presence.js
CHANGED
package/dist/presence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,cAAc,GAAG;IAC7B;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link Attendee} as a way to\n * identify clients in a session. {@link Attendee.attendeeId} will provide\n * the session ID.\n *\n * @
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,cAAc,GAAG;IAC7B;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link Attendee} as a way to\n * identify clients in a session. {@link Attendee.attendeeId} will provide\n * the session ID.\n *\n * @beta\n */\nexport type AttendeeId = SessionId & { readonly AttendeeId: \"AttendeeId\" };\n\n/**\n * The connection status of the {@link Attendee}.\n *\n * @beta\n */\nexport const AttendeeStatus = {\n\t/**\n\t * The {@link Attendee} is connected to the Fluid service.\n\t */\n\tConnected: \"Connected\",\n\n\t/**\n\t * The {@link Attendee} is not connected to the Fluid service.\n\t */\n\tDisconnected: \"Disconnected\",\n} as const;\n\n/**\n * Represents the connection status of an {@link Attendee}.\n *\n * This type can be either `'Connected'` or `'Disconnected'`, indicating whether\n * the attendee is currently connected to the Fluid service.\n *\n * When `'Disconnected'`:\n * - State changes are kept locally and communicated to others upon reconnect.\n * - Notification requests are discarded (silently).\n *\n * @beta\n */\nexport type AttendeeStatus = (typeof AttendeeStatus)[keyof typeof AttendeeStatus];\n\n/**\n * A client within a Fluid session (period of container connectivity to service).\n *\n * @remarks\n * Note: This is very preliminary attendee representation.\n *\n * {@link Attendee} should be used as key to distinguish between different\n * clients as they join, rejoin, and disconnect from a session. While a\n * client's {@link ClientConnectionId} from {@link Attendee.getConnectionStatus}\n * may change over time, `Attendee` will be fixed.\n *\n * @privateRemarks\n * As this is evolved, pay attention to how this relates to Audience, Service\n * Audience, and Quorum representations of clients and users.\n *\n * @sealed\n * @beta\n */\nexport interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {\n\t/**\n\t * The session ID of the client that is stable over all connections.\n\t */\n\treadonly attendeeId: SpecificAttendeeId;\n\n\t/**\n\t * Get current client connection ID.\n\t *\n\t * @returns Current client connection ID.\n\t *\n\t * @remarks\n\t * Connection ID will change on reconnect.\n\t *\n\t * If {@link Attendee.getConnectionStatus} is {@link (AttendeeStatus:variable).Disconnected}, this will represent the last known connection ID.\n\t */\n\tgetConnectionId(): ClientConnectionId;\n\n\t/**\n\t * Get connection status of attendee.\n\t *\n\t * @returns Connection status of attendee.\n\t *\n\t */\n\tgetConnectionStatus(): AttendeeStatus;\n}\n\n/**\n * Utility type limiting to a specific attendee. (A attendee with\n * a specific session ID - not just any session ID.)\n *\n * @internal\n */\nexport type SpecificAttendee<SpecificAttendeeId extends AttendeeId> =\n\tstring extends SpecificAttendeeId ? never : Attendee<SpecificAttendeeId>;\n\n/**\n * @sealed\n * @beta\n */\nexport interface AttendeesEvents {\n\t/**\n\t * Raised when new client joins session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeConnected: (attendee: Attendee) => void;\n\n\t/**\n\t * Raised when client appears disconnected from session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeDisconnected: (attendee: Attendee) => void;\n}\n\n/**\n * @sealed\n * @beta\n */\nexport interface PresenceEvents {\n\t/**\n\t * Raised when a workspace is activated within the session.\n\t *\n\t * \"Activated\" means that a workspace is being used by a client and this\n\t * client is seeing information for the first time.\n\t *\n\t * @remarks\n\t * Local workspaces may be passively acquired/registered when this event\n\t * is raised. For a notifications workspace, that lazy registration must\n\t * be done before the event handler returns to ensure no notifications\n\t * are missed.\n\t */\n\tworkspaceActivated: (\n\t\tworkspaceAddress: WorkspaceAddress,\n\t\ttype: \"States\" | \"Notifications\" | \"Unknown\",\n\t) => void;\n}\n\n/**\n * Presence represents known clients within a session and their custom states.\n *\n * @sealed\n * @beta\n */\nexport interface Presence {\n\t/**\n\t * Events for Presence.\n\t */\n\treadonly events: Listenable<PresenceEvents>;\n\n\treadonly attendees: {\n\t\t/**\n\t\t * Events for {@link Attendee}s.\n\t\t */\n\t\treadonly events: Listenable<AttendeesEvents>;\n\n\t\t/**\n\t\t * Get all {@link Attendee}s in the session.\n\t\t *\n\t\t * @remarks\n\t\t * Attendee states are dynamic and will change as clients join and leave\n\t\t * the session.\n\t\t */\n\t\tgetAttendees(): ReadonlySet<Attendee>;\n\n\t\t/**\n\t\t * Lookup a specific {@link Attendee} in the session.\n\t\t *\n\t\t * @param clientId - Client connection or session ID\n\t\t */\n\t\tgetAttendee(clientId: ClientConnectionId | AttendeeId): Attendee;\n\n\t\t/**\n\t\t * Get this client's {@link Attendee}.\n\t\t *\n\t\t * @returns This client's attendee.\n\t\t */\n\t\tgetMyself(): Attendee;\n\t};\n\n\treadonly states: {\n\t\t/**\n\t\t * Acquires a StatesWorkspace from store or adds new one.\n\t\t *\n\t\t * @param workspaceAddress - Address of the requested StatesWorkspace\n\t\t * @param requestedStates - Requested states for the workspace\n\t\t * @param controls - Optional settings for default broadcast controls\n\t\t * @returns A StatesWorkspace\n\t\t */\n\t\tgetWorkspace<StatesSchema extends StatesWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedStates: StatesSchema,\n\t\t\tcontrols?: BroadcastControlSettings,\n\t\t): StatesWorkspace<StatesSchema>;\n\t};\n}\n\n/**\n * Presence represents known clients within a session and their custom states and notifications.\n *\n * @remarks\n * To access this alpha API, cast any `{@link Presence}` to `PresenceWithNotifications`.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceWithNotifications extends Presence {\n\treadonly notifications: {\n\t\t/**\n\t\t * Acquires a Notifications workspace from store or adds new one.\n\t\t *\n\t\t * @param workspaceAddress - Address of the requested Notifications Workspace\n\t\t * @param requestedNotifications - Requested notifications for the workspace\n\t\t * @returns A Notifications workspace\n\t\t */\n\t\tgetWorkspace<NotificationsSchema extends NotificationsWorkspaceSchema>(\n\t\t\tnotificationsId: WorkspaceAddress,\n\t\t\trequestedNotifications: NotificationsSchema,\n\t\t): NotificationsWorkspace<NotificationsSchema>;\n\t};\n}\n"]}
|
|
@@ -2,53 +2,22 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import type { InboundExtensionMessage } from "@fluidframework/container-runtime-definitions/internal";
|
|
5
6
|
import type { IEmitter } from "@fluidframework/core-interfaces/internal";
|
|
6
|
-
import type { IInboundSignalMessage } from "@fluidframework/runtime-definitions/internal";
|
|
7
7
|
import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
8
8
|
import type { ClientConnectionId } from "./baseTypes.js";
|
|
9
9
|
import type { BroadcastControlSettings } from "./broadcastControls.js";
|
|
10
10
|
import type { IEphemeralRuntime } from "./internalTypes.js";
|
|
11
|
-
import type { AttendeeId, Attendee, Presence, PresenceEvents } from "./presence.js";
|
|
12
|
-
import type {
|
|
11
|
+
import type { AttendeeId, Attendee, PresenceWithNotifications as Presence, PresenceEvents } from "./presence.js";
|
|
12
|
+
import type { PresenceStatesInternal } from "./presenceStates.js";
|
|
13
|
+
import type { SignalMessages } from "./protocol.js";
|
|
13
14
|
import type { SystemWorkspaceDatastore } from "./systemWorkspace.js";
|
|
14
15
|
import type { AnyWorkspace, NotificationsWorkspace, NotificationsWorkspaceSchema, StatesWorkspace, StatesWorkspaceSchema, WorkspaceAddress } from "./types.js";
|
|
15
|
-
import type { IExtensionMessage } from "@fluidframework/presence/internal/container-definitions/internal";
|
|
16
16
|
interface AnyWorkspaceEntry<TSchema extends StatesWorkspaceSchema> {
|
|
17
17
|
public: AnyWorkspace<TSchema>;
|
|
18
18
|
internal: PresenceStatesInternal;
|
|
19
19
|
}
|
|
20
|
-
interface SystemDatastore {
|
|
21
|
-
"system:presence": SystemWorkspaceDatastore;
|
|
22
|
-
}
|
|
23
20
|
type InternalWorkspaceAddress = `${"s" | "n"}:${WorkspaceAddress}`;
|
|
24
|
-
interface GeneralDatastoreMessageContent {
|
|
25
|
-
[WorkspaceAddress: string]: {
|
|
26
|
-
[StateValueManagerKey: string]: {
|
|
27
|
-
[AttendeeId: AttendeeId]: ClientUpdateEntry;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
type DatastoreMessageContent = SystemDatastore & GeneralDatastoreMessageContent;
|
|
32
|
-
declare const datastoreUpdateMessageType = "Pres:DatastoreUpdate";
|
|
33
|
-
interface DatastoreUpdateMessage extends IInboundSignalMessage {
|
|
34
|
-
type: typeof datastoreUpdateMessageType;
|
|
35
|
-
content: {
|
|
36
|
-
sendTimestamp: number;
|
|
37
|
-
avgLatency: number;
|
|
38
|
-
isComplete?: true;
|
|
39
|
-
data: DatastoreMessageContent;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
declare const joinMessageType = "Pres:ClientJoin";
|
|
43
|
-
interface ClientJoinMessage extends IInboundSignalMessage {
|
|
44
|
-
type: typeof joinMessageType;
|
|
45
|
-
content: {
|
|
46
|
-
updateProviders: ClientConnectionId[];
|
|
47
|
-
sendTimestamp: number;
|
|
48
|
-
avgLatency: number;
|
|
49
|
-
data: DatastoreMessageContent;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
21
|
/**
|
|
53
22
|
* @internal
|
|
54
23
|
*/
|
|
@@ -56,7 +25,7 @@ export interface PresenceDatastoreManager {
|
|
|
56
25
|
joinSession(clientId: ClientConnectionId): void;
|
|
57
26
|
getWorkspace<TSchema extends StatesWorkspaceSchema>(internalWorkspaceAddress: `s:${WorkspaceAddress}`, requestedContent: TSchema, controls?: BroadcastControlSettings): StatesWorkspace<TSchema>;
|
|
58
27
|
getWorkspace<TSchema extends NotificationsWorkspaceSchema>(internalWorkspaceAddress: `n:${WorkspaceAddress}`, requestedContent: TSchema): NotificationsWorkspace<TSchema>;
|
|
59
|
-
processSignal(message:
|
|
28
|
+
processSignal(message: InboundExtensionMessage<SignalMessages>, local: boolean, optional: boolean): void;
|
|
60
29
|
}
|
|
61
30
|
/**
|
|
62
31
|
* Manages singleton datastore for all Presence.
|
|
@@ -91,7 +60,7 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
|
|
|
91
60
|
*/
|
|
92
61
|
private sendQueuedMessage;
|
|
93
62
|
private broadcastAllKnownState;
|
|
94
|
-
processSignal(message:
|
|
63
|
+
processSignal(message: InboundExtensionMessage<SignalMessages>, local: boolean, optional: boolean): void;
|
|
95
64
|
/**
|
|
96
65
|
* Handles responding to another client joining the session.
|
|
97
66
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,15 +8,15 @@ exports.PresenceDatastoreManagerImpl = void 0;
|
|
|
8
8
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
9
9
|
const internalUtils_js_1 = require("./internalUtils.js");
|
|
10
10
|
const presenceStates_js_1 = require("./presenceStates.js");
|
|
11
|
+
const protocol_js_1 = require("./protocol.js");
|
|
11
12
|
const timerManager_js_1 = require("./timerManager.js");
|
|
12
|
-
const datastoreUpdateMessageType = "Pres:DatastoreUpdate";
|
|
13
13
|
const internalWorkspaceTypes = {
|
|
14
14
|
s: "States",
|
|
15
15
|
n: "Notifications",
|
|
16
16
|
};
|
|
17
|
-
const
|
|
17
|
+
const knownMessageTypes = new Set([protocol_js_1.joinMessageType, protocol_js_1.datastoreUpdateMessageType]);
|
|
18
18
|
function isPresenceMessage(message) {
|
|
19
|
-
return message.type
|
|
19
|
+
return knownMessageTypes.has(message.type);
|
|
20
20
|
}
|
|
21
21
|
function mergeGeneralDatastoreMessageContent(base, newData) {
|
|
22
22
|
// This function-local "datastore" will hold the merged message data.
|
|
@@ -70,11 +70,14 @@ class PresenceDatastoreManagerImpl {
|
|
|
70
70
|
if (updateProviders.length > 3) {
|
|
71
71
|
updateProviders.length = 3;
|
|
72
72
|
}
|
|
73
|
-
this.runtime.submitSignal(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
this.runtime.submitSignal({
|
|
74
|
+
type: protocol_js_1.joinMessageType,
|
|
75
|
+
content: {
|
|
76
|
+
sendTimestamp: Date.now(),
|
|
77
|
+
avgLatency: this.averageLatency,
|
|
78
|
+
data: this.datastore,
|
|
79
|
+
updateProviders,
|
|
80
|
+
},
|
|
78
81
|
});
|
|
79
82
|
}
|
|
80
83
|
getWorkspace(internalWorkspaceAddress, requestedContent, controls) {
|
|
@@ -88,7 +91,7 @@ class PresenceDatastoreManagerImpl {
|
|
|
88
91
|
}
|
|
89
92
|
const localUpdate = (states, options) => {
|
|
90
93
|
// Check for connectivity before sending updates.
|
|
91
|
-
if (!this.runtime.
|
|
94
|
+
if (!this.runtime.isConnected()) {
|
|
92
95
|
return;
|
|
93
96
|
}
|
|
94
97
|
const updates = {};
|
|
@@ -151,13 +154,13 @@ class PresenceDatastoreManagerImpl {
|
|
|
151
154
|
return;
|
|
152
155
|
}
|
|
153
156
|
// Check for connectivity before sending updates.
|
|
154
|
-
if (!this.runtime.
|
|
157
|
+
if (!this.runtime.isConnected()) {
|
|
155
158
|
// Clear the queued data since we're disconnected. We don't want messages
|
|
156
159
|
// to queue infinitely while disconnected.
|
|
157
160
|
this.queuedData = undefined;
|
|
158
161
|
return;
|
|
159
162
|
}
|
|
160
|
-
const clientConnectionId = this.runtime.
|
|
163
|
+
const clientConnectionId = this.runtime.getClientId();
|
|
161
164
|
(0, internal_1.assert)(clientConnectionId !== undefined, 0xa59 /* Client connected without clientId */);
|
|
162
165
|
const currentClientToSessionValueState =
|
|
163
166
|
// When connected, `clientToSessionId` must always have current connection entry.
|
|
@@ -181,28 +184,25 @@ class PresenceDatastoreManagerImpl {
|
|
|
181
184
|
},
|
|
182
185
|
};
|
|
183
186
|
this.queuedData = undefined;
|
|
184
|
-
this.runtime.submitSignal(datastoreUpdateMessageType, newMessage);
|
|
187
|
+
this.runtime.submitSignal({ type: protocol_js_1.datastoreUpdateMessageType, content: newMessage });
|
|
185
188
|
}
|
|
186
189
|
broadcastAllKnownState() {
|
|
187
|
-
this.runtime.submitSignal(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
this.runtime.submitSignal({
|
|
191
|
+
type: protocol_js_1.datastoreUpdateMessageType,
|
|
192
|
+
content: {
|
|
193
|
+
sendTimestamp: Date.now(),
|
|
194
|
+
avgLatency: this.averageLatency,
|
|
195
|
+
isComplete: true,
|
|
196
|
+
data: this.datastore,
|
|
197
|
+
},
|
|
192
198
|
});
|
|
193
199
|
this.refreshBroadcastRequested = false;
|
|
194
200
|
}
|
|
195
|
-
processSignal(
|
|
196
|
-
// Note: IInboundSignalMessage is used here in place of IExtensionMessage
|
|
197
|
-
// as IExtensionMessage's strictly JSON `content` creates type compatibility
|
|
198
|
-
// issues with `AttendeeId` keys and really unknown value content.
|
|
199
|
-
// IExtensionMessage is a subset of IInboundSignalMessage so this is safe.
|
|
200
|
-
// Change types of DatastoreUpdateMessage | ClientJoinMessage to
|
|
201
|
-
// IExtensionMessage<> derivatives to see the issues.
|
|
202
|
-
message, local) {
|
|
201
|
+
processSignal(message, local, optional) {
|
|
203
202
|
const received = Date.now();
|
|
204
203
|
(0, internal_1.assert)(message.clientId !== null, 0xa3a /* Map received signal without clientId */);
|
|
205
204
|
if (!isPresenceMessage(message)) {
|
|
205
|
+
(0, internal_1.assert)(optional, "Unrecognized message type in critical message");
|
|
206
206
|
return;
|
|
207
207
|
}
|
|
208
208
|
if (local) {
|
|
@@ -219,18 +219,17 @@ class PresenceDatastoreManagerImpl {
|
|
|
219
219
|
}
|
|
220
220
|
const timeModifier = received -
|
|
221
221
|
(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);
|
|
222
|
-
if (message.type === joinMessageType) {
|
|
222
|
+
if (message.type === protocol_js_1.joinMessageType) {
|
|
223
223
|
// It is possible for some signals to come in while client is not connected due
|
|
224
224
|
// to how work is scheduled. If we are not connected, we can't respond to the
|
|
225
225
|
// join request. We will make our own Join request once we are connected.
|
|
226
|
-
if (this.runtime.
|
|
226
|
+
if (this.runtime.isConnected()) {
|
|
227
227
|
this.prepareJoinResponse(message.content.updateProviders, message.clientId);
|
|
228
228
|
}
|
|
229
229
|
// It is okay to continue processing the contained updates even if we are not
|
|
230
230
|
// connected.
|
|
231
231
|
}
|
|
232
232
|
else {
|
|
233
|
-
(0, internal_1.assert)(message.type === datastoreUpdateMessageType, 0xa3b /* Unexpected message type */);
|
|
234
233
|
if (message.content.isComplete) {
|
|
235
234
|
this.refreshBroadcastRequested = false;
|
|
236
235
|
}
|
|
@@ -254,7 +253,10 @@ class PresenceDatastoreManagerImpl {
|
|
|
254
253
|
this.events.emit("workspaceActivated", publicWorkspaceAddress, internalWorkspaceType);
|
|
255
254
|
}
|
|
256
255
|
const postUpdateActions = [];
|
|
257
|
-
|
|
256
|
+
// While the system workspace is processed here too, it is declared as
|
|
257
|
+
// conforming to the general schema. So drop its override.
|
|
258
|
+
const data = message.content.data;
|
|
259
|
+
for (const [workspaceAddress, remoteDatastore] of Object.entries(data)) {
|
|
258
260
|
// Direct to the appropriate Presence Workspace, if present.
|
|
259
261
|
const workspace = this.workspaces.get(workspaceAddress);
|
|
260
262
|
if (workspace) {
|
|
@@ -290,7 +292,7 @@ class PresenceDatastoreManagerImpl {
|
|
|
290
292
|
// We must be connected to receive this message, so clientId should be defined.
|
|
291
293
|
// If it isn't then, not really a problem; just won't be in provider or quorum list.
|
|
292
294
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
293
|
-
const clientId = this.runtime.
|
|
295
|
+
const clientId = this.runtime.getClientId();
|
|
294
296
|
// const requestor = message.clientId;
|
|
295
297
|
if (updateProviders.includes(clientId)) {
|
|
296
298
|
// Send all current state to the new client
|
|
@@ -333,7 +335,7 @@ class PresenceDatastoreManagerImpl {
|
|
|
333
335
|
setTimeout(() => {
|
|
334
336
|
// Make sure a broadcast is still needed and we are currently connected.
|
|
335
337
|
// If not connected, nothing we can do.
|
|
336
|
-
if (this.refreshBroadcastRequested && this.runtime.
|
|
338
|
+
if (this.refreshBroadcastRequested && this.runtime.isConnected()) {
|
|
337
339
|
this.broadcastAllKnownState();
|
|
338
340
|
this.logger?.sendTelemetryEvent({
|
|
339
341
|
eventName: "JoinResponse",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceDatastoreManager.js","sourceRoot":"","sources":["../src/presenceDatastoreManager.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 type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IInboundSignalMessage } from \"@fluidframework/runtime-definitions/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime, PostUpdateAction } from \"./internalTypes.js\";\nimport { objectEntries } from \"./internalUtils.js\";\nimport type { AttendeeId, Attendee, Presence, PresenceEvents } from \"./presence.js\";\nimport type {\n\tClientUpdateEntry,\n\tRuntimeLocalUpdateOptions,\n\tPresenceStatesInternal,\n\tValueElementMap,\n} from \"./presenceStates.js\";\nimport {\n\tcreatePresenceStates,\n\tmergeUntrackedDatastore,\n\tmergeValueDirectory,\n} from \"./presenceStates.js\";\nimport type { SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { TimerManager } from \"./timerManager.js\";\nimport type {\n\tAnyWorkspace,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\nimport type { IExtensionMessage } from \"@fluidframework/presence/internal/container-definitions/internal\";\n\ninterface AnyWorkspaceEntry<TSchema extends StatesWorkspaceSchema> {\n\tpublic: AnyWorkspace<TSchema>;\n\tinternal: PresenceStatesInternal;\n}\n\ninterface SystemDatastore {\n\t\"system:presence\": SystemWorkspaceDatastore;\n}\n\ntype InternalWorkspaceAddress = `${\"s\" | \"n\"}:${WorkspaceAddress}`;\n\ntype PresenceDatastore = SystemDatastore & {\n\t[WorkspaceAddress: string]: ValueElementMap<StatesWorkspaceSchema>;\n};\n\ninterface GeneralDatastoreMessageContent {\n\t[WorkspaceAddress: string]: {\n\t\t[StateValueManagerKey: string]: {\n\t\t\t[AttendeeId: AttendeeId]: ClientUpdateEntry;\n\t\t};\n\t};\n}\n\ntype DatastoreMessageContent = SystemDatastore & GeneralDatastoreMessageContent;\n\nconst datastoreUpdateMessageType = \"Pres:DatastoreUpdate\";\n\nconst internalWorkspaceTypes: Readonly<Record<string, \"States\" | \"Notifications\">> = {\n\ts: \"States\",\n\tn: \"Notifications\",\n} as const;\n\ninterface DatastoreUpdateMessage extends IInboundSignalMessage {\n\ttype: typeof datastoreUpdateMessageType;\n\tcontent: {\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tisComplete?: true;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nconst joinMessageType = \"Pres:ClientJoin\";\ninterface ClientJoinMessage extends IInboundSignalMessage {\n\ttype: typeof joinMessageType;\n\tcontent: {\n\t\tupdateProviders: ClientConnectionId[];\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nfunction isPresenceMessage(\n\tmessage: IInboundSignalMessage,\n): message is DatastoreUpdateMessage | ClientJoinMessage {\n\treturn message.type.startsWith(\"Pres:\");\n}\n/**\n * @internal\n */\nexport interface PresenceDatastoreManager {\n\tjoinSession(clientId: ClientConnectionId): void;\n\tgetWorkspace<TSchema extends StatesWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: `s:${WorkspaceAddress}`,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): StatesWorkspace<TSchema>;\n\tgetWorkspace<TSchema extends NotificationsWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: `n:${WorkspaceAddress}`,\n\t\trequestedContent: TSchema,\n\t): NotificationsWorkspace<TSchema>;\n\tprocessSignal(message: IExtensionMessage, local: boolean): void;\n}\n\nfunction mergeGeneralDatastoreMessageContent(\n\tbase: GeneralDatastoreMessageContent | undefined,\n\tnewData: GeneralDatastoreMessageContent,\n): GeneralDatastoreMessageContent {\n\t// This function-local \"datastore\" will hold the merged message data.\n\tconst queueDatastore = base ?? {};\n\n\t// Merge the current data with the existing data, if any exists.\n\t// Iterate over the current message data; individual items are workspaces.\n\tfor (const [workspaceName, workspaceData] of Object.entries(newData)) {\n\t\t// Initialize the merged data as the queued datastore entry for the workspace.\n\t\t// Since the key might not exist, create an empty object in that case. It will\n\t\t// be set explicitly after the loop.\n\t\tconst mergedData = queueDatastore[workspaceName] ?? {};\n\n\t\t// Iterate over each value manager and its data, merging it as needed.\n\t\tfor (const [valueManagerKey, valueManagerValue] of objectEntries(workspaceData)) {\n\t\t\tfor (const [attendeeId, value] of objectEntries(valueManagerValue)) {\n\t\t\t\tconst mergeObject = (mergedData[valueManagerKey] ??= {});\n\t\t\t\tconst oldData = mergeObject[attendeeId];\n\t\t\t\tmergeObject[attendeeId] = mergeValueDirectory(\n\t\t\t\t\toldData,\n\t\t\t\t\tvalue,\n\t\t\t\t\t0, // local values do not need a time shift\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Store the merged data in the function-local queue workspace. The whole contents of this\n\t\t// datastore will be sent as the message data.\n\t\tqueueDatastore[workspaceName] = mergedData;\n\t}\n\treturn queueDatastore;\n}\n\n/**\n * Manages singleton datastore for all Presence.\n */\nexport class PresenceDatastoreManagerImpl implements PresenceDatastoreManager {\n\tprivate readonly datastore: PresenceDatastore;\n\tprivate averageLatency = 0;\n\tprivate returnedMessages = 0;\n\tprivate refreshBroadcastRequested = false;\n\tprivate readonly timer = new TimerManager();\n\tprivate readonly workspaces = new Map<string, AnyWorkspaceEntry<StatesWorkspaceSchema>>();\n\n\tpublic constructor(\n\t\tprivate readonly attendeeId: AttendeeId,\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tprivate readonly lookupClient: (clientId: AttendeeId) => Attendee,\n\t\tprivate readonly logger: ITelemetryLoggerExt | undefined,\n\t\tprivate readonly events: IEmitter<PresenceEvents>,\n\t\tprivate readonly presence: Presence,\n\t\tsystemWorkspaceDatastore: SystemWorkspaceDatastore,\n\t\tsystemWorkspace: AnyWorkspaceEntry<StatesWorkspaceSchema>,\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tthis.datastore = { \"system:presence\": systemWorkspaceDatastore } as PresenceDatastore;\n\t\tthis.workspaces.set(\"system:presence\", systemWorkspace);\n\t}\n\n\tpublic joinSession(clientId: ClientConnectionId): void {\n\t\t// Broadcast join message to all clients\n\t\tconst updateProviders = [...this.runtime.getQuorum().getMembers().keys()].filter(\n\t\t\t(quorumClientId) => quorumClientId !== clientId,\n\t\t);\n\t\t// Limit to three providers to prevent flooding the network.\n\t\t// If none respond, others present will (should) after a delay.\n\t\tif (updateProviders.length > 3) {\n\t\t\tupdateProviders.length = 3;\n\t\t}\n\t\tthis.runtime.submitSignal(joinMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tdata: this.datastore,\n\t\t\tupdateProviders,\n\t\t} satisfies ClientJoinMessage[\"content\"]);\n\t}\n\n\tpublic getWorkspace<TSchema extends StatesWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): AnyWorkspace<TSchema> {\n\t\tconst existing = this.workspaces.get(internalWorkspaceAddress);\n\t\tif (existing) {\n\t\t\treturn existing.internal.ensureContent(requestedContent, controls);\n\t\t}\n\n\t\tlet workspaceDatastore: ValueElementMap<StatesWorkspaceSchema> | undefined =\n\t\t\tthis.datastore[internalWorkspaceAddress];\n\t\tif (workspaceDatastore === undefined) {\n\t\t\tworkspaceDatastore = this.datastore[internalWorkspaceAddress] = {};\n\t\t}\n\n\t\tconst localUpdate = (\n\t\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\t\toptions: RuntimeLocalUpdateOptions,\n\t\t): void => {\n\t\t\t// Check for connectivity before sending updates.\n\t\t\tif (!this.runtime.connected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updates: GeneralDatastoreMessageContent[InternalWorkspaceAddress] = {};\n\t\t\tfor (const [key, value] of Object.entries(states)) {\n\t\t\t\tupdates[key] = { [this.attendeeId]: value };\n\t\t\t}\n\n\t\t\tthis.enqueueMessage(\n\t\t\t\t{\n\t\t\t\t\t[internalWorkspaceAddress]: updates,\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t};\n\n\t\tconst entry = createPresenceStates(\n\t\t\t{\n\t\t\t\tpresence: this.presence,\n\t\t\t\tattendeeId: this.attendeeId,\n\t\t\t\tlookupClient: this.lookupClient,\n\t\t\t\tlocalUpdate,\n\t\t\t},\n\t\t\tworkspaceDatastore,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\n\t\tthis.workspaces.set(internalWorkspaceAddress, entry);\n\t\treturn entry.public;\n\t}\n\n\t/**\n\t * The combined contents of all queued updates. Will be undefined when no messages are queued.\n\t */\n\tprivate queuedData: GeneralDatastoreMessageContent | undefined;\n\n\t/**\n\t * Enqueues a new message to be sent. The message may be queued or may be sent immediately depending on the state of\n\t * the send timer, other messages in the queue, the configured allowed latency, etc.\n\t */\n\tprivate enqueueMessage(\n\t\tdata: GeneralDatastoreMessageContent,\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void {\n\t\t// Merging the message with any queued messages effectively queues the message.\n\t\t// It is OK to queue all incoming messages as long as when we send, we send the queued data.\n\t\tthis.queuedData = mergeGeneralDatastoreMessageContent(this.queuedData, data);\n\n\t\tconst { allowableUpdateLatencyMs } = options;\n\t\tconst now = Date.now();\n\t\tconst thisMessageDeadline = now + allowableUpdateLatencyMs;\n\n\t\tif (\n\t\t\t// If the timer has not expired, we can short-circuit because the timer will fire\n\t\t\t// and cover this update. In other words, queuing this will be fast enough to\n\t\t\t// meet its deadline, because a timer is already scheduled to fire before its deadline.\n\t\t\t!this.timer.hasExpired() &&\n\t\t\t// If the deadline for this message is later than the overall send deadline, then\n\t\t\t// we can exit early since a timer will take care of sending it.\n\t\t\tthisMessageDeadline >= this.timer.expireTime\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Either we need to send this message immediately, or we need to schedule a timer\n\t\t// to fire at the send deadline that will take care of it.\n\n\t\t// Note that timeoutInMs === allowableUpdateLatency, but the calculation is done this way for clarity.\n\t\tconst timeoutInMs = thisMessageDeadline - now;\n\t\tconst scheduleForLater = timeoutInMs > 0;\n\n\t\tif (scheduleForLater) {\n\t\t\t// Schedule the queued messages to be sent at the updateDeadline\n\t\t\tthis.timer.setTimeout(this.sendQueuedMessage.bind(this), timeoutInMs);\n\t\t} else {\n\t\t\tthis.sendQueuedMessage();\n\t\t}\n\t}\n\n\t/**\n\t * Send any queued signal immediately. Does nothing if no message is queued.\n\t */\n\tprivate sendQueuedMessage(): void {\n\t\tthis.timer.clearTimeout();\n\n\t\tif (this.queuedData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check for connectivity before sending updates.\n\t\tif (!this.runtime.connected) {\n\t\t\t// Clear the queued data since we're disconnected. We don't want messages\n\t\t\t// to queue infinitely while disconnected.\n\t\t\tthis.queuedData = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tconst clientConnectionId = this.runtime.clientId;\n\t\tassert(clientConnectionId !== undefined, 0xa59 /* Client connected without clientId */);\n\t\tconst currentClientToSessionValueState =\n\t\t\t// When connected, `clientToSessionId` must always have current connection entry.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tthis.datastore[\"system:presence\"].clientToSessionId[clientConnectionId]!;\n\n\t\tconst newMessage = {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\t// isComplete: false,\n\t\t\tdata: {\n\t\t\t\t// Always send current connection mapping for some resiliency against\n\t\t\t\t// lost signals. This ensures that client session id found in `updates`\n\t\t\t\t// (which is this client's client session id) is always represented in\n\t\t\t\t// system workspace of recipient clients.\n\t\t\t\t\"system:presence\": {\n\t\t\t\t\tclientToSessionId: {\n\t\t\t\t\t\t[clientConnectionId]: { ...currentClientToSessionValueState },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...this.queuedData,\n\t\t\t},\n\t\t} satisfies DatastoreUpdateMessage[\"content\"];\n\t\tthis.queuedData = undefined;\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, newMessage);\n\t}\n\n\tprivate broadcastAllKnownState(): void {\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tisComplete: true,\n\t\t\tdata: this.datastore,\n\t\t} satisfies DatastoreUpdateMessage[\"content\"]);\n\t\tthis.refreshBroadcastRequested = false;\n\t}\n\n\tpublic processSignal(\n\t\t// Note: IInboundSignalMessage is used here in place of IExtensionMessage\n\t\t// as IExtensionMessage's strictly JSON `content` creates type compatibility\n\t\t// issues with `AttendeeId` keys and really unknown value content.\n\t\t// IExtensionMessage is a subset of IInboundSignalMessage so this is safe.\n\t\t// Change types of DatastoreUpdateMessage | ClientJoinMessage to\n\t\t// IExtensionMessage<> derivatives to see the issues.\n\t\tmessage: IInboundSignalMessage | DatastoreUpdateMessage | ClientJoinMessage,\n\t\tlocal: boolean,\n\t): void {\n\t\tconst received = Date.now();\n\t\tassert(message.clientId !== null, 0xa3a /* Map received signal without clientId */);\n\t\tif (!isPresenceMessage(message)) {\n\t\t\treturn;\n\t\t}\n\t\tif (local) {\n\t\t\tconst deliveryDelta = received - message.content.sendTimestamp;\n\t\t\t// Limit returnedMessages count to 256 such that newest message\n\t\t\t// always contributes at least 1/256th to the average. Older\n\t\t\t// messages have more weight, but that diminishes as new messages\n\t\t\t// contribute.\n\t\t\tthis.returnedMessages = Math.min(this.returnedMessages + 1, 256);\n\t\t\tthis.averageLatency =\n\t\t\t\t(this.averageLatency * (this.returnedMessages - 1) + deliveryDelta) /\n\t\t\t\tthis.returnedMessages;\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeModifier =\n\t\t\treceived -\n\t\t\t(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);\n\n\t\tif (message.type === joinMessageType) {\n\t\t\t// It is possible for some signals to come in while client is not connected due\n\t\t\t// to how work is scheduled. If we are not connected, we can't respond to the\n\t\t\t// join request. We will make our own Join request once we are connected.\n\t\t\tif (this.runtime.connected) {\n\t\t\t\tthis.prepareJoinResponse(message.content.updateProviders, message.clientId);\n\t\t\t}\n\t\t\t// It is okay to continue processing the contained updates even if we are not\n\t\t\t// connected.\n\t\t} else {\n\t\t\tassert(message.type === datastoreUpdateMessageType, 0xa3b /* Unexpected message type */);\n\t\t\tif (message.content.isComplete) {\n\t\t\t\tthis.refreshBroadcastRequested = false;\n\t\t\t}\n\t\t}\n\n\t\t// Handle activation of unregistered workspaces before processing updates.\n\t\tfor (const [workspaceAddress] of Object.entries(message.content.data)) {\n\t\t\t// The first part of OR condition checks if workspace is already registered.\n\t\t\t// The second part checks if the workspace has already been seen before.\n\t\t\t// In either case we can skip emitting 'workspaceActivated' event.\n\t\t\tif (this.workspaces.has(workspaceAddress) || this.datastore[workspaceAddress]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Separate internal type prefix from public workspace address\n\t\t\tconst match = workspaceAddress.match(/^([^:]):([^:]+:.+)$/) as\n\t\t\t\t| null\n\t\t\t\t| [string, string, WorkspaceAddress];\n\n\t\t\tif (match === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst prefix = match[1];\n\t\t\tconst publicWorkspaceAddress = match[2];\n\n\t\t\tconst internalWorkspaceType = internalWorkspaceTypes[prefix] ?? \"Unknown\";\n\n\t\t\tthis.events.emit(\"workspaceActivated\", publicWorkspaceAddress, internalWorkspaceType);\n\t\t}\n\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [workspaceAddress, remoteDatastore] of Object.entries(message.content.data)) {\n\t\t\t// Direct to the appropriate Presence Workspace, if present.\n\t\t\tconst workspace = this.workspaces.get(workspaceAddress);\n\t\t\tif (workspace) {\n\t\t\t\tpostUpdateActions.push(\n\t\t\t\t\t...workspace.internal.processUpdate(\n\t\t\t\t\t\treceived,\n\t\t\t\t\t\ttimeModifier,\n\t\t\t\t\t\tremoteDatastore,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// All broadcast state is kept even if not currently registered, unless a value\n\t\t\t\t// notes itself to be ignored.\n\n\t\t\t\t// Ensure there is a datastore at this address and get it.\n\t\t\t\tconst workspaceDatastore = (this.datastore[workspaceAddress] ??= {});\n\t\t\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, workspaceDatastore, timeModifier);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\t/**\n\t * Handles responding to another client joining the session.\n\t *\n\t * @param updateProviders - list of client connection id's that requestor selected\n\t * to provide response\n\t * @param requestor - `requestor` is only used in telemetry. While it is the requestor's\n\t * client connection id, that is not most important. It is important that this is a\n\t * unique shared id across all clients that might respond as we want to monitor the\n\t * response patterns. The convenience of being client connection id will allow\n\t * correlation with other telemetry where it is often called just `clientId`.\n\t */\n\tprivate prepareJoinResponse(\n\t\tupdateProviders: ClientConnectionId[],\n\t\trequestor: ClientConnectionId,\n\t): void {\n\t\tthis.refreshBroadcastRequested = true;\n\t\t// We must be connected to receive this message, so clientId should be defined.\n\t\t// If it isn't then, not really a problem; just won't be in provider or quorum list.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst clientId = this.runtime.clientId!;\n\t\t// const requestor = message.clientId;\n\t\tif (updateProviders.includes(clientId)) {\n\t\t\t// Send all current state to the new client\n\t\t\tthis.broadcastAllKnownState();\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\tdetails: {\n\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\trequestor,\n\t\t\t\t\trole: \"primary\",\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Schedule a broadcast to the new client after a delay only to send if\n\t\t\t// another broadcast hasn't been seen in the meantime. The delay is based\n\t\t\t// on the position in the quorum list. It doesn't have to be a stable\n\t\t\t// list across all clients. We need something to provide suggested order\n\t\t\t// to prevent a flood of broadcasts.\n\t\t\tlet relativeResponseOrder;\n\t\t\tconst quorumMembers = this.runtime.getQuorum().getMembers();\n\t\t\tconst self = quorumMembers.get(clientId);\n\t\t\tif (self) {\n\t\t\t\t// Compute order quorum join order (indicated by sequenceNumber)\n\t\t\t\trelativeResponseOrder = 0;\n\t\t\t\tfor (const { sequenceNumber } of quorumMembers.values()) {\n\t\t\t\t\tif (sequenceNumber < self.sequenceNumber) {\n\t\t\t\t\t\trelativeResponseOrder++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Order past quorum members + arbitrary additional offset up to 10\n\t\t\t\trelativeResponseOrder = quorumMembers.size + Math.random() * 10;\n\t\t\t}\n\t\t\t// These numbers have been chosen arbitrarily to start with.\n\t\t\t// 20 is minimum wait time, 20 is the additional wait time per provider\n\t\t\t// given an chance before us with named providers given more time.\n\t\t\tconst waitTime = 20 + 20 * (3 * updateProviders.length + relativeResponseOrder);\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Make sure a broadcast is still needed and we are currently connected.\n\t\t\t\t// If not connected, nothing we can do.\n\t\t\t\tif (this.refreshBroadcastRequested && this.runtime.connected) {\n\t\t\t\t\tthis.broadcastAllKnownState();\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\t\t\trequestor,\n\t\t\t\t\t\t\trole: \"secondary\",\n\t\t\t\t\t\t\torder: relativeResponseOrder,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, waitTime);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presenceDatastoreManager.js","sourceRoot":"","sources":["../src/presenceDatastoreManager.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 type { InboundExtensionMessage } from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime, PostUpdateAction } from \"./internalTypes.js\";\nimport { objectEntries } from \"./internalUtils.js\";\nimport type {\n\tAttendeeId,\n\tAttendee,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport type {\n\tClientUpdateEntry,\n\tRuntimeLocalUpdateOptions,\n\tPresenceStatesInternal,\n\tValueElementMap,\n} from \"./presenceStates.js\";\nimport {\n\tcreatePresenceStates,\n\tmergeUntrackedDatastore,\n\tmergeValueDirectory,\n} from \"./presenceStates.js\";\nimport type {\n\tGeneralDatastoreMessageContent,\n\tInboundClientJoinMessage,\n\tInboundDatastoreUpdateMessage,\n\tOutboundDatastoreUpdateMessage,\n\tSignalMessages,\n\tSystemDatastore,\n} from \"./protocol.js\";\nimport { datastoreUpdateMessageType, joinMessageType } from \"./protocol.js\";\nimport type { SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { TimerManager } from \"./timerManager.js\";\nimport type {\n\tAnyWorkspace,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\ninterface AnyWorkspaceEntry<TSchema extends StatesWorkspaceSchema> {\n\tpublic: AnyWorkspace<TSchema>;\n\tinternal: PresenceStatesInternal;\n}\n\ntype PresenceDatastore = SystemDatastore & {\n\t[WorkspaceAddress: string]: ValueElementMap<StatesWorkspaceSchema>;\n};\n\ntype InternalWorkspaceAddress = `${\"s\" | \"n\"}:${WorkspaceAddress}`;\n\nconst internalWorkspaceTypes: Readonly<Record<string, \"States\" | \"Notifications\">> = {\n\ts: \"States\",\n\tn: \"Notifications\",\n} as const;\n\nconst knownMessageTypes = new Set([joinMessageType, datastoreUpdateMessageType]);\nfunction isPresenceMessage(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): message is InboundDatastoreUpdateMessage | InboundClientJoinMessage {\n\treturn knownMessageTypes.has(message.type);\n}\n\n/**\n * @internal\n */\nexport interface PresenceDatastoreManager {\n\tjoinSession(clientId: ClientConnectionId): void;\n\tgetWorkspace<TSchema extends StatesWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: `s:${WorkspaceAddress}`,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): StatesWorkspace<TSchema>;\n\tgetWorkspace<TSchema extends NotificationsWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: `n:${WorkspaceAddress}`,\n\t\trequestedContent: TSchema,\n\t): NotificationsWorkspace<TSchema>;\n\tprocessSignal(\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t\toptional: boolean,\n\t): void;\n}\n\nfunction mergeGeneralDatastoreMessageContent(\n\tbase: GeneralDatastoreMessageContent | undefined,\n\tnewData: GeneralDatastoreMessageContent,\n): GeneralDatastoreMessageContent {\n\t// This function-local \"datastore\" will hold the merged message data.\n\tconst queueDatastore = base ?? {};\n\n\t// Merge the current data with the existing data, if any exists.\n\t// Iterate over the current message data; individual items are workspaces.\n\tfor (const [workspaceName, workspaceData] of Object.entries(newData)) {\n\t\t// Initialize the merged data as the queued datastore entry for the workspace.\n\t\t// Since the key might not exist, create an empty object in that case. It will\n\t\t// be set explicitly after the loop.\n\t\tconst mergedData = queueDatastore[workspaceName] ?? {};\n\n\t\t// Iterate over each value manager and its data, merging it as needed.\n\t\tfor (const [valueManagerKey, valueManagerValue] of objectEntries(workspaceData)) {\n\t\t\tfor (const [attendeeId, value] of objectEntries(valueManagerValue)) {\n\t\t\t\tconst mergeObject = (mergedData[valueManagerKey] ??= {});\n\t\t\t\tconst oldData = mergeObject[attendeeId];\n\t\t\t\tmergeObject[attendeeId] = mergeValueDirectory(\n\t\t\t\t\toldData,\n\t\t\t\t\tvalue,\n\t\t\t\t\t0, // local values do not need a time shift\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Store the merged data in the function-local queue workspace. The whole contents of this\n\t\t// datastore will be sent as the message data.\n\t\tqueueDatastore[workspaceName] = mergedData;\n\t}\n\treturn queueDatastore;\n}\n\n/**\n * Manages singleton datastore for all Presence.\n */\nexport class PresenceDatastoreManagerImpl implements PresenceDatastoreManager {\n\tprivate readonly datastore: PresenceDatastore;\n\tprivate averageLatency = 0;\n\tprivate returnedMessages = 0;\n\tprivate refreshBroadcastRequested = false;\n\tprivate readonly timer = new TimerManager();\n\tprivate readonly workspaces = new Map<string, AnyWorkspaceEntry<StatesWorkspaceSchema>>();\n\n\tpublic constructor(\n\t\tprivate readonly attendeeId: AttendeeId,\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tprivate readonly lookupClient: (clientId: AttendeeId) => Attendee,\n\t\tprivate readonly logger: ITelemetryLoggerExt | undefined,\n\t\tprivate readonly events: IEmitter<PresenceEvents>,\n\t\tprivate readonly presence: Presence,\n\t\tsystemWorkspaceDatastore: SystemWorkspaceDatastore,\n\t\tsystemWorkspace: AnyWorkspaceEntry<StatesWorkspaceSchema>,\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tthis.datastore = { \"system:presence\": systemWorkspaceDatastore } as PresenceDatastore;\n\t\tthis.workspaces.set(\"system:presence\", systemWorkspace);\n\t}\n\n\tpublic joinSession(clientId: ClientConnectionId): void {\n\t\t// Broadcast join message to all clients\n\t\tconst updateProviders = [...this.runtime.getQuorum().getMembers().keys()].filter(\n\t\t\t(quorumClientId) => quorumClientId !== clientId,\n\t\t);\n\t\t// Limit to three providers to prevent flooding the network.\n\t\t// If none respond, others present will (should) after a delay.\n\t\tif (updateProviders.length > 3) {\n\t\t\tupdateProviders.length = 3;\n\t\t}\n\t\tthis.runtime.submitSignal({\n\t\t\ttype: joinMessageType,\n\t\t\tcontent: {\n\t\t\t\tsendTimestamp: Date.now(),\n\t\t\t\tavgLatency: this.averageLatency,\n\t\t\t\tdata: this.datastore,\n\t\t\t\tupdateProviders,\n\t\t\t},\n\t\t});\n\t}\n\n\tpublic getWorkspace<TSchema extends StatesWorkspaceSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): AnyWorkspace<TSchema> {\n\t\tconst existing = this.workspaces.get(internalWorkspaceAddress);\n\t\tif (existing) {\n\t\t\treturn existing.internal.ensureContent(requestedContent, controls);\n\t\t}\n\n\t\tlet workspaceDatastore: ValueElementMap<StatesWorkspaceSchema> | undefined =\n\t\t\tthis.datastore[internalWorkspaceAddress];\n\t\tif (workspaceDatastore === undefined) {\n\t\t\tworkspaceDatastore = this.datastore[internalWorkspaceAddress] = {};\n\t\t}\n\n\t\tconst localUpdate = (\n\t\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\t\toptions: RuntimeLocalUpdateOptions,\n\t\t): void => {\n\t\t\t// Check for connectivity before sending updates.\n\t\t\tif (!this.runtime.isConnected()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updates: GeneralDatastoreMessageContent[InternalWorkspaceAddress] = {};\n\t\t\tfor (const [key, value] of Object.entries(states)) {\n\t\t\t\tupdates[key] = { [this.attendeeId]: value };\n\t\t\t}\n\n\t\t\tthis.enqueueMessage(\n\t\t\t\t{\n\t\t\t\t\t[internalWorkspaceAddress]: updates,\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t};\n\n\t\tconst entry = createPresenceStates(\n\t\t\t{\n\t\t\t\tpresence: this.presence,\n\t\t\t\tattendeeId: this.attendeeId,\n\t\t\t\tlookupClient: this.lookupClient,\n\t\t\t\tlocalUpdate,\n\t\t\t},\n\t\t\tworkspaceDatastore,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\n\t\tthis.workspaces.set(internalWorkspaceAddress, entry);\n\t\treturn entry.public;\n\t}\n\n\t/**\n\t * The combined contents of all queued updates. Will be undefined when no messages are queued.\n\t */\n\tprivate queuedData: GeneralDatastoreMessageContent | undefined;\n\n\t/**\n\t * Enqueues a new message to be sent. The message may be queued or may be sent immediately depending on the state of\n\t * the send timer, other messages in the queue, the configured allowed latency, etc.\n\t */\n\tprivate enqueueMessage(\n\t\tdata: GeneralDatastoreMessageContent,\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void {\n\t\t// Merging the message with any queued messages effectively queues the message.\n\t\t// It is OK to queue all incoming messages as long as when we send, we send the queued data.\n\t\tthis.queuedData = mergeGeneralDatastoreMessageContent(this.queuedData, data);\n\n\t\tconst { allowableUpdateLatencyMs } = options;\n\t\tconst now = Date.now();\n\t\tconst thisMessageDeadline = now + allowableUpdateLatencyMs;\n\n\t\tif (\n\t\t\t// If the timer has not expired, we can short-circuit because the timer will fire\n\t\t\t// and cover this update. In other words, queuing this will be fast enough to\n\t\t\t// meet its deadline, because a timer is already scheduled to fire before its deadline.\n\t\t\t!this.timer.hasExpired() &&\n\t\t\t// If the deadline for this message is later than the overall send deadline, then\n\t\t\t// we can exit early since a timer will take care of sending it.\n\t\t\tthisMessageDeadline >= this.timer.expireTime\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Either we need to send this message immediately, or we need to schedule a timer\n\t\t// to fire at the send deadline that will take care of it.\n\n\t\t// Note that timeoutInMs === allowableUpdateLatency, but the calculation is done this way for clarity.\n\t\tconst timeoutInMs = thisMessageDeadline - now;\n\t\tconst scheduleForLater = timeoutInMs > 0;\n\n\t\tif (scheduleForLater) {\n\t\t\t// Schedule the queued messages to be sent at the updateDeadline\n\t\t\tthis.timer.setTimeout(this.sendQueuedMessage.bind(this), timeoutInMs);\n\t\t} else {\n\t\t\tthis.sendQueuedMessage();\n\t\t}\n\t}\n\n\t/**\n\t * Send any queued signal immediately. Does nothing if no message is queued.\n\t */\n\tprivate sendQueuedMessage(): void {\n\t\tthis.timer.clearTimeout();\n\n\t\tif (this.queuedData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check for connectivity before sending updates.\n\t\tif (!this.runtime.isConnected()) {\n\t\t\t// Clear the queued data since we're disconnected. We don't want messages\n\t\t\t// to queue infinitely while disconnected.\n\t\t\tthis.queuedData = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tconst clientConnectionId = this.runtime.getClientId();\n\t\tassert(clientConnectionId !== undefined, 0xa59 /* Client connected without clientId */);\n\t\tconst currentClientToSessionValueState =\n\t\t\t// When connected, `clientToSessionId` must always have current connection entry.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tthis.datastore[\"system:presence\"].clientToSessionId[clientConnectionId]!;\n\n\t\tconst newMessage = {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\t// isComplete: false,\n\t\t\tdata: {\n\t\t\t\t// Always send current connection mapping for some resiliency against\n\t\t\t\t// lost signals. This ensures that client session id found in `updates`\n\t\t\t\t// (which is this client's client session id) is always represented in\n\t\t\t\t// system workspace of recipient clients.\n\t\t\t\t\"system:presence\": {\n\t\t\t\t\tclientToSessionId: {\n\t\t\t\t\t\t[clientConnectionId]: { ...currentClientToSessionValueState },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...this.queuedData,\n\t\t\t},\n\t\t} satisfies OutboundDatastoreUpdateMessage[\"content\"];\n\t\tthis.queuedData = undefined;\n\t\tthis.runtime.submitSignal({ type: datastoreUpdateMessageType, content: newMessage });\n\t}\n\n\tprivate broadcastAllKnownState(): void {\n\t\tthis.runtime.submitSignal({\n\t\t\ttype: datastoreUpdateMessageType,\n\t\t\tcontent: {\n\t\t\t\tsendTimestamp: Date.now(),\n\t\t\t\tavgLatency: this.averageLatency,\n\t\t\t\tisComplete: true,\n\t\t\t\tdata: this.datastore,\n\t\t\t},\n\t\t});\n\t\tthis.refreshBroadcastRequested = false;\n\t}\n\n\tpublic processSignal(\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t\toptional: boolean,\n\t): void {\n\t\tconst received = Date.now();\n\t\tassert(message.clientId !== null, 0xa3a /* Map received signal without clientId */);\n\t\tif (!isPresenceMessage(message)) {\n\t\t\tassert(optional, \"Unrecognized message type in critical message\");\n\t\t\treturn;\n\t\t}\n\t\tif (local) {\n\t\t\tconst deliveryDelta = received - message.content.sendTimestamp;\n\t\t\t// Limit returnedMessages count to 256 such that newest message\n\t\t\t// always contributes at least 1/256th to the average. Older\n\t\t\t// messages have more weight, but that diminishes as new messages\n\t\t\t// contribute.\n\t\t\tthis.returnedMessages = Math.min(this.returnedMessages + 1, 256);\n\t\t\tthis.averageLatency =\n\t\t\t\t(this.averageLatency * (this.returnedMessages - 1) + deliveryDelta) /\n\t\t\t\tthis.returnedMessages;\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeModifier =\n\t\t\treceived -\n\t\t\t(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);\n\n\t\tif (message.type === joinMessageType) {\n\t\t\t// It is possible for some signals to come in while client is not connected due\n\t\t\t// to how work is scheduled. If we are not connected, we can't respond to the\n\t\t\t// join request. We will make our own Join request once we are connected.\n\t\t\tif (this.runtime.isConnected()) {\n\t\t\t\tthis.prepareJoinResponse(message.content.updateProviders, message.clientId);\n\t\t\t}\n\t\t\t// It is okay to continue processing the contained updates even if we are not\n\t\t\t// connected.\n\t\t} else {\n\t\t\tif (message.content.isComplete) {\n\t\t\t\tthis.refreshBroadcastRequested = false;\n\t\t\t}\n\t\t}\n\n\t\t// Handle activation of unregistered workspaces before processing updates.\n\t\tfor (const [workspaceAddress] of Object.entries(message.content.data)) {\n\t\t\t// The first part of OR condition checks if workspace is already registered.\n\t\t\t// The second part checks if the workspace has already been seen before.\n\t\t\t// In either case we can skip emitting 'workspaceActivated' event.\n\t\t\tif (this.workspaces.has(workspaceAddress) || this.datastore[workspaceAddress]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Separate internal type prefix from public workspace address\n\t\t\tconst match = workspaceAddress.match(/^([^:]):([^:]+:.+)$/) as\n\t\t\t\t| null\n\t\t\t\t| [string, string, WorkspaceAddress];\n\n\t\t\tif (match === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst prefix = match[1];\n\t\t\tconst publicWorkspaceAddress = match[2];\n\n\t\t\tconst internalWorkspaceType = internalWorkspaceTypes[prefix] ?? \"Unknown\";\n\n\t\t\tthis.events.emit(\"workspaceActivated\", publicWorkspaceAddress, internalWorkspaceType);\n\t\t}\n\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\t// While the system workspace is processed here too, it is declared as\n\t\t// conforming to the general schema. So drop its override.\n\t\tconst data = message.content.data as Omit<typeof message.content.data, \"system:presence\">;\n\t\tfor (const [workspaceAddress, remoteDatastore] of Object.entries(data)) {\n\t\t\t// Direct to the appropriate Presence Workspace, if present.\n\t\t\tconst workspace = this.workspaces.get(workspaceAddress);\n\t\t\tif (workspace) {\n\t\t\t\tpostUpdateActions.push(\n\t\t\t\t\t...workspace.internal.processUpdate(\n\t\t\t\t\t\treceived,\n\t\t\t\t\t\ttimeModifier,\n\t\t\t\t\t\tremoteDatastore,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// All broadcast state is kept even if not currently registered, unless a value\n\t\t\t\t// notes itself to be ignored.\n\n\t\t\t\t// Ensure there is a datastore at this address and get it.\n\t\t\t\tconst workspaceDatastore = (this.datastore[workspaceAddress] ??= {});\n\t\t\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, workspaceDatastore, timeModifier);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\t/**\n\t * Handles responding to another client joining the session.\n\t *\n\t * @param updateProviders - list of client connection id's that requestor selected\n\t * to provide response\n\t * @param requestor - `requestor` is only used in telemetry. While it is the requestor's\n\t * client connection id, that is not most important. It is important that this is a\n\t * unique shared id across all clients that might respond as we want to monitor the\n\t * response patterns. The convenience of being client connection id will allow\n\t * correlation with other telemetry where it is often called just `clientId`.\n\t */\n\tprivate prepareJoinResponse(\n\t\tupdateProviders: ClientConnectionId[],\n\t\trequestor: ClientConnectionId,\n\t): void {\n\t\tthis.refreshBroadcastRequested = true;\n\t\t// We must be connected to receive this message, so clientId should be defined.\n\t\t// If it isn't then, not really a problem; just won't be in provider or quorum list.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst clientId = this.runtime.getClientId()!;\n\t\t// const requestor = message.clientId;\n\t\tif (updateProviders.includes(clientId)) {\n\t\t\t// Send all current state to the new client\n\t\t\tthis.broadcastAllKnownState();\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\tdetails: {\n\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\trequestor,\n\t\t\t\t\trole: \"primary\",\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Schedule a broadcast to the new client after a delay only to send if\n\t\t\t// another broadcast hasn't been seen in the meantime. The delay is based\n\t\t\t// on the position in the quorum list. It doesn't have to be a stable\n\t\t\t// list across all clients. We need something to provide suggested order\n\t\t\t// to prevent a flood of broadcasts.\n\t\t\tlet relativeResponseOrder;\n\t\t\tconst quorumMembers = this.runtime.getQuorum().getMembers();\n\t\t\tconst self = quorumMembers.get(clientId);\n\t\t\tif (self) {\n\t\t\t\t// Compute order quorum join order (indicated by sequenceNumber)\n\t\t\t\trelativeResponseOrder = 0;\n\t\t\t\tfor (const { sequenceNumber } of quorumMembers.values()) {\n\t\t\t\t\tif (sequenceNumber < self.sequenceNumber) {\n\t\t\t\t\t\trelativeResponseOrder++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Order past quorum members + arbitrary additional offset up to 10\n\t\t\t\trelativeResponseOrder = quorumMembers.size + Math.random() * 10;\n\t\t\t}\n\t\t\t// These numbers have been chosen arbitrarily to start with.\n\t\t\t// 20 is minimum wait time, 20 is the additional wait time per provider\n\t\t\t// given an chance before us with named providers given more time.\n\t\t\tconst waitTime = 20 + 20 * (3 * updateProviders.length + relativeResponseOrder);\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Make sure a broadcast is still needed and we are currently connected.\n\t\t\t\t// If not connected, nothing we can do.\n\t\t\t\tif (this.refreshBroadcastRequested && this.runtime.isConnected()) {\n\t\t\t\t\tthis.broadcastAllKnownState();\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\t\t\trequestor,\n\t\t\t\t\t\t\trole: \"secondary\",\n\t\t\t\t\t\t\torder: relativeResponseOrder,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, waitTime);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
5
|
+
import type { ContainerExtension } from "@fluidframework/container-runtime-definitions/internal";
|
|
6
|
+
import type { ExtensionRuntimeProperties, IEphemeralRuntime } from "./internalTypes.js";
|
|
7
|
+
import type { AttendeeId, PresenceWithNotifications as Presence } from "./presence.js";
|
|
8
8
|
/**
|
|
9
|
-
* Portion of the container extension requirements ({@link
|
|
9
|
+
* Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.
|
|
10
10
|
*
|
|
11
11
|
* @internal
|
|
12
12
|
*/
|
|
13
|
-
export type PresenceExtensionInterface = Required<Pick<
|
|
13
|
+
export type PresenceExtensionInterface = Required<Pick<ContainerExtension<ExtensionRuntimeProperties>, "processSignal">>;
|
|
14
14
|
/**
|
|
15
15
|
* Instantiates Presence Manager
|
|
16
16
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceManager.d.ts","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"presenceManager.d.ts","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,wDAAwD,CAAC;AAWhE,OAAO,KAAK,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAEX,UAAU,EACV,yBAAyB,IAAI,QAAQ,EAErC,MAAM,eAAe,CAAC;AAcvB;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAChD,IAAI,CAAC,kBAAkB,CAAC,0BAA0B,CAAC,EAAE,eAAe,CAAC,CACrE,CAAC;AA0IF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,UAAU,GAAE,UAA4C,GACtD,QAAQ,GAAG,0BAA0B,CAEvC"}
|
package/dist/presenceManager.js
CHANGED
|
@@ -30,10 +30,11 @@ class PresenceManager {
|
|
|
30
30
|
}
|
|
31
31
|
[this.datastoreManager, this.systemWorkspace] = setupSubComponents(attendeeId, runtime, this.events, this.mc?.logger, this);
|
|
32
32
|
this.attendees = this.systemWorkspace;
|
|
33
|
-
runtime.on("connected", this.onConnect.bind(this));
|
|
34
|
-
runtime.on("disconnected", () => {
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
runtime.events.on("connected", this.onConnect.bind(this));
|
|
34
|
+
runtime.events.on("disconnected", () => {
|
|
35
|
+
const currentClientId = runtime.getClientId();
|
|
36
|
+
if (currentClientId !== undefined) {
|
|
37
|
+
this.removeClientConnectionId(currentClientId);
|
|
37
38
|
}
|
|
38
39
|
});
|
|
39
40
|
runtime.getAudience().on("removeMember", this.removeClientConnectionId.bind(this));
|
|
@@ -43,8 +44,8 @@ class PresenceManager {
|
|
|
43
44
|
// delayed we expect that "connected" event has passed.
|
|
44
45
|
// Note: In some manual testing, this does not appear to be enough to
|
|
45
46
|
// always trigger an initial connect.
|
|
46
|
-
const clientId = runtime.
|
|
47
|
-
if (clientId !== undefined && runtime.
|
|
47
|
+
const clientId = runtime.getClientId();
|
|
48
|
+
if (clientId !== undefined && runtime.isConnected()) {
|
|
48
49
|
this.onConnect(clientId);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -58,12 +59,13 @@ class PresenceManager {
|
|
|
58
59
|
/**
|
|
59
60
|
* Check for Presence message and process it.
|
|
60
61
|
*
|
|
61
|
-
* @param
|
|
62
|
-
* @param message -
|
|
62
|
+
* @param addressChain - Address chain of the message
|
|
63
|
+
* @param message - Unverified message to be processed
|
|
63
64
|
* @param local - Whether the message originated locally (`true`) or remotely (`false`)
|
|
64
65
|
*/
|
|
65
|
-
processSignal(
|
|
66
|
-
this.datastoreManager.processSignal(message, local
|
|
66
|
+
processSignal(addressChain, message, local) {
|
|
67
|
+
this.datastoreManager.processSignal(message, local,
|
|
68
|
+
/* optional */ addressChain[0] === "?");
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
/**
|