@fluidframework/presence 2.41.0 → 2.43.0-343119

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.
Files changed (147) hide show
  1. package/dist/broadcastControls.d.ts +2 -3
  2. package/dist/broadcastControls.d.ts.map +1 -1
  3. package/dist/broadcastControls.js +2 -3
  4. package/dist/broadcastControls.js.map +1 -1
  5. package/dist/datastorePresenceManagerFactory.d.ts.map +1 -1
  6. package/dist/datastorePresenceManagerFactory.js +1 -0
  7. package/dist/datastorePresenceManagerFactory.js.map +1 -1
  8. package/dist/datastoreSupport.d.ts +7 -2
  9. package/dist/datastoreSupport.d.ts.map +1 -1
  10. package/dist/datastoreSupport.js +6 -4
  11. package/dist/datastoreSupport.js.map +1 -1
  12. package/dist/exposedInternalTypes.d.ts +22 -4
  13. package/dist/exposedInternalTypes.d.ts.map +1 -1
  14. package/dist/exposedInternalTypes.js.map +1 -1
  15. package/dist/exposedUtilityTypes.d.ts +6 -5
  16. package/dist/exposedUtilityTypes.d.ts.map +1 -1
  17. package/dist/exposedUtilityTypes.js.map +1 -1
  18. package/dist/internalTypes.d.ts +11 -9
  19. package/dist/internalTypes.d.ts.map +1 -1
  20. package/dist/internalTypes.js.map +1 -1
  21. package/dist/internalUtils.d.ts +26 -8
  22. package/dist/internalUtils.d.ts.map +1 -1
  23. package/dist/internalUtils.js +35 -8
  24. package/dist/internalUtils.js.map +1 -1
  25. package/dist/latestMapValueManager.d.ts +28 -7
  26. package/dist/latestMapValueManager.d.ts.map +1 -1
  27. package/dist/latestMapValueManager.js +10 -9
  28. package/dist/latestMapValueManager.js.map +1 -1
  29. package/dist/latestValueManager.d.ts +17 -3
  30. package/dist/latestValueManager.d.ts.map +1 -1
  31. package/dist/latestValueManager.js +20 -9
  32. package/dist/latestValueManager.js.map +1 -1
  33. package/dist/latestValueTypes.d.ts +11 -1
  34. package/dist/latestValueTypes.d.ts.map +1 -1
  35. package/dist/latestValueTypes.js.map +1 -1
  36. package/dist/notificationsManager.d.ts +2 -2
  37. package/dist/notificationsManager.d.ts.map +1 -1
  38. package/dist/notificationsManager.js +14 -7
  39. package/dist/notificationsManager.js.map +1 -1
  40. package/dist/presence.d.ts +7 -5
  41. package/dist/presence.d.ts.map +1 -1
  42. package/dist/presence.js.map +1 -1
  43. package/dist/presenceDatastoreManager.d.ts +5 -6
  44. package/dist/presenceDatastoreManager.d.ts.map +1 -1
  45. package/dist/presenceDatastoreManager.js +19 -7
  46. package/dist/presenceDatastoreManager.js.map +1 -1
  47. package/dist/presenceManager.d.ts +0 -4
  48. package/dist/presenceManager.d.ts.map +1 -1
  49. package/dist/presenceManager.js +1 -3
  50. package/dist/presenceManager.js.map +1 -1
  51. package/dist/presenceStates.d.ts +9 -14
  52. package/dist/presenceStates.d.ts.map +1 -1
  53. package/dist/presenceStates.js +1 -8
  54. package/dist/presenceStates.js.map +1 -1
  55. package/dist/protocol.d.ts +37 -12
  56. package/dist/protocol.d.ts.map +1 -1
  57. package/dist/protocol.js +7 -3
  58. package/dist/protocol.js.map +1 -1
  59. package/dist/stateDatastore.d.ts +9 -8
  60. package/dist/stateDatastore.d.ts.map +1 -1
  61. package/dist/stateDatastore.js +0 -4
  62. package/dist/stateDatastore.js.map +1 -1
  63. package/dist/systemWorkspace.d.ts +12 -6
  64. package/dist/systemWorkspace.d.ts.map +1 -1
  65. package/dist/systemWorkspace.js +14 -4
  66. package/dist/systemWorkspace.js.map +1 -1
  67. package/dist/types.d.ts +3 -2
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/valueManager.d.ts +0 -4
  71. package/dist/valueManager.d.ts.map +1 -1
  72. package/dist/valueManager.js +0 -4
  73. package/dist/valueManager.js.map +1 -1
  74. package/lib/broadcastControls.d.ts +2 -3
  75. package/lib/broadcastControls.d.ts.map +1 -1
  76. package/lib/broadcastControls.js +2 -3
  77. package/lib/broadcastControls.js.map +1 -1
  78. package/lib/datastorePresenceManagerFactory.d.ts.map +1 -1
  79. package/lib/datastorePresenceManagerFactory.js +1 -0
  80. package/lib/datastorePresenceManagerFactory.js.map +1 -1
  81. package/lib/datastoreSupport.d.ts +7 -2
  82. package/lib/datastoreSupport.d.ts.map +1 -1
  83. package/lib/datastoreSupport.js +6 -4
  84. package/lib/datastoreSupport.js.map +1 -1
  85. package/lib/exposedInternalTypes.d.ts +22 -4
  86. package/lib/exposedInternalTypes.d.ts.map +1 -1
  87. package/lib/exposedInternalTypes.js.map +1 -1
  88. package/lib/exposedUtilityTypes.d.ts +6 -5
  89. package/lib/exposedUtilityTypes.d.ts.map +1 -1
  90. package/lib/exposedUtilityTypes.js.map +1 -1
  91. package/lib/internalTypes.d.ts +11 -9
  92. package/lib/internalTypes.d.ts.map +1 -1
  93. package/lib/internalTypes.js.map +1 -1
  94. package/lib/internalUtils.d.ts +26 -8
  95. package/lib/internalUtils.d.ts.map +1 -1
  96. package/lib/internalUtils.js +31 -7
  97. package/lib/internalUtils.js.map +1 -1
  98. package/lib/latestMapValueManager.d.ts +28 -7
  99. package/lib/latestMapValueManager.d.ts.map +1 -1
  100. package/lib/latestMapValueManager.js +11 -10
  101. package/lib/latestMapValueManager.js.map +1 -1
  102. package/lib/latestValueManager.d.ts +17 -3
  103. package/lib/latestValueManager.d.ts.map +1 -1
  104. package/lib/latestValueManager.js +19 -9
  105. package/lib/latestValueManager.js.map +1 -1
  106. package/lib/latestValueTypes.d.ts +11 -1
  107. package/lib/latestValueTypes.d.ts.map +1 -1
  108. package/lib/latestValueTypes.js.map +1 -1
  109. package/lib/notificationsManager.d.ts +2 -2
  110. package/lib/notificationsManager.d.ts.map +1 -1
  111. package/lib/notificationsManager.js +14 -7
  112. package/lib/notificationsManager.js.map +1 -1
  113. package/lib/presence.d.ts +7 -5
  114. package/lib/presence.d.ts.map +1 -1
  115. package/lib/presence.js.map +1 -1
  116. package/lib/presenceDatastoreManager.d.ts +5 -6
  117. package/lib/presenceDatastoreManager.d.ts.map +1 -1
  118. package/lib/presenceDatastoreManager.js +20 -8
  119. package/lib/presenceDatastoreManager.js.map +1 -1
  120. package/lib/presenceManager.d.ts +0 -4
  121. package/lib/presenceManager.d.ts.map +1 -1
  122. package/lib/presenceManager.js +1 -3
  123. package/lib/presenceManager.js.map +1 -1
  124. package/lib/presenceStates.d.ts +9 -14
  125. package/lib/presenceStates.d.ts.map +1 -1
  126. package/lib/presenceStates.js +1 -8
  127. package/lib/presenceStates.js.map +1 -1
  128. package/lib/protocol.d.ts +37 -12
  129. package/lib/protocol.d.ts.map +1 -1
  130. package/lib/protocol.js +6 -2
  131. package/lib/protocol.js.map +1 -1
  132. package/lib/stateDatastore.d.ts +9 -8
  133. package/lib/stateDatastore.d.ts.map +1 -1
  134. package/lib/stateDatastore.js +0 -4
  135. package/lib/stateDatastore.js.map +1 -1
  136. package/lib/systemWorkspace.d.ts +12 -6
  137. package/lib/systemWorkspace.d.ts.map +1 -1
  138. package/lib/systemWorkspace.js +14 -4
  139. package/lib/systemWorkspace.js.map +1 -1
  140. package/lib/types.d.ts +3 -2
  141. package/lib/types.d.ts.map +1 -1
  142. package/lib/types.js.map +1 -1
  143. package/lib/valueManager.d.ts +0 -4
  144. package/lib/valueManager.d.ts.map +1 -1
  145. package/lib/valueManager.js +0 -4
  146. package/lib/valueManager.js.map +1 -1
  147. package/package.json +17 -17
