Commit 8a31663
authored
fix: push isolate reuses FGS hub WebSocket (1-socket invariant) (#1104)
* fix: push isolate reuses FGS hub WebSocket instead of opening its own
PushNotificationIsolateManager previously always created a SignalingModuleImpl
directly, opening a second WebSocket when the FGS hub was already running.
This violated the 1-WebSocket invariant.
The fix adds createPushIsolateModule() to SignalingServicePlatform and
WebtritSignalingService. On Android, the method checks IsolateNameServer for
a live FGS hub: if found and acknowledged, a SignalingHubModule is returned
and no new connection is opened. When no hub is active (app killed), falls
back to a direct SignalingModuleImpl.
PushNotificationIsolateManager now exposes an init() method for async hub
discovery, called from _getOrInit() before run(). run() skips connect() when
the module reports isConnected (hub reuse path).
* logs: add diagnostic logs for push isolate signaling module resolution
Adds log lines to verify the 1-socket invariant at runtime:
- _initSignaling(): logs module type and isConnected after createPushIsolateModule
resolves, making hub-reuse vs direct-socket path visible in logcat
- close(): logs module type and pending request count on teardown
- _getOrInit(): logs before and after init() so init timing is traceable
These logs confirm whether the hub path or fallback path is taken on each push
notification, and that teardown completes cleanly.
* fix: push isolate starts FGS and waits for hub instead of direct socket
Previously createPushIsolateModule fell back immediately to a direct
SignalingModuleImpl when no hub was running (pushBound mode, first push
after app close). This violated the 1-WebSocket invariant: both the push
isolate and the Activity would open their own WebSocket connections.
New flow:
1. Hub already running -> reuse (persistent mode or second push)
2. No hub -> startFgsOnly(pushBound) -> poll IsolateNameServer until hub
registers and acknowledges -> return SignalingHubModule
3. Hub not available after 10 s -> emergency fallback to direct module
The push isolate now always shares the same FGS WebSocket with the
Activity, matching the intended architecture.
* fix: address Copilot review comments on push isolate hub reuse
- _tryConnectHub: yield to event loop after ack so hub replay events
(SignalingConnected etc.) are processed before returning the module.
Prevents run() from calling connect() on an already-live hub session
due to isConnected being transiently false while replay is in flight.
- run(): throw StateError when called before init() instead of silently
leaving _completer unresolved and hanging the caller until timeout.
- lefthook.yml: pass {1} to commit-msg-check.sh so the hook reads the
actual commit message file (git hook argv) instead of git log -1.
* refactor: unify push isolate signaling with Activity via WebtritSignalingService
Push isolate now uses WebtritSignalingService(mode: pushBound) directly,
the same mechanism the Activity uses. HubConnectionManager inside the
service handles FGS start, hub discovery, and auto-reconnect if the hub
is killed between push arrival and Activity open.
Removes createPushIsolateModule from platform API — it was a one-shot
workaround that bypassed HubConnectionManager and had no reconnect logic.
Removes _tryConnectHub, _startFgsOnly, and related constants from the
Android plugin. The single code path eliminates the duplication.
Lifecycle boundary remains unchanged:
push mode — FGS lives from push arrival through Activity close
persistent — FGS lives indefinitely
* fix: address remaining Copilot review comments
- Remove unnecessary async from _initSignaling() — nothing is awaited
- Rename log field hubConnected -> isConnected (accurate with WebtritSignalingService)
- Always call connect() in run() — WebtritSignalingService.connect() is
idempotent via _startPending/_isConnected guard; the old conditional
was left over from SignalingHubModule direct usage
- Fix class doc: qualify 1-WebSocket claim as Android-only
- Fix _initSignaling doc: remove auto-reconnect claim, HubConnectionManager
handles FGS start and hub discovery, not reconnect after disconnect
- commit-msg-check.sh: add guard for missing or unreadable $1 argument
* docs: fix stale comments after signaling unification
- init() doc: hub discovery and FGS start happen in connect() via
HubConnectionManager, not in init() as the old comment stated
- background_isolate_callbacks: same correction for _getOrInit comment
- commit-msg-check.sh: add set -euo pipefail for consistency with other scripts
* refactor: replace nullable signalingModule with late field and remove unnecessary async from init()
- _signalingModule/_signalingSubscription: SignalingModule? → late SignalingModule;
eliminates null-aware ?. access throughout the class since run() requires init() first
- Add _initialized bool flag so close() can guard disposal without accessing late fields prematurely
- init(): Future<void> async => _initSignaling() → void init() (sync, no await needed)
- run(): null check replaced with !_initialized guard; remove intermediate `module` local
- All ?. accesses on _signalingModule replaced with direct . access1 parent f4fb2a6 commit 8a31663
4 files changed
Lines changed: 65 additions & 16 deletions
File tree
- lib/features/call/services
- tool/scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
50 | 55 | | |
51 | 56 | | |
52 | 57 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
| |||
22 | 21 | | |
23 | 22 | | |
24 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
25 | 28 | | |
26 | 29 | | |
27 | 30 | | |
| |||
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
34 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
35 | 40 | | |
36 | 41 | | |
37 | 42 | | |
| |||
43 | 48 | | |
44 | 49 | | |
45 | 50 | | |
46 | | - | |
47 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
48 | 55 | | |
49 | 56 | | |
50 | 57 | | |
| |||
69 | 76 | | |
70 | 77 | | |
71 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
72 | 90 | | |
73 | 91 | | |
74 | 92 | | |
75 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
76 | 97 | | |
77 | 98 | | |
78 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
79 | 104 | | |
80 | 105 | | |
81 | 106 | | |
82 | 107 | | |
83 | 108 | | |
84 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
85 | 113 | | |
86 | 114 | | |
87 | 115 | | |
88 | 116 | | |
89 | 117 | | |
90 | 118 | | |
91 | 119 | | |
92 | | - | |
93 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
94 | 124 | | |
95 | 125 | | |
96 | 126 | | |
| |||
122 | 152 | | |
123 | 153 | | |
124 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
125 | 161 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
133 | 171 | | |
134 | 172 | | |
135 | 173 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | | - | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
4 | 10 | | |
5 | 11 | | |
6 | 12 | | |
| |||
0 commit comments