Skip to content

feat(client): processing during CatchingUp ConnectionState#25750

Merged
jason-ha merged 2 commits intomainfrom
test/client/catchingUp-processing-foundation
Oct 27, 2025
Merged

feat(client): processing during CatchingUp ConnectionState#25750
jason-ha merged 2 commits intomainfrom
test/client/catchingUp-processing-foundation

Conversation

@jason-ha
Copy link
Contributor

IRuntime now has an optional (preferred) setConnectionStatus method
that replaces the previous setConnectionState method (still required
for compatibility). The new method is called for all ConnectionState
changes, including CatchingUp and EstablishingConnection. Calls may
also be made when readonly state changes, even if there is no overall
change in connection status.

ContainerRuntime announces fewer "disconnected" events when a client
is not fully connected and the readonly state changes.

And add case to test missing setConnectionStatus while making its presence the default.

Add internal Signal only based Audience that can be used while CatchingUp.

For Container Extensions:

  • rename "connectionTypeChanged" event to "operabilityChanged" to allow for later move to operate during CatchingUp
  • Document JoinedStatus states

@jason-ha jason-ha requested a review from a team as a code owner October 24, 2025 22:11
@github-actions github-actions bot added area: loader Loader related issues area: runtime Runtime related issues public api change Changes to a public API base: main PRs targeted against main branch labels Oct 24, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new setConnectionStatus method on IRuntime that provides more granular connection state information, including support for CatchingUp and EstablishingConnection states. The new method deprecates the existing setConnectionState method while maintaining backwards compatibility. Key changes include:

  • Added setConnectionStatus method to IRuntime with connection status interfaces for all connection states
  • Implemented signal-based audience for faster connection state updates during CatchingUp
  • Renamed "connectionTypeChanged" event to "operabilityChanged" in Container Extensions for clarity

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/runtime/container-runtime/src/containerRuntime.ts Implements new setConnectionStatus method, handles CatchingUp state, renames event to "operabilityChanged"
packages/runtime/container-runtime/src/test/containerRuntime.extensions.spec.ts Updates tests for renamed event and adds signalAudience simulation support
packages/runtime/container-runtime-definitions/src/containerExtension.ts Documents JoinedStatus states and renames "connectionTypeChanged" to "operabilityChanged"
packages/runtime/container-runtime-definitions/src/index.ts Exports new JoinedStatus type variants
packages/common/container-definitions/src/runtime.ts Defines ConnectionStatus interfaces and adds setConnectionStatus to IRuntime
packages/common/container-definitions/src/index.ts Exports new ConnectionStatus types
packages/loader/container-loader/src/container.ts Implements setConnectionStatus calling logic with backwards compatibility for older runtimes
packages/loader/container-loader/src/containerContext.ts Adds signalAudience property
packages/loader/container-loader/src/protocol.ts Implements wrapProtocolHandlerBuilder for signal-based audience
packages/loader/container-loader/src/test/loader.spec.ts Adds test for IRuntime without setConnectionStatus
packages/loader/container-loader/src/test/testProxies.ts Adds support for testing runtime without setConnectionStatus
packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md Updates API surface with new ConnectionStatus types

Copy link
Contributor

@WillieHabi WillieHabi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Left one comment about canSendOpsChanged when transitioning to CatchingUp status

// event.