@@ -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 { 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"]}
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\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\tInternalWorkspaceAddress,\n\tOutboundDatastoreUpdateMessage,\n\tSignalMessages,\n\tSystemDatastore,\n} from \"./protocol.js\";\nimport {\n\tacknowledgementMessageType,\n\tdatastoreUpdateMessageType,\n\tjoinMessageType,\n} 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: InternalWorkspaceAddress]: ValueElementMap<StatesWorkspaceSchema>;\n};\n\nconst internalWorkspaceTypes: Readonly<Record<string, \"States\" | \"Notifications\">> = {\n\ts: \"States\",\n\tn: \"Notifications\",\n} as const;\n\nconst knownMessageTypes = new Set([\n\tjoinMessageType,\n\tdatastoreUpdateMessageType,\n\tacknowledgementMessageType,\n]);\nfunction isPresenceMessage(\n\tmessage: InboundExtensionMessage<SignalMessages>,\n): message is InboundDatastoreUpdateMessage | InboundClientJoinMessage {\n\treturn knownMessageTypes.has(message.type);\n}\n\n/**\n * High-level contract for manager of singleton Presence datastore\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 objectEntries(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\tprivate readonly targetedSignalSupport: boolean;\n\n\tpublic constructor(\n\t\tprivate readonly attendeeId: AttendeeId,\n\t\tprivate readonly runtime: IEphemeralRuntime,\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\tthis.targetedSignalSupport = this.runtime.supportedFeatures.has(\"submit_signals_v2\");\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\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\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\t// If the message requests an acknowledgement, we will send a targeted acknowledgement message back to just the requestor.\n\t\t\tif (message.content.acknowledgementId !== undefined) {\n\t\t\t\tassert(\n\t\t\t\t\tthis.targetedSignalSupport,\n\t\t\t\t\t\"Acknowledgment message was requested while targeted signal capability is not supported\",\n\t\t\t\t);\n\t\t\t\tthis.runtime.submitSignal({\n\t\t\t\t\ttype: acknowledgementMessageType,\n\t\t\t\t\tcontent: { id: message.content.acknowledgementId },\n\t\t\t\t\ttargetClientId: message.clientId,\n\t\t\t\t});\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 objectEntries(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 objectEntries(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"]}
@@ -7,14 +7,10 @@ import type { ExtensionRuntimeProperties, IEphemeralRuntime } from "./internalTy
7
7
  import type { AttendeeId, PresenceWithNotifications as Presence } from "./presence.js";
8
8
  /**
9
9
  * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.
10
- *
11
- * @internal
12
10
  */
13
11
  export type PresenceExtensionInterface = Required<Pick<ContainerExtension<ExtensionRuntimeProperties>, "processSignal">>;
14
12
  /**
15
13
  * Instantiates Presence Manager
16
- *
17
- * @internal
18
14
  */
19
15
  export declare function createPresenceManager(runtime: IEphemeralRuntime, attendeeId?: AttendeeId): Presence & PresenceExtensionInterface;
20
16
  //# sourceMappingURL=presenceManager.d.ts.map
@@ -1 +1 @@
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"}
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;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAChD,IAAI,CAAC,kBAAkB,CAAC,0BAA0B,CAAC,EAAE,eAAe,CAAC,CACrE,CAAC;AAyIF;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,UAAU,GAAE,UAA4C,GACtD,QAAQ,GAAG,0BAA0B,CAEvC"}
@@ -83,13 +83,11 @@ function setupSubComponents(attendeeId, runtime, events, logger, presence) {
83
83
  clientToSessionId: {},
84
84
  };
85
85
  const systemWorkspaceConfig = (0, systemWorkspace_js_1.createSystemWorkspace)(attendeeId, systemWorkspaceDatastore, events, runtime.getAudience());
86
- const datastoreManager = new presenceDatastoreManager_js_1.PresenceDatastoreManagerImpl(attendeeId, runtime, systemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace), logger, events, presence, systemWorkspaceDatastore, systemWorkspaceConfig.statesEntry);
86
+ const datastoreManager = new presenceDatastoreManager_js_1.PresenceDatastoreManagerImpl(attendeeId, runtime, logger, events, presence, systemWorkspaceDatastore, systemWorkspaceConfig.statesEntry);
87
87
  return [datastoreManager, systemWorkspaceConfig.workspace];
88
88
  }
89
89
  /**
90
90
  * Instantiates Presence Manager
91
- *
92
- * @internal
93
91
  */
94
92
  function createPresenceManager(runtime, attendeeId = (0, internal_1.createSessionId)()) {
95
93
  return new PresenceManager(runtime, attendeeId);
@@ -1 +1 @@
1
- {"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../src/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\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./internalTypes.js\";\nimport type {\n\tAttendeesEvents,\n\tAttendeeId,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages } from \"./protocol.js\";\nimport type { SystemWorkspace, SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * Portion of the container extension requirements ({@link ContainerExtension}) that are delegated to presence manager.\n *\n * @internal\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<ContainerExtension<ExtensionRuntimeProperties>, \"processSignal\">\n>;\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\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: <TSchema extends StatesWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <TSchema extends NotificationsWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext | undefined = undefined;\n\n\tpublic constructor(runtime: IEphemeralRuntime, attendeeId: AttendeeId) {\n\t\tconst logger = runtime.logger;\n\t\tif (logger) {\n\t\t\tthis.mc = createChildMonitoringContext({ logger, namespace: \"Presence\" });\n\t\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\t\t}\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(\"connected\", this.onConnect.bind(this));\n\n\t\truntime.events.on(\"disconnected\", () => {\n\t\t\tconst currentClientId = runtime.getClientId();\n\t\t\tif (currentClientId !== undefined) {\n\t\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t\t}\n\t\t});\n\n\t\truntime.getAudience().on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected 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 \"connected\" event will be raised during completion. With construction\n\t\t// delayed we expect that \"connected\" 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 (clientId !== undefined && runtime.isConnected()) {\n\t\t\tthis.onConnect(clientId);\n\t\t}\n\t}\n\n\tprivate onConnect(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.onConnectionAdded(clientConnectionId);\n\t\tthis.datastoreManager.joinSession(clientConnectionId);\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\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\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: ITelemetryLoggerExt | undefined,\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\tsystemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace),\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 *\n * @internal\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/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\tContainerExtension,\n\tInboundExtensionMessage,\n} from \"@fluidframework/container-runtime-definitions/internal\";\nimport type { IEmitter, Listenable } from \"@fluidframework/core-interfaces/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { ExtensionRuntimeProperties, IEphemeralRuntime } from \"./internalTypes.js\";\nimport type {\n\tAttendeesEvents,\n\tAttendeeId,\n\tPresenceWithNotifications as Presence,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SignalMessages } from \"./protocol.js\";\nimport type { SystemWorkspace, SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.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 * The Presence manager\n */\nclass PresenceManager implements Presence, PresenceExtensionInterface {\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: <TSchema extends StatesWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t\tsettings?: BroadcastControlSettings,\n\t\t): StatesWorkspace<TSchema> =>\n\t\t\tthis.datastoreManager.getWorkspace(`s:${workspaceAddress}`, requestedContent, settings),\n\t};\n\tpublic readonly notifications = {\n\t\tgetWorkspace: <TSchema extends NotificationsWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedContent: TSchema,\n\t\t): NotificationsWorkspace<TSchema> =>\n\t\t\tthis.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent),\n\t};\n\n\tprivate readonly mc: MonitoringContext | undefined = undefined;\n\n\tpublic constructor(runtime: IEphemeralRuntime, attendeeId: AttendeeId) {\n\t\tconst logger = runtime.logger;\n\t\tif (logger) {\n\t\t\tthis.mc = createChildMonitoringContext({ logger, namespace: \"Presence\" });\n\t\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\t\t}\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(\"connected\", this.onConnect.bind(this));\n\n\t\truntime.events.on(\"disconnected\", () => {\n\t\t\tconst currentClientId = runtime.getClientId();\n\t\t\tif (currentClientId !== undefined) {\n\t\t\t\tthis.removeClientConnectionId(currentClientId);\n\t\t\t}\n\t\t});\n\n\t\truntime.getAudience().on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected 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 \"connected\" event will be raised during completion. With construction\n\t\t// delayed we expect that \"connected\" 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 (clientId !== undefined && runtime.isConnected()) {\n\t\t\tthis.onConnect(clientId);\n\t\t}\n\t}\n\n\tprivate onConnect(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.onConnectionAdded(clientConnectionId);\n\t\tthis.datastoreManager.joinSession(clientConnectionId);\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\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\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: ITelemetryLoggerExt | undefined,\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"]}
@@ -6,7 +6,7 @@ import type { ClientConnectionId } from "./baseTypes.js";
6
6
  import type { BroadcastControlSettings } from "./broadcastControls.js";
7
7
  import type { InternalTypes } from "./exposedInternalTypes.js";
8
8
  import type { ClientRecord, PostUpdateAction } from "./internalTypes.js";
9
- import type { AttendeeId, Attendee, PresenceWithNotifications as Presence } from "./presence.js";
9
+ import type { AttendeeId, PresenceWithNotifications as Presence } from "./presence.js";
10
10
  import type { AnyWorkspace, StatesWorkspaceSchema } from "./types.js";
11
11
  /**
12
12
  * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type
@@ -16,14 +16,16 @@ import type { AnyWorkspace, StatesWorkspaceSchema } from "./types.js";
16
16
  * If the `Part` is an optional property, undefined will be included in the
17
17
  * result. Applying `Required` to the return type prior to extracting `Part`
18
18
  * does not work as expected. Use Exclude\<, undefined\> can be used as needed.
19
- *
20
- * @internal
21
19
  */
22
20
  export type MapSchemaElement<TSchema extends StatesWorkspaceSchema, Part extends keyof ReturnType<TSchema[keyof TSchema]>, Keys extends keyof TSchema = keyof TSchema> = ReturnType<TSchema[Keys]>[Part];
23
21
  /**
24
- * @internal
22
+ * Miscellaneous options for local state updates
25
23
  */
26
24
  export interface RuntimeLocalUpdateOptions {
25
+ /**
26
+ * The maximum time in milliseconds that this update is allowed to be
27
+ * delayed before it must be sent to the service.
28
+ */
27
29
  allowableUpdateLatencyMs: number;
28
30
  /**
29
31
  * Special option allowed for unicast notifications.
@@ -31,12 +33,11 @@ export interface RuntimeLocalUpdateOptions {
31
33
  targetClientId?: ClientConnectionId;
32
34
  }
33
35
  /**
34
- * @internal
36
+ * Contract for `PresenceDatastoreManager` as required by States Workspaces ({@link PresenceStatesImpl}).
35
37
  */
36
38
  export interface PresenceRuntime {
37
39
  readonly presence: Presence;
38
40
  readonly attendeeId: AttendeeId;
39
- lookupClient(clientId: ClientConnectionId): Attendee;
40
41
  localUpdate(states: {
41
42
  [key: string]: ClientUpdateEntry;
42
43
  }, options: RuntimeLocalUpdateOptions): void;
@@ -49,14 +50,12 @@ export interface PresenceRuntime {
49
50
  *
50
51
  * This generic aspect makes some typing difficult. The loose typing is not broadcast to the
51
52
  * consumers that are expected to maintain their schema over multiple versions of clients.
52
- *
53
- * @internal
54
53
  */
55
54
  export interface ValueElementMap<_TSchema extends StatesWorkspaceSchema> {
56
55
  [key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;
57
56
  }
58
57
  /**
59
- * @internal
58
+ * Data content of a datastore entry in update messages
60
59
  */
61
60
  export type ClientUpdateEntry = InternalTypes.ValueDirectoryOrState<unknown> & {
62
61
  ignoreUnmonitored?: true;
@@ -66,7 +65,7 @@ interface ValueUpdateRecord {
66
65
  [valueKey: string]: ClientUpdateRecord;
67
66
  }
68
67
  /**
69
- * @internal
68
+ * Contract for Workspaces as required by `PresenceDatastoreManager`
70
69
  */
71
70
  export interface PresenceStatesInternal {
72
71
  ensureContent<TSchemaAdditional extends StatesWorkspaceSchema>(content: TSchemaAdditional, controls: BroadcastControlSettings | undefined): AnyWorkspace<TSchemaAdditional>;
@@ -74,8 +73,6 @@ export interface PresenceStatesInternal {
74
73
  }
75
74
  /**
76
75
  * Merge a value directory.
77
- *
78
- * @internal
79
76
  */
80
77
  export declare function mergeValueDirectory<T, TValueState extends InternalTypes.ValueRequiredState<T> | InternalTypes.ValueOptionalState<T>>(base: TValueState | InternalTypes.ValueDirectory<T> | undefined, update: TValueState | InternalTypes.ValueDirectory<T>, timeDelta: number): TValueState | InternalTypes.ValueDirectory<T>;
81
78
  /**
@@ -88,8 +85,6 @@ export declare function mergeValueDirectory<T, TValueState extends InternalTypes
88
85
  * @remarks
89
86
  * In the case of ignored unmonitored data, the client entries are not stored,
90
87
  * though the value keys will be populated and often remain empty.
91
- *
92
- * @internal
93
88
  */
94
89
  export declare function mergeUntrackedDatastore(key: string, remoteAllKnownState: ClientUpdateRecord, datastore: ValueElementMap<StatesWorkspaceSchema>, timeModifier: number): void;
95
90
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"presenceStates.d.ts","sourceRoot":"","sources":["../src/presenceStates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presenceStates.d.ts","sourceRoot":"","sources":["../src/presenceStates.ts"],"names":[],"mappings":"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"}
@@ -15,8 +15,6 @@ function isValueDirectory(value) {
15
15
  }
16
16
  /**
17
17
  * Merge a value directory.
18
- *
19
- * @internal
20
18
  */
21
19
  function mergeValueDirectory(base, update, timeDelta) {
22
20
  if (!isValueDirectory(update)) {
@@ -61,8 +59,6 @@ exports.mergeValueDirectory = mergeValueDirectory;
61
59
  * @remarks
62
60
  * In the case of ignored unmonitored data, the client entries are not stored,
63
61
  * though the value keys will be populated and often remain empty.
64
- *
65
- * @internal
66
62
  */
67
63
  function mergeUntrackedDatastore(key, remoteAllKnownState, datastore, timeModifier) {
68
64
  const localAllKnownState = (0, internalUtils_js_1.getOrCreateRecord)(datastore, key, () => ({}));
@@ -149,9 +145,6 @@ class PresenceStatesImpl {
149
145
  const allKnownState = this.datastore[key];
150
146
  allKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);
151
147
  }
152
- lookupClient(clientId) {
153
- return this.runtime.lookupClient(clientId);
154
- }
155
148
  add(key, nodeFactory) {
156
149
  (0, internal_1.assert)(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);
157
150
  const nodeData = nodeFactory(key, (0, stateDatastore_js_1.handleFromDatastore)(this));
@@ -201,7 +194,7 @@ class PresenceStatesImpl {
201
194
  else {
202
195
  const node = (0, valueManager_js_1.unbrandIVM)(brandedIVM);
203
196
  for (const [attendeeId, value] of (0, internalUtils_js_1.objectEntries)(remoteAllKnownState)) {
204
- const client = this.runtime.lookupClient(attendeeId);
197
+ const client = this.runtime.presence.attendees.getAttendee(attendeeId);
205
198
  postUpdateActions.push(...node.update(client, received, value));
206
199
  }
207
200
  }
@@ -1 +1 @@
1
- {"version":3,"file":"presenceStates.js","sourceRoot":"","sources":["../src/presenceStates.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 { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { RequiredBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { ClientRecord, PostUpdateAction } from \"./internalTypes.js\";\nimport type { RecordEntryTypes } from \"./internalUtils.js\";\nimport { getOrCreateRecord, objectEntries } from \"./internalUtils.js\";\nimport type {\n\tAttendeeId,\n\tAttendee,\n\tPresenceWithNotifications as Presence,\n} from \"./presence.js\";\nimport type { LocalStateUpdateOptions, StateDatastore } from \"./stateDatastore.js\";\nimport { handleFromDatastore } from \"./stateDatastore.js\";\nimport type { AnyWorkspace, StatesWorkspace, StatesWorkspaceSchema } from \"./types.js\";\nimport { unbrandIVM } from \"./valueManager.js\";\n\n/**\n * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type\n * matching the {@link StatesWorkspaceSchema} `Keys` given.\n *\n * @remarks\n * If the `Part` is an optional property, undefined will be included in the\n * result. Applying `Required` to the return type prior to extracting `Part`\n * does not work as expected. Use Exclude\\<, undefined\\> can be used as needed.\n *\n * @internal\n */\nexport type MapSchemaElement<\n\tTSchema extends StatesWorkspaceSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n\tKeys extends keyof TSchema = keyof TSchema,\n> = ReturnType<TSchema[Keys]>[Part];\n\n/**\n * @internal\n */\nexport interface RuntimeLocalUpdateOptions {\n\tallowableUpdateLatencyMs: number;\n\n\t/**\n\t * Special option allowed for unicast notifications.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * @internal\n */\nexport interface PresenceRuntime {\n\treadonly presence: Presence;\n\treadonly attendeeId: AttendeeId;\n\tlookupClient(clientId: ClientConnectionId): Attendee;\n\tlocalUpdate(\n\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void;\n}\n\ntype PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema extends StatesWorkspaceSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n> = {\n\t[Key in keyof TSchema]: MapSchemaElement<TSchema, Part, Key>;\n};\n\ntype MapEntries<TSchema extends StatesWorkspaceSchema> = PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema,\n\t\"manager\"\n>;\n\n/**\n * ValueElementMap is a map of key to a map of clientId to ValueState.\n * It is not restricted to the schema of the map as it may receive updates from other clients\n * with managers that have not been registered locally. Each map node is responsible for keeping\n * all session's state to be able to pick arbitrary client to rebroadcast to others.\n *\n * This generic aspect makes some typing difficult. The loose typing is not broadcast to the\n * consumers that are expected to maintain their schema over multiple versions of clients.\n *\n * @internal\n */\nexport interface ValueElementMap<_TSchema extends StatesWorkspaceSchema> {\n\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n}\n\n// An attempt to make the type more precise, but it is not working.\n// If the casting in support code is too much we could keep two references to the same\n// complete datastore, but with the respective types desired.\n// type ValueElementMap<TSchema extends PresenceStatesNodeSchema> =\n// \t| {\n// \t\t\t[Key in keyof TSchema & string]?: {\n// \t\t\t\t[AttendeeId: AttendeeId]: InternalTypes.ValueDirectoryOrState<MapSchemaElement<TSchema,\"value\",Key>>;\n// \t\t\t};\n// \t }\n// \t| {\n// \t\t\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n// \t };\n// interface ValueElementMap<TValue> {\n// \t[Id: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// Version with local packed in is convenient for map, but not for join broadcast to serialize simply.\n// \t// [Id: string]: {\n// \t// \tlocal: InternalTypes.ValueDirectoryOrState<TValue>;\n// \t// \tall: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// };\n// }\n\n/**\n * @internal\n */\nexport type ClientUpdateEntry = InternalTypes.ValueDirectoryOrState<unknown> & {\n\tignoreUnmonitored?: true;\n};\n\ntype ClientUpdateRecord = ClientRecord<ClientUpdateEntry>;\n\ninterface ValueUpdateRecord {\n\t[valueKey: string]: ClientUpdateRecord;\n}\n\n/**\n * @internal\n */\nexport interface PresenceStatesInternal {\n\tensureContent<TSchemaAdditional extends StatesWorkspaceSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): AnyWorkspace<TSchemaAdditional>;\n\tprocessUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t\tsenderConnectionId: ClientConnectionId,\n\t): PostUpdateAction[];\n}\n\nfunction isValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tvalue: InternalTypes.ValueDirectory<T> | TValueState,\n): value is InternalTypes.ValueDirectory<T> {\n\treturn \"items\" in value;\n}\n\n/**\n * Merge a value directory.\n *\n * @internal\n */\nexport function mergeValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tbase: TValueState | InternalTypes.ValueDirectory<T> | undefined,\n\tupdate: TValueState | InternalTypes.ValueDirectory<T>,\n\ttimeDelta: number,\n): TValueState | InternalTypes.ValueDirectory<T> {\n\tif (!isValueDirectory(update)) {\n\t\tif (base === undefined || update.rev > base.rev) {\n\t\t\treturn { ...update, timestamp: update.timestamp + timeDelta };\n\t\t}\n\t\treturn base;\n\t}\n\n\tlet mergeBase: InternalTypes.ValueDirectory<T>;\n\tif (base === undefined) {\n\t\tmergeBase = { rev: update.rev, items: {} };\n\t} else {\n\t\tconst baseIsDirectory = isValueDirectory(base);\n\t\tif (base.rev >= update.rev) {\n\t\t\tif (!baseIsDirectory) {\n\t\t\t\t// base is leaf value that is more recent - nothing to do\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\t// While base has more advanced revision, assume mis-ordering or\n\t\t\t// missed and catchup update needs merged in.\n\t\t\tmergeBase = base;\n\t\t} else {\n\t\t\tmergeBase = { rev: update.rev, items: baseIsDirectory ? base.items : {} };\n\t\t}\n\t}\n\tfor (const [key, value] of Object.entries(update.items)) {\n\t\tconst baseElement = mergeBase.items[key];\n\t\tmergeBase.items[key] = mergeValueDirectory(baseElement, value, timeDelta);\n\t}\n\treturn mergeBase;\n}\n\n/**\n * Updates remote state into the local [untracked] datastore.\n *\n * @param key - The key of the datastore to merge the untracked data into.\n * @param remoteAllKnownState - The remote state to merge into the datastore.\n * @param datastore - The datastore to merge the untracked data into.\n *\n * @remarks\n * In the case of ignored unmonitored data, the client entries are not stored,\n * though the value keys will be populated and often remain empty.\n *\n * @internal\n */\nexport function mergeUntrackedDatastore(\n\tkey: string,\n\tremoteAllKnownState: ClientUpdateRecord,\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\ttimeModifier: number,\n): void {\n\tconst localAllKnownState = getOrCreateRecord(\n\t\tdatastore,\n\t\tkey,\n\t\t(): RecordEntryTypes<typeof datastore> => ({}),\n\t);\n\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\tif (!(\"ignoreUnmonitored\" in value)) {\n\t\t\tlocalAllKnownState[attendeeId] = mergeValueDirectory(\n\t\t\t\tlocalAllKnownState[attendeeId],\n\t\t\t\tvalue,\n\t\t\t\ttimeModifier,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * The default allowable update latency for StatesWorkspace in milliseconds.\n */\nconst defaultAllowableUpdateLatencyMs = 60;\n\n/**\n * Produces the value type of a schema element or set of elements.\n */\ntype SchemaElementValueType<\n\tTSchema extends StatesWorkspaceSchema,\n\tKeys extends keyof TSchema & string,\n> = Exclude<MapSchemaElement<TSchema, \"initialData\", Keys>, undefined>[\"value\"];\n\nclass PresenceStatesImpl<TSchema extends StatesWorkspaceSchema>\n\timplements\n\t\tPresenceStatesInternal,\n\t\tAnyWorkspace<TSchema>,\n\t\tStateDatastore<\n\t\t\tkeyof TSchema & string,\n\t\t\tSchemaElementValueType<TSchema, keyof TSchema & string>\n\t\t>\n{\n\tprivate readonly nodes: MapEntries<TSchema>;\n\tpublic readonly states: StatesWorkspace<TSchema>[\"states\"];\n\tpublic readonly notifications: AnyWorkspace<TSchema>[\"notifications\"];\n\n\tpublic readonly controls: RequiredBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: PresenceRuntime,\n\t\tprivate readonly datastore: ValueElementMap<TSchema>,\n\t\tinitialContent: TSchema,\n\t\tcontrolsSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new RequiredBroadcastControl(defaultAllowableUpdateLatencyMs);\n\t\tif (controlsSettings?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controlsSettings.allowableUpdateLatencyMs;\n\t\t}\n\n\t\t// Prepare initial map content from initial state\n\t\t{\n\t\t\tconst attendeeId = this.runtime.attendeeId;\n\t\t\t// Empty record does not satisfy the type, but nodes will post loop.\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tconst nodes = {} as MapEntries<TSchema>;\n\t\t\tlet anyInitialValues = false;\n\t\t\tconst newValues: { [key: string]: InternalTypes.ValueDirectoryOrState<unknown> } = {};\n\t\t\tlet cumulativeAllowableUpdateLatencyMs: number | undefined;\n\t\t\tfor (const [key, nodeFactory] of Object.entries(initialContent)) {\n\t\t\t\tconst newNodeData = nodeFactory(key, handleFromDatastore(this));\n\t\t\t\tnodes[key as keyof TSchema] = newNodeData.manager;\n\t\t\t\tif (\"initialData\" in newNodeData) {\n\t\t\t\t\tconst { value, allowableUpdateLatencyMs } = newNodeData.initialData;\n\t\t\t\t\t(datastore[key] ??= {})[attendeeId] = value;\n\t\t\t\t\tnewValues[key] = value;\n\t\t\t\t\tif (allowableUpdateLatencyMs !== undefined) {\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs =\n\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs === undefined\n\t\t\t\t\t\t\t\t? allowableUpdateLatencyMs\n\t\t\t\t\t\t\t\t: Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);\n\t\t\t\t\t}\n\t\t\t\t\tanyInitialValues = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.nodes = nodes;\n\t\t\t// states and notifications are the public view of nodes that limits the entries\n\t\t\t// types to the public interface of State objects with an additional type\n\t\t\t// filter that beguiles the type system. So just reinterpret cast.\n\t\t\tconst properties = nodes as unknown as AnyWorkspace<TSchema>[\"states\"];\n\t\t\t// `AnyWorkspace` support comes from defining both `states` for\n\t\t\t// `StatesWorkspace` and `notifications` for `NotificationsWorkspace`.\n\t\t\t// `notifications` is always a subset of what `states` can be; so the same.\n\t\t\tthis.notifications = this.states = properties;\n\n\t\t\tif (anyInitialValues) {\n\t\t\t\tthis.runtime.localUpdate(newValues, {\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.runtime.presence;\n\t}\n\n\tpublic knownValues<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t): {\n\t\tself: AttendeeId | undefined;\n\t\tstates: ClientRecord<SchemaElementValueType<TSchema, Key>>;\n\t} {\n\t\treturn {\n\t\t\tself: this.runtime.attendeeId,\n\t\t\t// Caller must only use `key`s that are part of `this.datastore`.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tstates: this.datastore[key]!,\n\t\t};\n\t}\n\n\tpublic localUpdate<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tvalue: SchemaElementValueType<TSchema, Key> & ClientUpdateEntry,\n\t\toptions: LocalStateUpdateOptions,\n\t): void {\n\t\tthis.runtime.localUpdate(\n\t\t\t{ [key]: value },\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\toptions.allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic update<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tclientId: AttendeeId,\n\t\tvalue: Exclude<MapSchemaElement<TSchema, \"initialData\", Key>, undefined>[\"value\"],\n\t): void {\n\t\t// Callers my only use `key`s that are part of `this.datastore`.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst allKnownState = this.datastore[key]!;\n\t\tallKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);\n\t}\n\n\tpublic lookupClient(clientId: ClientConnectionId): Attendee {\n\t\treturn this.runtime.lookupClient(clientId);\n\t}\n\n\tpublic add<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\t\tTValueManager,\n\t>(\n\t\tkey: TKey,\n\t\tnodeFactory: InternalTypes.ManagerFactory<TKey, TValue, TValueManager>,\n\t): asserts this is StatesWorkspace<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TValueManager>>\n\t> {\n\t\tassert(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);\n\t\tconst nodeData = nodeFactory(key, handleFromDatastore(this));\n\t\tthis.nodes[key] = nodeData.manager;\n\t\tif (\"initialData\" in nodeData) {\n\t\t\tconst { value, allowableUpdateLatencyMs } = nodeData.initialData;\n\t\t\tlet datastoreValue = this.datastore[key];\n\t\t\tif (datastoreValue === undefined) {\n\t\t\t\tdatastoreValue = this.datastore[key] = {};\n\t\t\t} else {\n\t\t\t\t// Already have received state from other clients. Kept in `all`.\n\t\t\t\t// TODO: Send current `all` state to state manager.\n\t\t\t}\n\t\t\tdatastoreValue[this.runtime.attendeeId] = value;\n\t\t\tthis.runtime.localUpdate(\n\t\t\t\t{ [key]: value },\n\t\t\t\t{\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tallowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends StatesWorkspaceSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): AnyWorkspace<TSchema & TSchemaAdditional> {\n\t\tif (controls?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controls.allowableUpdateLatencyMs;\n\t\t}\n\t\tfor (const [key, nodeFactory] of Object.entries(content)) {\n\t\t\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\n\t\t\t\tthis.add(key, nodeFactory);\n\t\t\t} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tif (!(node instanceof nodeFactory.instanceBase)) {\n\t\t\t\t\tthrow new TypeError(`State \"${key}\" previously created by different State object.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this as AnyWorkspace<TSchema & TSchemaAdditional>;\n\t}\n\n\tpublic processUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t): PostUpdateAction[] {\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\n\t\t\t\t// Assume all broadcast state is meant to be kept even if not currently registered.\n\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, this.datastore, timeModifier);\n\t\t\t} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\t\t\t\tconst client = this.runtime.lookupClient(attendeeId);\n\t\t\t\t\tpostUpdateActions.push(...node.update(client, received, value));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Create a new Workspace using the DataStoreRuntime provided.\n * @param initialContent - The initial State objects to register.\n */\nexport function createPresenceStates<TSchema extends StatesWorkspaceSchema>(\n\truntime: PresenceRuntime,\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\tinitialContent: TSchema,\n\tcontrols: BroadcastControlSettings | undefined,\n): { public: AnyWorkspace<TSchema>; internal: PresenceStatesInternal } {\n\tconst impl = new PresenceStatesImpl<TSchema>(runtime, datastore, initialContent, controls);\n\n\treturn {\n\t\tpublic: impl,\n\t\tinternal: impl,\n\t};\n}\n"]}
1
+ {"version":3,"file":"presenceStates.js","sourceRoot":"","sources":["../src/presenceStates.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 { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { RequiredBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { ClientRecord, PostUpdateAction } from \"./internalTypes.js\";\nimport type { RecordEntryTypes } from \"./internalUtils.js\";\nimport { getOrCreateRecord, objectEntries } from \"./internalUtils.js\";\nimport type { AttendeeId, PresenceWithNotifications as Presence } from \"./presence.js\";\nimport type { LocalStateUpdateOptions, StateDatastore } from \"./stateDatastore.js\";\nimport { handleFromDatastore } from \"./stateDatastore.js\";\nimport type { AnyWorkspace, StatesWorkspace, StatesWorkspaceSchema } from \"./types.js\";\nimport { unbrandIVM } from \"./valueManager.js\";\n\n/**\n * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type\n * matching the {@link StatesWorkspaceSchema} `Keys` given.\n *\n * @remarks\n * If the `Part` is an optional property, undefined will be included in the\n * result. Applying `Required` to the return type prior to extracting `Part`\n * does not work as expected. Use Exclude\\<, undefined\\> can be used as needed.\n */\nexport type MapSchemaElement<\n\tTSchema extends StatesWorkspaceSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n\tKeys extends keyof TSchema = keyof TSchema,\n> = ReturnType<TSchema[Keys]>[Part];\n\n/**\n * Miscellaneous options for local state updates\n */\nexport interface RuntimeLocalUpdateOptions {\n\t/**\n\t * The maximum time in milliseconds that this update is allowed to be\n\t * delayed before it must be sent to the service.\n\t */\n\tallowableUpdateLatencyMs: number;\n\n\t/**\n\t * Special option allowed for unicast notifications.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * Contract for `PresenceDatastoreManager` as required by States Workspaces ({@link PresenceStatesImpl}).\n */\nexport interface PresenceRuntime {\n\treadonly presence: Presence;\n\treadonly attendeeId: AttendeeId;\n\tlocalUpdate(\n\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void;\n}\n\ntype PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema extends StatesWorkspaceSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n> = {\n\t[Key in keyof TSchema]: MapSchemaElement<TSchema, Part, Key>;\n};\n\ntype MapEntries<TSchema extends StatesWorkspaceSchema> = PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema,\n\t\"manager\"\n>;\n\n/**\n * ValueElementMap is a map of key to a map of clientId to ValueState.\n * It is not restricted to the schema of the map as it may receive updates from other clients\n * with managers that have not been registered locally. Each map node is responsible for keeping\n * all session's state to be able to pick arbitrary client to rebroadcast to others.\n *\n * This generic aspect makes some typing difficult. The loose typing is not broadcast to the\n * consumers that are expected to maintain their schema over multiple versions of clients.\n */\nexport interface ValueElementMap<_TSchema extends StatesWorkspaceSchema> {\n\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n}\n\n// An attempt to make the type more precise, but it is not working.\n// If the casting in support code is too much we could keep two references to the same\n// complete datastore, but with the respective types desired.\n// type ValueElementMap<TSchema extends PresenceStatesNodeSchema> =\n// \t| {\n// \t\t\t[Key in keyof TSchema & string]?: {\n// \t\t\t\t[AttendeeId: AttendeeId]: InternalTypes.ValueDirectoryOrState<MapSchemaElement<TSchema,\"value\",Key>>;\n// \t\t\t};\n// \t }\n// \t| {\n// \t\t\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n// \t };\n// interface ValueElementMap<TValue> {\n// \t[Id: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// Version with local packed in is convenient for map, but not for join broadcast to serialize simply.\n// \t// [Id: string]: {\n// \t// \tlocal: InternalTypes.ValueDirectoryOrState<TValue>;\n// \t// \tall: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// };\n// }\n\n/**\n * Data content of a datastore entry in update messages\n */\nexport type ClientUpdateEntry = InternalTypes.ValueDirectoryOrState<unknown> & {\n\tignoreUnmonitored?: true;\n};\n\ntype ClientUpdateRecord = ClientRecord<ClientUpdateEntry>;\n\ninterface ValueUpdateRecord {\n\t[valueKey: string]: ClientUpdateRecord;\n}\n\n/**\n * Contract for Workspaces as required by `PresenceDatastoreManager`\n */\nexport interface PresenceStatesInternal {\n\tensureContent<TSchemaAdditional extends StatesWorkspaceSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): AnyWorkspace<TSchemaAdditional>;\n\tprocessUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t\tsenderConnectionId: ClientConnectionId,\n\t): PostUpdateAction[];\n}\n\nfunction isValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tvalue: InternalTypes.ValueDirectory<T> | TValueState,\n): value is InternalTypes.ValueDirectory<T> {\n\treturn \"items\" in value;\n}\n\n/**\n * Merge a value directory.\n */\nexport function mergeValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tbase: TValueState | InternalTypes.ValueDirectory<T> | undefined,\n\tupdate: TValueState | InternalTypes.ValueDirectory<T>,\n\ttimeDelta: number,\n): TValueState | InternalTypes.ValueDirectory<T> {\n\tif (!isValueDirectory(update)) {\n\t\tif (base === undefined || update.rev > base.rev) {\n\t\t\treturn { ...update, timestamp: update.timestamp + timeDelta };\n\t\t}\n\t\treturn base;\n\t}\n\n\tlet mergeBase: InternalTypes.ValueDirectory<T>;\n\tif (base === undefined) {\n\t\tmergeBase = { rev: update.rev, items: {} };\n\t} else {\n\t\tconst baseIsDirectory = isValueDirectory(base);\n\t\tif (base.rev >= update.rev) {\n\t\t\tif (!baseIsDirectory) {\n\t\t\t\t// base is leaf value that is more recent - nothing to do\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\t// While base has more advanced revision, assume mis-ordering or\n\t\t\t// missed and catchup update needs merged in.\n\t\t\tmergeBase = base;\n\t\t} else {\n\t\t\tmergeBase = { rev: update.rev, items: baseIsDirectory ? base.items : {} };\n\t\t}\n\t}\n\tfor (const [key, value] of Object.entries(update.items)) {\n\t\tconst baseElement = mergeBase.items[key];\n\t\tmergeBase.items[key] = mergeValueDirectory(baseElement, value, timeDelta);\n\t}\n\treturn mergeBase;\n}\n\n/**\n * Updates remote state into the local [untracked] datastore.\n *\n * @param key - The key of the datastore to merge the untracked data into.\n * @param remoteAllKnownState - The remote state to merge into the datastore.\n * @param datastore - The datastore to merge the untracked data into.\n *\n * @remarks\n * In the case of ignored unmonitored data, the client entries are not stored,\n * though the value keys will be populated and often remain empty.\n */\nexport function mergeUntrackedDatastore(\n\tkey: string,\n\tremoteAllKnownState: ClientUpdateRecord,\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\ttimeModifier: number,\n): void {\n\tconst localAllKnownState = getOrCreateRecord(\n\t\tdatastore,\n\t\tkey,\n\t\t(): RecordEntryTypes<typeof datastore> => ({}),\n\t);\n\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\tif (!(\"ignoreUnmonitored\" in value)) {\n\t\t\tlocalAllKnownState[attendeeId] = mergeValueDirectory(\n\t\t\t\tlocalAllKnownState[attendeeId],\n\t\t\t\tvalue,\n\t\t\t\ttimeModifier,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * The default allowable update latency for StatesWorkspace in milliseconds.\n */\nconst defaultAllowableUpdateLatencyMs = 60;\n\n/**\n * Produces the value type of a schema element or set of elements.\n */\ntype SchemaElementValueType<\n\tTSchema extends StatesWorkspaceSchema,\n\tKeys extends keyof TSchema & string,\n> = Exclude<MapSchemaElement<TSchema, \"initialData\", Keys>, undefined>[\"value\"];\n\nclass PresenceStatesImpl<TSchema extends StatesWorkspaceSchema>\n\timplements\n\t\tPresenceStatesInternal,\n\t\tAnyWorkspace<TSchema>,\n\t\tStateDatastore<\n\t\t\tkeyof TSchema & string,\n\t\t\tSchemaElementValueType<TSchema, keyof TSchema & string>\n\t\t>\n{\n\tprivate readonly nodes: MapEntries<TSchema>;\n\tpublic readonly states: StatesWorkspace<TSchema>[\"states\"];\n\tpublic readonly notifications: AnyWorkspace<TSchema>[\"notifications\"];\n\n\tpublic readonly controls: RequiredBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: PresenceRuntime,\n\t\tprivate readonly datastore: ValueElementMap<TSchema>,\n\t\tinitialContent: TSchema,\n\t\tcontrolsSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new RequiredBroadcastControl(defaultAllowableUpdateLatencyMs);\n\t\tif (controlsSettings?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controlsSettings.allowableUpdateLatencyMs;\n\t\t}\n\n\t\t// Prepare initial map content from initial state\n\t\t{\n\t\t\tconst attendeeId = this.runtime.attendeeId;\n\t\t\t// Empty record does not satisfy the type, but nodes will post loop.\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tconst nodes = {} as MapEntries<TSchema>;\n\t\t\tlet anyInitialValues = false;\n\t\t\tconst newValues: { [key: string]: InternalTypes.ValueDirectoryOrState<unknown> } = {};\n\t\t\tlet cumulativeAllowableUpdateLatencyMs: number | undefined;\n\t\t\tfor (const [key, nodeFactory] of Object.entries(initialContent)) {\n\t\t\t\tconst newNodeData = nodeFactory(key, handleFromDatastore(this));\n\t\t\t\tnodes[key as keyof TSchema] = newNodeData.manager;\n\t\t\t\tif (\"initialData\" in newNodeData) {\n\t\t\t\t\tconst { value, allowableUpdateLatencyMs } = newNodeData.initialData;\n\t\t\t\t\t(datastore[key] ??= {})[attendeeId] = value;\n\t\t\t\t\tnewValues[key] = value;\n\t\t\t\t\tif (allowableUpdateLatencyMs !== undefined) {\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs =\n\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs === undefined\n\t\t\t\t\t\t\t\t? allowableUpdateLatencyMs\n\t\t\t\t\t\t\t\t: Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);\n\t\t\t\t\t}\n\t\t\t\t\tanyInitialValues = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.nodes = nodes;\n\t\t\t// states and notifications are the public view of nodes that limits the entries\n\t\t\t// types to the public interface of State objects with an additional type\n\t\t\t// filter that beguiles the type system. So just reinterpret cast.\n\t\t\tconst properties = nodes as unknown as AnyWorkspace<TSchema>[\"states\"];\n\t\t\t// `AnyWorkspace` support comes from defining both `states` for\n\t\t\t// `StatesWorkspace` and `notifications` for `NotificationsWorkspace`.\n\t\t\t// `notifications` is always a subset of what `states` can be; so the same.\n\t\t\tthis.notifications = this.states = properties;\n\n\t\t\tif (anyInitialValues) {\n\t\t\t\tthis.runtime.localUpdate(newValues, {\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.runtime.presence;\n\t}\n\n\tpublic knownValues<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t): {\n\t\tself: AttendeeId | undefined;\n\t\tstates: ClientRecord<SchemaElementValueType<TSchema, Key>>;\n\t} {\n\t\treturn {\n\t\t\tself: this.runtime.attendeeId,\n\t\t\t// Caller must only use `key`s that are part of `this.datastore`.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tstates: this.datastore[key]!,\n\t\t};\n\t}\n\n\tpublic localUpdate<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tvalue: SchemaElementValueType<TSchema, Key> & ClientUpdateEntry,\n\t\toptions: LocalStateUpdateOptions,\n\t): void {\n\t\tthis.runtime.localUpdate(\n\t\t\t{ [key]: value },\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\toptions.allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic update<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tclientId: AttendeeId,\n\t\tvalue: Exclude<MapSchemaElement<TSchema, \"initialData\", Key>, undefined>[\"value\"],\n\t): void {\n\t\t// Callers my only use `key`s that are part of `this.datastore`.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst allKnownState = this.datastore[key]!;\n\t\tallKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);\n\t}\n\n\tpublic add<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\t\tTValueManager,\n\t>(\n\t\tkey: TKey,\n\t\tnodeFactory: InternalTypes.ManagerFactory<TKey, TValue, TValueManager>,\n\t): asserts this is StatesWorkspace<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TValueManager>>\n\t> {\n\t\tassert(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);\n\t\tconst nodeData = nodeFactory(key, handleFromDatastore(this));\n\t\tthis.nodes[key] = nodeData.manager;\n\t\tif (\"initialData\" in nodeData) {\n\t\t\tconst { value, allowableUpdateLatencyMs } = nodeData.initialData;\n\t\t\tlet datastoreValue = this.datastore[key];\n\t\t\tif (datastoreValue === undefined) {\n\t\t\t\tdatastoreValue = this.datastore[key] = {};\n\t\t\t} else {\n\t\t\t\t// Already have received state from other clients. Kept in `all`.\n\t\t\t\t// TODO: Send current `all` state to state manager.\n\t\t\t}\n\t\t\tdatastoreValue[this.runtime.attendeeId] = value;\n\t\t\tthis.runtime.localUpdate(\n\t\t\t\t{ [key]: value },\n\t\t\t\t{\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tallowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends StatesWorkspaceSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): AnyWorkspace<TSchema & TSchemaAdditional> {\n\t\tif (controls?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controls.allowableUpdateLatencyMs;\n\t\t}\n\t\tfor (const [key, nodeFactory] of Object.entries(content)) {\n\t\t\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\n\t\t\t\tthis.add(key, nodeFactory);\n\t\t\t} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tif (!(node instanceof nodeFactory.instanceBase)) {\n\t\t\t\t\tthrow new TypeError(`State \"${key}\" previously created by different State object.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this as AnyWorkspace<TSchema & TSchemaAdditional>;\n\t}\n\n\tpublic processUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t): PostUpdateAction[] {\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\n\t\t\t\t// Assume all broadcast state is meant to be kept even if not currently registered.\n\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, this.datastore, timeModifier);\n\t\t\t} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\t\t\t\tconst client = this.runtime.presence.attendees.getAttendee(attendeeId);\n\t\t\t\t\tpostUpdateActions.push(...node.update(client, received, value));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Create a new Workspace using the DataStoreRuntime provided.\n * @param initialContent - The initial State objects to register.\n */\nexport function createPresenceStates<TSchema extends StatesWorkspaceSchema>(\n\truntime: PresenceRuntime,\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\tinitialContent: TSchema,\n\tcontrols: BroadcastControlSettings | undefined,\n): { public: AnyWorkspace<TSchema>; internal: PresenceStatesInternal } {\n\tconst impl = new PresenceStatesImpl<TSchema>(runtime, datastore, initialContent, controls);\n\n\treturn {\n\t\tpublic: impl,\n\t\tinternal: impl,\n\t};\n}\n"]}
@@ -7,25 +7,31 @@ import type { ClientConnectionId } from "./baseTypes.js";
7
7
  import type { AttendeeId } from "./presence.js";
8
8
  import type { ClientUpdateEntry } from "./presenceStates.js";
9
9
  import type { SystemWorkspaceDatastore } from "./systemWorkspace.js";
10
+ import type { WorkspaceAddress } from "./types.js";
10
11
  /**
11
- * @internal
12
+ * Datastore that contains system workspace data
12
13
  */
13
14
  export interface SystemDatastore {
14
15
  "system:presence": SystemWorkspaceDatastore;
15
16
  }
16
17
  /**
17
- * @internal
18
+ * Expected address format for general workspaces in the presence protocol.
19
+ */
20
+ export type InternalWorkspaceAddress = `${"s" | "n"}:${WorkspaceAddress}`;
21
+ /**
22
+ * General datastore (and message) structure.
18
23
  */
19
24
  export interface GeneralDatastoreMessageContent {
20
- [WorkspaceAddress: string]: {
25
+ [WorkspaceAddress: InternalWorkspaceAddress]: {
21
26
  [StateValueManagerKey: string]: {
22
27
  [AttendeeId: AttendeeId]: ClientUpdateEntry;
23
28
  };
24
29
  };
25
30
  }
26
- type DatastoreMessageContent = GeneralDatastoreMessageContent & SystemDatastore;
31
+ type DatastoreMessageContent = SystemDatastore & GeneralDatastoreMessageContent;
32
+ type AcknowledgmentId = string;
27
33
  /**
28
- * @internal
34
+ * Datastore update message type.
29
35
  */
30
36
  export declare const datastoreUpdateMessageType = "Pres:DatastoreUpdate";
31
37
  interface DatastoreUpdateMessage {
@@ -33,20 +39,21 @@ interface DatastoreUpdateMessage {
33
39
  content: {
34
40
  sendTimestamp: number;
35
41
  avgLatency: number;
42
+ acknowledgementId?: AcknowledgmentId;
36
43
  isComplete?: true;
37
44
  data: DatastoreMessageContent;
38
45
  };
39
46
  }
40
47
  /**
41
- * @internal
48
+ * Outbound datastore update message
42
49
  */
43
50
  export type OutboundDatastoreUpdateMessage = OutboundExtensionMessage<DatastoreUpdateMessage>;
44
51
  /**
45
- * @internal
52
+ * Inbound and verified datastore update message
46
53
  */
47
54
  export type InboundDatastoreUpdateMessage = VerifiedInboundExtensionMessage<DatastoreUpdateMessage>;
48
55
  /**
49
- * @internal
56
+ * Client join message type.
50
57
  */
51
58
  export declare const joinMessageType = "Pres:ClientJoin";
52
59
  interface ClientJoinMessage {
@@ -59,16 +66,34 @@ interface ClientJoinMessage {
59
66
  };
60
67
  }
61
68
  /**
62
- * @internal
69
+ * Acknowledgement message type.
70
+ */
71
+ export declare const acknowledgementMessageType = "Pres:Ack";
72
+ interface AcknowledgementMessage {
73
+ type: typeof acknowledgementMessageType;
74
+ content: {
75
+ id: AcknowledgmentId;
76
+ };
77
+ }
78
+ /**
79
+ * Outbound acknowledgement message.
80
+ */
81
+ export type OutboundAcknowledgementMessage = OutboundExtensionMessage<AcknowledgementMessage>;
82
+ /**
83
+ * Outbound client join message
63
84
  */
64
85
  export type OutboundClientJoinMessage = OutboundExtensionMessage<ClientJoinMessage>;
65
86
  /**
66
- * @internal
87
+ * Inbound and verified client join message
67
88
  */
68
89
  export type InboundClientJoinMessage = VerifiedInboundExtensionMessage<ClientJoinMessage>;
69
90
  /**
70
- * @internal
91
+ * Outbound presence message.
92
+ */
93
+ export type OutboundPresenceMessage = OutboundAcknowledgementMessage | OutboundClientJoinMessage | OutboundDatastoreUpdateMessage;
94
+ /**
95
+ * Messages structures that can be sent and received as understood in the presence protocol
71
96
  */
72
- export type SignalMessages = ClientJoinMessage | DatastoreUpdateMessage;
97
+ export type SignalMessages = AcknowledgementMessage | ClientJoinMessage | DatastoreUpdateMessage;
73
98
  export {};
74
99
  //# sourceMappingURL=protocol.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,wBAAwB,EACxB,+BAA+B,EAC/B,MAAM,wDAAwD,CAAC;AAEhE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,iBAAiB,EAAE,wBAAwB,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,CAAC,gBAAgB,EAAE,MAAM,GAAG;QAC3B,CAAC,oBAAoB,EAAE,MAAM,GAAG;YAC/B,CAAC,UAAU,EAAE,UAAU,GAAG,iBAAiB,CAAC;SAC5C,CAAC;KACF,CAAC;CACF;AAED,KAAK,uBAAuB,GAAG,8BAA8B,GAAG,eAAe,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,UAAU,sBAAsB;IAC/B,IAAI,EAAE,OAAO,0BAA0B,CAAC;IACxC,OAAO,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,IAAI,CAAC;QAClB,IAAI,EAAE,uBAAuB,CAAC;KAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,6BAA6B,GACxC,+BAA+B,CAAC,sBAAsB,CAAC,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,UAAU,iBAAiB;IAC1B,IAAI,EAAE,OAAO,eAAe,CAAC;IAC7B,OAAO,EAAE;QACR,eAAe,EAAE,kBAAkB,EAAE,CAAC;QACtC,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,uBAAuB,CAAC;KAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,CAAC,iBAAiB,CAAC,CAAC;AAE1F;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,iBAAiB,GAAG,sBAAsB,CAAC"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,wBAAwB,EACxB,+BAA+B,EAC/B,MAAM,wDAAwD,CAAC;AAEhE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,iBAAiB,EAAE,wBAAwB,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,gBAAgB,EAAE,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C,CAAC,gBAAgB,EAAE,wBAAwB,GAAG;QAC7C,CAAC,oBAAoB,EAAE,MAAM,GAAG;YAC/B,CAAC,UAAU,EAAE,UAAU,GAAG,iBAAiB,CAAC;SAC5C,CAAC;KACF,CAAC;CACF;AAED,KAAK,uBAAuB,GAAG,eAAe,GAAG,8BAA8B,CAAC;AAChF,KAAK,gBAAgB,GAAG,MAAM,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,UAAU,sBAAsB;IAC/B,IAAI,EAAE,OAAO,0BAA0B,CAAC;IACxC,OAAO,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;QACrC,UAAU,CAAC,EAAE,IAAI,CAAC;QAClB,IAAI,EAAE,uBAAuB,CAAC;KAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,6BAA6B,GACxC,+BAA+B,CAAC,sBAAsB,CAAC,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,UAAU,iBAAiB;IAC1B,IAAI,EAAE,OAAO,eAAe,CAAC;IAC7B,OAAO,EAAE;QACR,eAAe,EAAE,kBAAkB,EAAE,CAAC;QACtC,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,uBAAuB,CAAC;KAC9B,CAAC;CACF;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B,aAAa,CAAC;AAErD,UAAU,sBAAsB;IAC/B,IAAI,EAAE,OAAO,0BAA0B,CAAC;IACxC,OAAO,EAAE;QACR,EAAE,EAAE,gBAAgB,CAAC;KACrB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,CAAC,iBAAiB,CAAC,CAAC;AAE1F;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAChC,8BAA8B,GAC9B,yBAAyB,GACzB,8BAA8B,CAAC;AAElC;;GAEG;AACH,MAAM,MAAM,cAAc,GACvB,sBAAsB,GACtB,iBAAiB,GACjB,sBAAsB,CAAC"}