Skip to content

feat(apps): add multi-geo Socket Mode supervisor and transport - #685

Merged
teddy arida-moody (teddyam) merged 33 commits into
mainfrom
teddyam-socket-mode-geo-supervisor
Oct 1, 2026
Merged

teddy arida-moody (teddyam) merged 33 commits into
mainfrom
teddyam-socket-mode-geo-supervisor

Conversation

@teddyam

@teddyam teddy arida-moody (teddyam) commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Layer 3 of the Socket Mode stack, on top of #683 (SignalR connection) and #682 (protocol). Everything added here is internal: no public API, no App integration, no samples and no docs yet.

Changes

GeoSocket — one supervisor per geo

  • Startup: startup succeeds once one connection reports SocketReady. Failures retry within the startup budget, using the server's Retry-After when it sends one and backoff otherwise. A startup timeout of zero allows exactly one attempt.
  • Fresh connection per attempt: every attempt and every replacement creates a new connection through ISocketConnectionFactory. Each one carries a generation number, and only the current ready connection or one that is being retired can dispatch activities.
  • Token rotation (make-before-break): a replacement is scheduled at token lifetime minus a refresh margin, with a 1-second minimum. The old connection keeps dispatching until the replacement is ready. It is then retired after a handoff window (5 seconds). No rotation is scheduled when the token has no lifetime.
  • Reconnects: an unexpected close emits disconnected, then reconnected. A planned local stop or a rotation does not emit either.
  • Stop: StopAsync interrupts startup, retry, rotation and retirement work that is still pending. Every connection is stopped and disposed exactly once, and calling it again is safe.

SocketModeTransport — top level

  • Geo resolution: endpoints are {base}/{geo}/v3/websockets/connect. The default geos are amer, emea and apac. An empty geo means the base URL with no geo segment.
  • Start and stop: every geo starts at once. If any geo fails its initial start, the others are cancelled, everything is stopped and the first error is thrown. Stop tears down all geos.
  • Status: a combined status (Idle, Connecting, Ready, Disconnected, Stopped) and a per-geo status are tracked internally.
  • Dispatch:
    • Invoke activities get an invoke reply; other activities get an acknowledgement carrying the handler's status.
    • If the handler throws, the reply is 500 and an optional error hook is called.
    • An envelope with an unsupported protocol version gets a 400.

Tests

The SocketMode filter passes 118/118 on both net8.0 and net10.0. All tests use hand-written fakes, and timing tests use an injected TimeProvider instead of sleeping.

  • GeoSocketTests cover: startup, retry and Retry-After, reconnect, rotation handoff, rejection of stale generations, stop races, and exactly-once cleanup.
  • SocketModeTransportTests cover: geo resolution, fail-fast startup, status, and dispatch with its 400 and 500 cases.
  • SocketModeEndToEndTests run the transport together with the real negotiator from feat(apps): add Socket Mode protocol transport #682 and the real SignalR connection factory from feat(apps): add SignalR Socket Mode connection #683. Only the HTTP responses and the SignalR client are faked.

Teddy Arida-Moody and others added 11 commits September 22, 2026 17:15
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teddyam
teddy arida-moody (teddyam) added this pull request to stack #684 September 24, 2026 05:39
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Four moderate issues remain in token refresh timing, startup failure handling, protocol rejection replies, and stopped geo status reporting.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 4 Medium severity

Open (4)
What changed in this PR

Adds the internal multi-geo Socket Mode supervisor and transport layer.

Changes:

  • Adds per-geo startup, retries, reconnects, token rotation, and cleanup.
  • Adds multi-geo routing, lifecycle status, and activity dispatch.
  • Adds unit and end-to-end test coverage.