this.emitServiceConnectionEvents(
/* canSendOpsChanged */ this.canSendOps,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be false? AFAIK the ability to send ops doesn't change when transitioning to CatchingUp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. But I don't see a reason to mess with the state machine. If it was true in some case we aren't thinking about then this would be accurate. Perhaps some funny transition from write-client going back to CatchingUp when becoming a read-only client.

/**
* The ID of the client connection that was most recently connecting (catching up).
*/
priorPendingClientConnectionId: string | undefined;
Copy link
Contributor

@WillieHabi WillieHabi Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Do we need this attribute? I don't see it used when passed into setConnectionStatus in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is more informational than anything else. If someone were trying to track client id information through the transitions this would be good to know.

`IRuntime` now has an optional (preferred) `setConnectionStatus` method
that replaces the previous `setConnectionState` method (still required
for compatibility). The new method is called for all `ConnectionState`
changes, including `CatchingUp` and `EstablishingConnection`. Calls may
also be made when readonly state changes, even if there is no overall
change in connection status.

`ContainerRuntime` announces fewer "disconnected" events when a client
is not fully connected and the readonly state changes.

And add case to test missing setConnectionStatus while making its presence the default.

Add internal Signal only based Audience that can be used while CatchingUp.

For Container Extensions:
- rename "connectionTypeChanged" event to "operabilityChanged" to allow for later move to operate during CatchingUp
- Document JoinedStatus states
@jason-ha jason-ha force-pushed the test/client/catchingUp-processing-foundation branch from e21dea0 to 0afb3e0 Compare October 24, 2025 23:37
@WillieHabi WillieHabi self-requested a review October 24, 2025 23:45
@jason-ha jason-ha enabled auto-merge (squash) October 24, 2025 23:49
@github-actions
Copy link
Contributor

🔗 Found some broken links! 💔

Run a link check locally to find them. See
https://github.com/microsoft/FluidFramework/wiki/Checking-for-broken-links-in-the-documentation for more information.

linkcheck output


> fluid-framework-docs-site@0.0.0 ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

 ELIFECYCLE  Command failed with exit code 1.

runtime.setConnectionStatus({
connectionState,
clientConnectionId: clientId,
canSendOps: !context.isReadonly,
Copy link
Contributor

@anthony-murphy anthony-murphy Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems odd that we never re-signal if and when canSendOps changes? specifically if readonly becomes false? Overall, i find these kinds of composed values difficult to reason about in the current design where each value is separate, as it seem like a consumer still needs to understand the internals of canSendOps, so they know to track readonly, and only then can they figure out if they can actually send ops or not.

I don't know what the right solution to the above problem is, but i think it need some solution. A couple ideas

  • do not compose into canSendOps but just call this readonly which to me makes it clear i also need to track the read-only signal
  • send this combined signal on both connection and readonly status change

my preference is to not compose into canSendOps, and just expose readonly. we could add a free function to container utils that takes ConnectionStatusTemplate can computes canSendOPs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do signal changes of canSendOps. See emitServiceConnectionEvents implementation and calls. In test code look at case "should handle connection type changes".
Additionally, you can look at #25751 which uses this new support fully.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you saying when readonly state changes we trigger a connection state change with the updated canSendOps? I don't see code that does that, but it could just be missing it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the call i see to emitServiceConnectionEvents only occurs on setConnectionStatus which i don't believe is called readonly changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my read of the code ContainerRuntime maintains canSendOps exclusively through setConnectionStateCore. At the end of that method is call to emitServiceConnectionEvents which will notify for a change in canSendOps whether from readonly or other reasons.
(started Teams chat for efficient discussion)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In container.ts:

deltaManager.on("readonly", (readonly) => {
			if (this.loaded) {
				this.setConnectionStatus(readonly);
			}
			this.emit("readonly", readonly);
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion we will follow up with a break-out of readonly explicitly in the new connection status object. That will help is stay distinct from canSendOp (that will still always be false if readonly is true). We can also extend it overtime to add more things of interest.

@jason-ha jason-ha merged commit 5721d4a into main Oct 27, 2025
52 checks passed
@jason-ha jason-ha deleted the test/client/catchingUp-processing-foundation branch October 27, 2025 19:18
anthony-murphy-agent pushed a commit to anthony-murphy-agent/FluidFramework that referenced this pull request Jan 14, 2026
…#25750)

`IRuntime` now has an optional (preferred) `setConnectionStatus` method
that replaces the previous `setConnectionState` method (still required
for compatibility). The new method is called for all `ConnectionState`
changes, including `CatchingUp` and `EstablishingConnection`. Calls may
also be made when readonly state changes, even if there is no overall
change in connection status.

`ContainerRuntime` announces fewer "disconnected" events when a client
is not fully connected and the readonly state changes.

And add case to test missing setConnectionStatus while making its
presence the default.

Add internal Signal only based Audience that can be used while
CatchingUp.

For Container Extensions:
- rename "connectionTypeChanged" event to "operabilityChanged" to allow
for later move to operate during CatchingUp
- Document JoinedStatus states
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: loader Loader related issues area: runtime Runtime related issues base: main PRs targeted against main branch public api change Changes to a public API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments