@fluid-internal/presence-runtime 2.103.0 → 2.110.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/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/runtime/extension/containerPresence.d.ts +1 -1
- package/dist/runtime/presenceManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/runtime/extension/containerPresence.d.ts +1 -1
- package/lib/runtime/presenceManager.js.map +1 -1
- package/package.json +15 -15
package/dist/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 = "@fluid-internal/presence-runtime";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.110.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluid-internal/presence-runtime";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.110.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,SAAS,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 = \"@fluid-internal/presence-runtime\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,kCAAkC,CAAC;AAC7C,QAAA,UAAU,GAAG,SAAS,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 = \"@fluid-internal/presence-runtime\";\nexport const pkgVersion = \"2.110.0\";\n"]}
|
|
@@ -13,7 +13,7 @@ import type { ExtensionHost, ExtensionRuntimeProperties } from "../runtimeTypes.
|
|
|
13
13
|
declare class ContainerPresenceManager implements ContainerExtension<ExtensionRuntimeProperties>, ReturnType<ContainerExtensionFactory<PresenceWithNotifications, ExtensionRuntimeProperties>["instantiateExtension"]> {
|
|
14
14
|
readonly compatibility: {
|
|
15
15
|
readonly generation: 1;
|
|
16
|
-
readonly version: "2.
|
|
16
|
+
readonly version: "2.110.0";
|
|
17
17
|
readonly capabilities: Set<never>;
|
|
18
18
|
};
|
|
19
19
|
readonly interface: PresenceWithNotifications;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../../src/runtime/presenceManager.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 {\n\tAttendeesEvents,\n\tAttendeeId,\n\tBroadcastControlSettings,\n\tClientConnectionId,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"@fluid-internal/presence-definitions\";\nimport type {\n\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tTelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages, SystemWorkspaceDatastore } from \"./protocol.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./runtimeTypes.js\";\nimport type { SystemWorkspace } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\n\n/**\n * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<ContainerExtension<ExtensionRuntimeProperties>, \"processSignal\">\n>;\n\n/**\n * Confirms that the message is from a client and has a clientId\n * versus from the system which specifies `null` for clientId.\n */\nfunction assertMessageIsFromAClient(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): asserts message is InboundExtensionMessage<SignalMessages> & {\n\tclientId: ClientConnectionId;\n} {\n\tassert(message.clientId !== null, 0xa3a /* Presence received signal without clientId */);\n}\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\n\tprivate joined = false;\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents & AttendeesEvents>();\n\n\tpublic readonly attendees: Presence[\"attendees\"];\n\n\tpublic readonly states = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<StatesWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema, unknown, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<NotificationsWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tattendeeId: AttendeeId,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({ logger: runtime.logger, namespace: \"Presence\" });\n\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tattendeeId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc.logger,\n\t\t\tthis,\n\t\t);\n\t\tthis.attendees = this.systemWorkspace;\n\n\t\truntime.events.on(\"disconnected\", this.onDisconnected.bind(this));\n\n\t\tconst audience = runtime.getAudience();\n\t\t// Listen for self add to Audience to indicate join (with a stable\n\t\t// audience population).\n\t\taudience.on(\"addMember\", this.addClientConnectionId.bind(this));\n\t\taudience.on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected (can send signals and complete audience)\n\t\t// at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the self-\"addMember\" event will be raised during completion. With\n\t\t// construction delayed we expect that self-\"addMember\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.getClientId();\n\t\tif (\n\t\t\tclientId !== undefined &&\n\t\t\truntime.getJoinedStatus() !== \"disconnected\" &&\n\t\t\taudience.getMember(clientId) !== undefined\n\t\t) {\n\t\t\tthis.onJoin(clientId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate addClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\t// Check specifically for self join that indicates stable audience\n\t\t// and is preferred trigger for presence join.\n\t\tif (clientConnectionId === this.runtime.getClientId()) {\n\t\t\tthis.onJoin(clientConnectionId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tprivate onJoin(\n\t\tclientConnectionId: ClientConnectionId,\n\t\talternateUpdateProvider: ClientConnectionId | undefined,\n\t): void {\n\t\t// System workspace is notified even if already \"joined\", to handle the\n\t\t// audience -> attendee status updates.\n\t\tthis.systemWorkspace.onConnectionAdded(\n\t\t\tclientConnectionId,\n\t\t\t// audienceOutOfDate - out of date when onJoin is forced by receiving\n\t\t\t// a signal (which calls with alternateUpdateProvider defined).\n\t\t\talternateUpdateProvider !== undefined,\n\t\t);\n\t\tif (!this.joined) {\n\t\t\tthis.datastoreManager.joinSession(clientConnectionId, alternateUpdateProvider);\n\t\t\tthis.joined = true;\n\t\t}\n\t}\n\n\tprivate onDisconnected(): void {\n\t\tthis.joined = false;\n\t\tconst currentClientId = this.runtime.getClientId();\n\t\tif (currentClientId !== undefined) {\n\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t}\n\t\tthis.datastoreManager.onDisconnected();\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param addressChain - Address chain of the message\n\t * @param message - Unverified message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(\n\t\taddressChain: string[],\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t): void {\n\t\tassertMessageIsFromAClient(message);\n\n\t\t// Check for undesired case of receiving a remote presence signal\n\t\t// without having been alerted to self audience join that is preferred\n\t\t// trigger for join. (Perhaps join signal was dropped.)\n\t\t// In practice it is commonly observed that local signals can be\n\t\t// returned ahead of audience join notification. So, it is reasonable\n\t\t// to expect that audience join notification may be delayed until after\n\t\t// other presence signals are received. One is enough to get things\n\t\t// rolling.\n\t\tif (!local && !this.joined) {\n\t\t\tconst selfClientId = this.runtime.getClientId();\n\t\t\tassert(selfClientId !== undefined, 0xcbf /* Received signal without clientId */);\n\t\t\tthis.onJoin(selfClientId, /* alternateUpdateProvider */ message.clientId);\n\t\t}\n\n\t\tthis.datastoreManager.processSignal(\n\t\t\tmessage,\n\t\t\tlocal,\n\t\t\t/* optional */ addressChain[0] === \"?\",\n\t\t);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tattendeeId: AttendeeId,\n\truntime: IEphemeralRuntime,\n\tevents: Listenable<PresenceEvents & AttendeesEvents> &\n\t\tIEmitter<PresenceEvents & AttendeesEvents>,\n\tlogger: TelemetryLoggerExt,\n\tpresence: Presence,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tattendeeId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tattendeeId,\n\t\truntime,\n\t\tlogger,\n\t\tevents,\n\t\tpresence,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tattendeeId: AttendeeId = createSessionId() as AttendeeId,\n): Presence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, attendeeId);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../../src/runtime/presenceManager.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 {\n\tAttendeesEvents,\n\tAttendeeId,\n\tBroadcastControlSettings,\n\tClientConnectionId,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"@fluid-internal/presence-definitions\";\nimport type {\n\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tMonitoringContext,\n\tTelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages, SystemWorkspaceDatastore } from \"./protocol.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./runtimeTypes.js\";\nimport type { SystemWorkspace } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\n\n/**\n * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<ContainerExtension<ExtensionRuntimeProperties>, \"processSignal\">\n>;\n\n/**\n * Confirms that the message is from a client and has a clientId\n * versus from the system which specifies `null` for clientId.\n */\nfunction assertMessageIsFromAClient(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): asserts message is InboundExtensionMessage<SignalMessages> & {\n\tclientId: ClientConnectionId;\n} {\n\tassert(message.clientId !== null, 0xa3a /* Presence received signal without clientId */);\n}\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\n\tprivate joined = false;\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents & AttendeesEvents>();\n\n\tpublic readonly attendees: Presence[\"attendees\"];\n\n\tpublic readonly states = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<StatesWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema, unknown, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<NotificationsWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tattendeeId: AttendeeId,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({ logger: runtime.logger, namespace: \"Presence\" });\n\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tattendeeId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc.logger,\n\t\t\tthis,\n\t\t);\n\t\tthis.attendees = this.systemWorkspace;\n\n\t\truntime.events.on(\"disconnected\", this.onDisconnected.bind(this));\n\n\t\tconst audience = runtime.getAudience();\n\t\t// Listen for self add to Audience to indicate join (with a stable\n\t\t// audience population).\n\t\taudience.on(\"addMember\", this.addClientConnectionId.bind(this));\n\t\taudience.on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected (can send signals and complete audience)\n\t\t// at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the self-\"addMember\" event will be raised during completion. With\n\t\t// construction delayed we expect that self-\"addMember\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.getClientId();\n\t\tif (\n\t\t\tclientId !== undefined &&\n\t\t\truntime.getJoinedStatus() !== \"disconnected\" &&\n\t\t\taudience.getMember(clientId) !== undefined\n\t\t) {\n\t\t\tthis.onJoin(clientId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate addClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\t// Check specifically for self join that indicates stable audience\n\t\t// and is preferred trigger for presence join.\n\t\tif (clientConnectionId === this.runtime.getClientId()) {\n\t\t\tthis.onJoin(clientConnectionId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tprivate onJoin(\n\t\tclientConnectionId: ClientConnectionId,\n\t\talternateUpdateProvider: ClientConnectionId | undefined,\n\t): void {\n\t\t// System workspace is notified even if already \"joined\", to handle the\n\t\t// audience -> attendee status updates.\n\t\tthis.systemWorkspace.onConnectionAdded(\n\t\t\tclientConnectionId,\n\t\t\t// audienceOutOfDate - out of date when onJoin is forced by receiving\n\t\t\t// a signal (which calls with alternateUpdateProvider defined).\n\t\t\talternateUpdateProvider !== undefined,\n\t\t);\n\t\tif (!this.joined) {\n\t\t\tthis.datastoreManager.joinSession(clientConnectionId, alternateUpdateProvider);\n\t\t\tthis.joined = true;\n\t\t}\n\t}\n\n\tprivate onDisconnected(): void {\n\t\tthis.joined = false;\n\t\tconst currentClientId = this.runtime.getClientId();\n\t\tif (currentClientId !== undefined) {\n\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t}\n\t\tthis.datastoreManager.onDisconnected();\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param addressChain - Address chain of the message\n\t * @param message - Unverified message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(\n\t\taddressChain: string[],\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t): void {\n\t\tassertMessageIsFromAClient(message);\n\n\t\t// Check for undesired case of receiving a remote presence signal\n\t\t// without having been alerted to self audience join that is preferred\n\t\t// trigger for join. (Perhaps join signal was dropped.)\n\t\t// In practice it is commonly observed that local signals can be\n\t\t// returned ahead of audience join notification. So, it is reasonable\n\t\t// to expect that audience join notification may be delayed until after\n\t\t// other presence signals are received. One is enough to get things\n\t\t// rolling.\n\t\tif (!local && !this.joined) {\n\t\t\tconst selfClientId = this.runtime.getClientId();\n\t\t\tassert(selfClientId !== undefined, 0xcbf /* Received signal without clientId */);\n\t\t\tthis.onJoin(selfClientId, /* alternateUpdateProvider */ message.clientId);\n\t\t}\n\n\t\tthis.datastoreManager.processSignal(\n\t\t\tmessage,\n\t\t\tlocal,\n\t\t\t/* optional */ addressChain[0] === \"?\",\n\t\t);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tattendeeId: AttendeeId,\n\truntime: IEphemeralRuntime,\n\tevents: Listenable<PresenceEvents & AttendeesEvents> &\n\t\tIEmitter<PresenceEvents & AttendeesEvents>,\n\tlogger: TelemetryLoggerExt,\n\tpresence: Presence,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tattendeeId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tattendeeId,\n\t\truntime,\n\t\tlogger,\n\t\tevents,\n\t\tpresence,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tattendeeId: AttendeeId = createSessionId() as AttendeeId,\n): Presence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, attendeeId);\n}\n"]}
|
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 = "@fluid-internal/presence-runtime";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.110.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
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,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,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 = \"@fluid-internal/presence-runtime\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,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 = \"@fluid-internal/presence-runtime\";\nexport const pkgVersion = \"2.110.0\";\n"]}
|
|
@@ -13,7 +13,7 @@ import type { ExtensionHost, ExtensionRuntimeProperties } from "../runtimeTypes.
|
|
|
13
13
|
declare class ContainerPresenceManager implements ContainerExtension<ExtensionRuntimeProperties>, ReturnType<ContainerExtensionFactory<PresenceWithNotifications, ExtensionRuntimeProperties>["instantiateExtension"]> {
|
|
14
14
|
readonly compatibility: {
|
|
15
15
|
readonly generation: 1;
|
|
16
|
-
readonly version: "2.
|
|
16
|
+
readonly version: "2.110.0";
|
|
17
17
|
readonly capabilities: Set<never>;
|
|
18
18
|
};
|
|
19
19
|
readonly interface: PresenceWithNotifications;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../../src/runtime/presenceManager.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 {\n\tAttendeesEvents,\n\tAttendeeId,\n\tBroadcastControlSettings,\n\tClientConnectionId,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"@fluid-internal/presence-definitions\";\nimport type {\n\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tTelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages, SystemWorkspaceDatastore } from \"./protocol.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./runtimeTypes.js\";\nimport type { SystemWorkspace } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\n\n/**\n * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<ContainerExtension<ExtensionRuntimeProperties>, \"processSignal\">\n>;\n\n/**\n * Confirms that the message is from a client and has a clientId\n * versus from the system which specifies `null` for clientId.\n */\nfunction assertMessageIsFromAClient(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): asserts message is InboundExtensionMessage<SignalMessages> & {\n\tclientId: ClientConnectionId;\n} {\n\tassert(message.clientId !== null, 0xa3a /* Presence received signal without clientId */);\n}\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\n\tprivate joined = false;\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents & AttendeesEvents>();\n\n\tpublic readonly attendees: Presence[\"attendees\"];\n\n\tpublic readonly states = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<StatesWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema, unknown, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<NotificationsWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tattendeeId: AttendeeId,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({ logger: runtime.logger, namespace: \"Presence\" });\n\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tattendeeId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc.logger,\n\t\t\tthis,\n\t\t);\n\t\tthis.attendees = this.systemWorkspace;\n\n\t\truntime.events.on(\"disconnected\", this.onDisconnected.bind(this));\n\n\t\tconst audience = runtime.getAudience();\n\t\t// Listen for self add to Audience to indicate join (with a stable\n\t\t// audience population).\n\t\taudience.on(\"addMember\", this.addClientConnectionId.bind(this));\n\t\taudience.on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected (can send signals and complete audience)\n\t\t// at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the self-\"addMember\" event will be raised during completion. With\n\t\t// construction delayed we expect that self-\"addMember\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.getClientId();\n\t\tif (\n\t\t\tclientId !== undefined &&\n\t\t\truntime.getJoinedStatus() !== \"disconnected\" &&\n\t\t\taudience.getMember(clientId) !== undefined\n\t\t) {\n\t\t\tthis.onJoin(clientId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate addClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\t// Check specifically for self join that indicates stable audience\n\t\t// and is preferred trigger for presence join.\n\t\tif (clientConnectionId === this.runtime.getClientId()) {\n\t\t\tthis.onJoin(clientConnectionId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tprivate onJoin(\n\t\tclientConnectionId: ClientConnectionId,\n\t\talternateUpdateProvider: ClientConnectionId | undefined,\n\t): void {\n\t\t// System workspace is notified even if already \"joined\", to handle the\n\t\t// audience -> attendee status updates.\n\t\tthis.systemWorkspace.onConnectionAdded(\n\t\t\tclientConnectionId,\n\t\t\t// audienceOutOfDate - out of date when onJoin is forced by receiving\n\t\t\t// a signal (which calls with alternateUpdateProvider defined).\n\t\t\talternateUpdateProvider !== undefined,\n\t\t);\n\t\tif (!this.joined) {\n\t\t\tthis.datastoreManager.joinSession(clientConnectionId, alternateUpdateProvider);\n\t\t\tthis.joined = true;\n\t\t}\n\t}\n\n\tprivate onDisconnected(): void {\n\t\tthis.joined = false;\n\t\tconst currentClientId = this.runtime.getClientId();\n\t\tif (currentClientId !== undefined) {\n\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t}\n\t\tthis.datastoreManager.onDisconnected();\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param addressChain - Address chain of the message\n\t * @param message - Unverified message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(\n\t\taddressChain: string[],\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t): void {\n\t\tassertMessageIsFromAClient(message);\n\n\t\t// Check for undesired case of receiving a remote presence signal\n\t\t// without having been alerted to self audience join that is preferred\n\t\t// trigger for join. (Perhaps join signal was dropped.)\n\t\t// In practice it is commonly observed that local signals can be\n\t\t// returned ahead of audience join notification. So, it is reasonable\n\t\t// to expect that audience join notification may be delayed until after\n\t\t// other presence signals are received. One is enough to get things\n\t\t// rolling.\n\t\tif (!local && !this.joined) {\n\t\t\tconst selfClientId = this.runtime.getClientId();\n\t\t\tassert(selfClientId !== undefined, 0xcbf /* Received signal without clientId */);\n\t\t\tthis.onJoin(selfClientId, /* alternateUpdateProvider */ message.clientId);\n\t\t}\n\n\t\tthis.datastoreManager.processSignal(\n\t\t\tmessage,\n\t\t\tlocal,\n\t\t\t/* optional */ addressChain[0] === \"?\",\n\t\t);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tattendeeId: AttendeeId,\n\truntime: IEphemeralRuntime,\n\tevents: Listenable<PresenceEvents & AttendeesEvents> &\n\t\tIEmitter<PresenceEvents & AttendeesEvents>,\n\tlogger: TelemetryLoggerExt,\n\tpresence: Presence,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tattendeeId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tattendeeId,\n\t\truntime,\n\t\tlogger,\n\t\tevents,\n\t\tpresence,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tattendeeId: AttendeeId = createSessionId() as AttendeeId,\n): Presence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, attendeeId);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../../src/runtime/presenceManager.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 {\n\tAttendeesEvents,\n\tAttendeeId,\n\tBroadcastControlSettings,\n\tClientConnectionId,\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"@fluid-internal/presence-definitions\";\nimport type {\n\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tMonitoringContext,\n\tTelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages, SystemWorkspaceDatastore } from \"./protocol.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./runtimeTypes.js\";\nimport type { SystemWorkspace } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\n\n/**\n * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<ContainerExtension<ExtensionRuntimeProperties>, \"processSignal\">\n>;\n\n/**\n * Confirms that the message is from a client and has a clientId\n * versus from the system which specifies `null` for clientId.\n */\nfunction assertMessageIsFromAClient(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): asserts message is InboundExtensionMessage<SignalMessages> & {\n\tclientId: ClientConnectionId;\n} {\n\tassert(message.clientId !== null, 0xa3a /* Presence received signal without clientId */);\n}\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\n\tprivate joined = false;\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents & AttendeesEvents>();\n\n\tpublic readonly attendees: Presence[\"attendees\"];\n\n\tpublic readonly states = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<StatesWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema, unknown, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <\n\t\t\tTSchema extends Partial<NotificationsWorkspaceSchema<TSchemaKeys>>,\n\t\t\tTSchemaKeys extends string & keyof TSchema,\n\t\t>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema, TSchemaKeys> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tattendeeId: AttendeeId,\n\t) {\n\t\tthis.mc = createChildMonitoringContext({ logger: runtime.logger, namespace: \"Presence\" });\n\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tattendeeId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc.logger,\n\t\t\tthis,\n\t\t);\n\t\tthis.attendees = this.systemWorkspace;\n\n\t\truntime.events.on(\"disconnected\", this.onDisconnected.bind(this));\n\n\t\tconst audience = runtime.getAudience();\n\t\t// Listen for self add to Audience to indicate join (with a stable\n\t\t// audience population).\n\t\taudience.on(\"addMember\", this.addClientConnectionId.bind(this));\n\t\taudience.on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected (can send signals and complete audience)\n\t\t// at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the self-\"addMember\" event will be raised during completion. With\n\t\t// construction delayed we expect that self-\"addMember\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.getClientId();\n\t\tif (\n\t\t\tclientId !== undefined &&\n\t\t\truntime.getJoinedStatus() !== \"disconnected\" &&\n\t\t\taudience.getMember(clientId) !== undefined\n\t\t) {\n\t\t\tthis.onJoin(clientId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate addClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\t// Check specifically for self join that indicates stable audience\n\t\t// and is preferred trigger for presence join.\n\t\tif (clientConnectionId === this.runtime.getClientId()) {\n\t\t\tthis.onJoin(clientConnectionId, /* alternateUpdateProvider */ undefined);\n\t\t}\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tprivate onJoin(\n\t\tclientConnectionId: ClientConnectionId,\n\t\talternateUpdateProvider: ClientConnectionId | undefined,\n\t): void {\n\t\t// System workspace is notified even if already \"joined\", to handle the\n\t\t// audience -> attendee status updates.\n\t\tthis.systemWorkspace.onConnectionAdded(\n\t\t\tclientConnectionId,\n\t\t\t// audienceOutOfDate - out of date when onJoin is forced by receiving\n\t\t\t// a signal (which calls with alternateUpdateProvider defined).\n\t\t\talternateUpdateProvider !== undefined,\n\t\t);\n\t\tif (!this.joined) {\n\t\t\tthis.datastoreManager.joinSession(clientConnectionId, alternateUpdateProvider);\n\t\t\tthis.joined = true;\n\t\t}\n\t}\n\n\tprivate onDisconnected(): void {\n\t\tthis.joined = false;\n\t\tconst currentClientId = this.runtime.getClientId();\n\t\tif (currentClientId !== undefined) {\n\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t}\n\t\tthis.datastoreManager.onDisconnected();\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param addressChain - Address chain of the message\n\t * @param message - Unverified message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(\n\t\taddressChain: string[],\n\t\tmessage: InboundExtensionMessage<SignalMessages>,\n\t\tlocal: boolean,\n\t): void {\n\t\tassertMessageIsFromAClient(message);\n\n\t\t// Check for undesired case of receiving a remote presence signal\n\t\t// without having been alerted to self audience join that is preferred\n\t\t// trigger for join. (Perhaps join signal was dropped.)\n\t\t// In practice it is commonly observed that local signals can be\n\t\t// returned ahead of audience join notification. So, it is reasonable\n\t\t// to expect that audience join notification may be delayed until after\n\t\t// other presence signals are received. One is enough to get things\n\t\t// rolling.\n\t\tif (!local && !this.joined) {\n\t\t\tconst selfClientId = this.runtime.getClientId();\n\t\t\tassert(selfClientId !== undefined, 0xcbf /* Received signal without clientId */);\n\t\t\tthis.onJoin(selfClientId, /* alternateUpdateProvider */ message.clientId);\n\t\t}\n\n\t\tthis.datastoreManager.processSignal(\n\t\t\tmessage,\n\t\t\tlocal,\n\t\t\t/* optional */ addressChain[0] === \"?\",\n\t\t);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tattendeeId: AttendeeId,\n\truntime: IEphemeralRuntime,\n\tevents: Listenable<PresenceEvents & AttendeesEvents> &\n\t\tIEmitter<PresenceEvents & AttendeesEvents>,\n\tlogger: TelemetryLoggerExt,\n\tpresence: Presence,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tattendeeId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tattendeeId,\n\t\truntime,\n\t\tlogger,\n\t\tevents,\n\t\tpresence,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tattendeeId: AttendeeId = createSessionId() as AttendeeId,\n): Presence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, attendeeId);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-internal/presence-runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.110.0",
|
|
4
4
|
"description": "Core runtime implementation for Fluid Framework presence",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -84,27 +84,27 @@
|
|
|
84
84
|
"temp-directory": "nyc/.nyc_output"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@fluid-internal/client-utils": "~2.
|
|
88
|
-
"@fluid-internal/presence-definitions": "~2.
|
|
89
|
-
"@fluidframework/container-definitions": "~2.
|
|
90
|
-
"@fluidframework/container-runtime-definitions": "~2.
|
|
91
|
-
"@fluidframework/core-interfaces": "~2.
|
|
92
|
-
"@fluidframework/core-utils": "~2.
|
|
93
|
-
"@fluidframework/id-compressor": "~2.
|
|
94
|
-
"@fluidframework/runtime-definitions": "~2.
|
|
95
|
-
"@fluidframework/telemetry-utils": "~2.
|
|
87
|
+
"@fluid-internal/client-utils": "~2.110.0",
|
|
88
|
+
"@fluid-internal/presence-definitions": "~2.110.0",
|
|
89
|
+
"@fluidframework/container-definitions": "~2.110.0",
|
|
90
|
+
"@fluidframework/container-runtime-definitions": "~2.110.0",
|
|
91
|
+
"@fluidframework/core-interfaces": "~2.110.0",
|
|
92
|
+
"@fluidframework/core-utils": "~2.110.0",
|
|
93
|
+
"@fluidframework/id-compressor": "~2.110.0",
|
|
94
|
+
"@fluidframework/runtime-definitions": "~2.110.0",
|
|
95
|
+
"@fluidframework/telemetry-utils": "~2.110.0"
|
|
96
96
|
},
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
99
99
|
"@biomejs/biome": "~2.4.5",
|
|
100
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
100
|
+
"@fluid-internal/mocha-test-setup": "~2.110.0",
|
|
101
101
|
"@fluid-tools/build-cli": "^0.65.0",
|
|
102
102
|
"@fluidframework/build-common": "^2.0.3",
|
|
103
103
|
"@fluidframework/build-tools": "^0.65.0",
|
|
104
|
-
"@fluidframework/driver-definitions": "~2.
|
|
105
|
-
"@fluidframework/eslint-config-fluid": "^
|
|
106
|
-
"@fluidframework/test-runtime-utils": "~2.
|
|
107
|
-
"@fluidframework/test-utils": "~2.
|
|
104
|
+
"@fluidframework/driver-definitions": "~2.110.0",
|
|
105
|
+
"@fluidframework/eslint-config-fluid": "^13.0.0",
|
|
106
|
+
"@fluidframework/test-runtime-utils": "~2.110.0",
|
|
107
|
+
"@fluidframework/test-utils": "~2.110.0",
|
|
108
108
|
"@microsoft/api-extractor": "7.58.1",
|
|
109
109
|
"@types/mocha": "^10.0.10",
|
|
110
110
|
"@types/node": "~22.19.17",
|