Skip to content

Commit 340baad

Browse files
committed
implemented _handleConnectionClosed and fix issue with getVM
1 parent 0edf3d8 commit 340baad

File tree

2 files changed

+103
-14
lines changed

2 files changed

+103
-14
lines changed

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,6 @@ class DevHandler {
754754
existingConnection?.shutDown();
755755
services.connectedInstanceId = message.instanceId;
756756

757-
services.webSocketProxyService?.destroyIsolate();
758757
_logger.finest('WebSocket service reconnected for app: ${message.appId}');
759758

760759
_setupMainExecution(
@@ -800,7 +799,9 @@ class DevHandler {
800799
final appId = appConnection.request.appId;
801800

802801
if (useWebSocketConnection) {
803-
_servicesByAppId[appId]?.webSocketProxyService?.destroyIsolate();
802+
_logger.fine(
803+
'Isolate exit handled by WebSocket proxy service for app: $appId',
804+
);
804805
} else {
805806
_servicesByAppId[appId]?.chromeProxyService.destroyIsolate();
806807
}

dwds/lib/src/services/web_socket_proxy_service.dart

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,12 @@ class WebSocketProxyService implements VmServiceInterface {
104104
/// Active hot reload trackers by request ID.
105105
final Map<String, _HotReloadTracker> _pendingHotReloads = {};
106106

107-
/// App connection cleanup subscription.
108-
StreamSubscription<void>? _appConnectionDoneSubscription;
107+
/// App connection cleanup subscriptions by connection instance ID.
108+
final Map<String, StreamSubscription<void>> _appConnectionDoneSubscriptions =
109+
{};
110+
111+
/// Active connection count for this service.
112+
int _activeConnectionCount = 0;
109113

110114
/// Event stream controllers.
111115
final Map<String, StreamController<vm_service.Event>> _streamControllers = {};
@@ -153,15 +157,42 @@ class WebSocketProxyService implements VmServiceInterface {
153157
// Update app connection if override provided
154158
appConnection = appConnectionOverride ?? appConnection;
155159

160+
// Track this connection
161+
final connectionId = appConnection.request.instanceId;
162+
163+
// Check if this connection is already being tracked
164+
final isNewConnection =
165+
!_appConnectionDoneSubscriptions.containsKey(connectionId);
166+
167+
if (isNewConnection) {
168+
_activeConnectionCount++;
169+
_logger.fine(
170+
'Adding new connection: $connectionId (total: $_activeConnectionCount)',
171+
);
172+
} else {
173+
_logger.fine(
174+
'Reconnecting existing connection: $connectionId (total: $_activeConnectionCount)',
175+
);
176+
}
177+
156178
// Auto-cleanup on connection close
157-
await _appConnectionDoneSubscription?.cancel();
158-
_appConnectionDoneSubscription = appConnection.onDone.asStream().listen((
159-
_,
160-
) {
161-
destroyIsolate();
162-
});
179+
final existingSubscription = _appConnectionDoneSubscriptions[connectionId];
180+
await existingSubscription?.cancel();
181+
_appConnectionDoneSubscriptions[connectionId] = appConnection.onDone
182+
.asStream()
183+
.listen((_) {
184+
_handleConnectionClosed(connectionId);
185+
});
186+
187+
// If we already have a running isolate, just update the connection and return
188+
if (_isIsolateRunning && _isolateRef != null) {
189+
_logger.fine(
190+
'Reusing existing isolate ${_isolateRef!.id} for connection: $connectionId',
191+
);
192+
return;
193+
}
163194

164-
// Create isolate reference with unique ID that changes on each page refresh
195+
// Create isolate reference with unique ID
165196
final isolateId = '${++_globalIsolateIdCounter}';
166197
final isolateRef = vm_service.IsolateRef(
167198
id: isolateId,
@@ -175,6 +206,10 @@ class WebSocketProxyService implements VmServiceInterface {
175206
_vm.isolates?.add(isolateRef);
176207
final timestamp = DateTime.now().millisecondsSinceEpoch;
177208

209+
_logger.fine(
210+
'Created new isolate: $isolateId for connection: $connectionId',
211+
);
212+
178213
// Send lifecycle events
179214
_streamNotify(
180215
vm_service.EventStreams.kIsolate,
@@ -208,15 +243,55 @@ class WebSocketProxyService implements VmServiceInterface {
208243
if (!_initializedCompleter.isCompleted) _initializedCompleter.complete();
209244
}
210245

246+
/// Handles a connection being closed.
247+
void _handleConnectionClosed(String connectionId) {
248+
_logger.fine('Connection closed: $connectionId');
249+
250+
// Only decrement if this connection was actually being tracked
251+
if (_appConnectionDoneSubscriptions.containsKey(connectionId)) {
252+
// Remove the subscription for this connection
253+
_appConnectionDoneSubscriptions[connectionId]?.cancel();
254+
_appConnectionDoneSubscriptions.remove(connectionId);
255+
256+
// Decrease active connection count
257+
_activeConnectionCount--;
258+
_logger.fine(
259+
'Removed connection: $connectionId (remaining: $_activeConnectionCount)',
260+
);
261+
262+
// Only destroy the isolate if there are no more active connections
263+
if (_activeConnectionCount <= 0) {
264+
_logger.fine('No more active connections, destroying isolate');
265+
destroyIsolate();
266+
} else {
267+
_logger.fine(
268+
'Still have $_activeConnectionCount active connections, keeping isolate alive',
269+
);
270+
}
271+
} else {
272+
_logger.warning(
273+
'Attempted to close connection that was not tracked: $connectionId',
274+
);
275+
}
276+
}
277+
211278
/// Destroys the isolate and cleans up state.
212279
void destroyIsolate() {
213280
_logger.fine('Destroying isolate');
214-
if (!_isIsolateRunning) return;
281+
282+
if (!_isIsolateRunning) {
283+
_logger.fine('Isolate already destroyed, ignoring');
284+
return;
285+
}
215286

216287
final isolateRef = _isolateRef;
217288

218-
_appConnectionDoneSubscription?.cancel();
219-
_appConnectionDoneSubscription = null;
289+
// Cancel all connection subscriptions
290+
for (final subscription in _appConnectionDoneSubscriptions.values) {
291+
subscription.cancel();
292+
}
293+
_appConnectionDoneSubscriptions.clear();
294+
_activeConnectionCount = 0;
220295

221296
// Send exit event
222297
if (isolateRef != null) {
@@ -391,6 +466,19 @@ class WebSocketProxyService implements VmServiceInterface {
391466

392467
Future<vm_service.VM> _getVM() {
393468
return captureElapsedTime(() async {
469+
// Ensure the VM's isolate list is synchronized with our actual state
470+
if (_isIsolateRunning && _isolateRef != null) {
471+
// Make sure our isolate is in the VM's isolate list
472+
final isolateExists =
473+
_vm.isolates?.any((ref) => ref.id == _isolateRef!.id) ?? false;
474+
if (!isolateExists) {
475+
_vm.isolates?.add(_isolateRef!);
476+
}
477+
} else {
478+
// If no isolate is running, make sure the list is empty
479+
_vm.isolates?.clear();
480+
}
481+
394482
return _vm;
395483
}, (result) => DwdsEvent.getVM());
396484
}

0 commit comments

Comments
 (0)