File Summary
test/​Microsoft.Teams.Apps.UnitTests/​SocketMode/​SocketModeTransportTests.cs Tests transport routing, status, startup failures, and dispatch behavior.
test/​Microsoft.Teams.Apps.UnitTests/​SocketMode/​SocketModeEndToEndTests.cs Tests integrated transport, negotiation, and SignalR behavior.
test/​Microsoft.Teams.Apps.UnitTests/​SocketMode/​GeoSocketTests.cs Tests supervision, retries, reconnects, rotation, stale generations, and cleanup.
src/​Microsoft.Teams.Apps/​SocketMode/​SocketModeTransport.cs Implements multi-geo orchestration and dispatch; moderate issues remain with cleanup error propagation, version-rejection reply shape, and stopped per-geo statuses.
src/​Microsoft.Teams.Apps/​SocketMode/​GeoSocket.cs Implements per-geo connection supervision and token rotation; token refresh timing may be incorrect after lengthy startup.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Microsoft.Teams.Apps/SocketMode/GeoSocket.cs
Comment thread src/Microsoft.Teams.Apps/SocketMode/SocketModeTransport.cs
Comment thread src/Microsoft.Teams.Apps/SocketMode/SocketModeTransport.cs Outdated
Comment thread src/Microsoft.Teams.Apps/SocketMode/SocketModeTransport.cs
Teddy Arida-Moody and others added 9 commits September 24, 2026 11:03
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Refactor OnActivity to await readiness before handling activity.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Teddy Arida-Moody and others added 2 commits September 24, 2026 11:06
Adds an internal GeoSocket that keeps one geo connected: initial startup
within a monotonic budget, Retry-After/backoff retries, reconnect after
unexpected closure, and make-before-break token rotation with a retiring
handoff window. Dispatch is fenced to the active or retiring generation,
and every connection is stopped and disposed exactly once.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve per-geo negotiate endpoints, start every geo with fail-fast
startup, stop all geos, aggregate status internally, and dispatch
envelopes with invoke/ack replies and 500 on handler failure.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teddyam
teddy arida-moody (teddyam) force-pushed the teddyam-socket-mode-geo-supervisor branch from 0181348 to 5e4c28f Compare September 24, 2026 18:07
Base automatically changed from teddyam-socket-mode-signalr-connection to main September 24, 2026 18:39
Teddy Arida-Moody and others added 2 commits September 24, 2026 11:39
Adds an internal GeoSocket that keeps one geo connected: initial startup
within a monotonic budget, Retry-After/backoff retries, reconnect after
unexpected closure, and make-before-break token rotation with a retiring
handoff window. Dispatch is fenced to the active or retiring generation,
and every connection is stopped and disposed exactly once.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve per-geo negotiate endpoints, start every geo with fail-fast
startup, stop all geos, aggregate status internally, and dispatch
envelopes with invoke/ack replies and 500 on handler failure.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teddyam
teddy arida-moody (teddyam) force-pushed the teddyam-socket-mode-geo-supervisor branch from 5e4c28f to 8953d5e Compare September 24, 2026 18:39
Comment thread src/Microsoft.Teams.Apps/SocketMode/GeoSocket.cs
Comment thread src/Microsoft.Teams.Apps/SocketMode/SocketModeTransport.cs
Comment thread src/Microsoft.Teams.Apps/SocketMode/GeoSocket.cs Outdated
Log connection stop/dispose failures instead of throwing so they cannot
mask the original startup failure or end a geo's supervisor, and mark
every geo as Stopped when the transport stops.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teddyam
teddy arida-moody (teddyam) force-pushed the teddyam-socket-mode-geo-supervisor branch from cd40b2d to ab2a6ae Compare September 24, 2026 22:12
Teddy Arida-Moody and others added 3 commits September 24, 2026 15:33
A faulted supervisor is already logged; rethrowing it from stop could
mask the original startup failure in the transport.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread src/Microsoft.Teams.Apps/SocketMode/GeoSocket.cs Outdated
Comment thread src/Microsoft.Teams.Apps/SocketMode/GeoSocket.cs
@teddyam
teddy arida-moody (teddyam) added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit 33591e4 Oct 1, 2026
8 checks passed
@teddyam
teddy arida-moody (teddyam) deleted the teddyam-socket-mode-geo-supervisor branch October 1, 2026 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants