Skip to content

Commit a6ab635

Browse files
committed
Support reconnects on page refreshes for SSE client connections
If we treat reloads as parts of an app lifecycle, it seems natural to preserve an app instance id on full reloads, and looks like a session storage is a good fit. Fixes #2726.
1 parent c820e2a commit a6ab635

File tree

3 files changed

+57
-32
lines changed

3 files changed

+57
-32
lines changed

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -636,21 +636,11 @@ class DevHandler {
636636
readyToRunMainCompleter.future,
637637
);
638638

639-
// We can take over a connection if there is no connectedInstanceId (this
640-
// means the client completely disconnected), or if the existing
641-
// AppConnection is in the KeepAlive state (this means it disconnected but
642-
// is still waiting for a possible reconnect - this happens during a page
643-
// reload).
644-
final canReconnect =
645-
services != null &&
646-
(services.connectedInstanceId == null ||
647-
existingConnection?.isInKeepAlivePeriod == true);
648-
649-
if (canReconnect) {
639+
if (_canReconnect(existingConnection, message)) {
650640
// Disconnect any old connection (eg. those in the keep-alive waiting
651641
// state when reloading the page).
652642
existingConnection?.shutDown();
653-
final chromeProxy = services.proxyService;
643+
final chromeProxy = services!.proxyService;
654644
if (chromeProxy is ChromeProxyService) {
655645
chromeProxy.destroyIsolate();
656646
}
@@ -703,24 +693,10 @@ class DevHandler {
703693
readyToRunMainCompleter.future,
704694
);
705695

706-
// Allow connection reuse for page refreshes and same instance reconnections
707-
final isSameInstance =
708-
existingConnection?.request.instanceId == message.instanceId;
709-
final isKeepAliveReconnect =
710-
existingConnection?.isInKeepAlivePeriod == true;
711-
final hasNoActiveConnection = services?.connectedInstanceId == null;
712-
final noExistingConnection = existingConnection == null;
713-
714-
final canReconnect =
715-
services != null &&
716-
(isSameInstance ||
717-
(isKeepAliveReconnect && hasNoActiveConnection) ||
718-
(noExistingConnection && hasNoActiveConnection));
719-
720-
if (canReconnect) {
696+
if (_canReconnect(existingConnection, message)) {
721697
// Reconnect to existing service.
722698
await _reconnectToService(
723-
services,
699+
services!,
724700
existingConnection,
725701
connection,
726702
message,
@@ -749,6 +725,30 @@ class DevHandler {
749725
return connection;
750726
}
751727

728+
/// Allow connection reuse for page refreshes and same instance reconnections
729+
bool _canReconnect(
730+
AppConnection? existingConnection,
731+
ConnectRequest message,
732+
) {
733+
final services = _servicesByAppId[message.appId];
734+
735+
if (services == null) {
736+
return false;
737+
}
738+
739+
if (existingConnection?.request.instanceId == message.instanceId) {
740+
return true;
741+
}
742+
743+
final isKeepAliveReconnect =
744+
existingConnection?.isInKeepAlivePeriod == true;
745+
final hasNoActiveConnection = services.connectedInstanceId == null;
746+
final noExistingConnection = existingConnection == null;
747+
748+
return (isKeepAliveReconnect && hasNoActiveConnection) ||
749+
(noExistingConnection && hasNoActiveConnection);
750+
}
751+
752752
/// Handles reconnection to existing services for web-socket mode.
753753
Future<void> _reconnectToService(
754754
AppDebugServices services,

dwds/lib/src/injected/client.js

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dwds/web/client.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,22 @@ Future<void>? main() {
4747
() async {
4848
// Set the unique id for this instance of the app.
4949
// Test apps may already have this set.
50-
dartAppInstanceId ??= const Uuid().v1();
50+
const dartAppInstanceIdKey = 'dartAppInstanceId';
51+
if (dartAppInstanceId == null) {
52+
// Check the session storage for the instance id.
53+
final storedInstanceId = window.sessionStorage.getItem(
54+
dartAppInstanceIdKey,
55+
);
56+
if (storedInstanceId != null) {
57+
dartAppInstanceId = storedInstanceId;
58+
} else {
59+
dartAppInstanceId = const Uuid().v1();
60+
window.sessionStorage.setItem(
61+
dartAppInstanceIdKey,
62+
dartAppInstanceId!,
63+
);
64+
}
65+
}
5166

5267
final fixedPath = _fixProtocol(dwdsDevHandlerPath);
5368
final fixedUri = Uri.parse(fixedPath);

0 commit comments

Comments
 (0)