Skip to content

Commit a864856

Browse files
committed
Reload page automatically only when resume fails after non-graceful pause
1 parent 04ea8f0 commit a864856

File tree

7 files changed

+29
-13
lines changed

7 files changed

+29
-13
lines changed

src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
3636

3737
remote = false;
3838

39+
graceful = false;
40+
3941
retryWhenDocumentBecomesVisible: () => void;
4042

4143
constructor(dialogId: string, private readonly document: Document, private readonly logger: Logger) {
@@ -95,6 +97,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
9597
}
9698

9799
this.operation = options?.type ?? 'reconnect';
100+
this.graceful = (options?.type === 'pause') ? options.graceful : false;
98101

99102
this.retryButton.style.display = 'none';
100103
this.rejoiningAnimation.style.display = 'block';
@@ -105,6 +108,8 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
105108

106109
update(options: ReconnectDisplayUpdateOptions): void {
107110
this.operation = options.type;
111+
this.graceful = (options.type === 'pause') ? options.graceful : false;
112+
108113
if (this.operation === 'pause') {
109114
this.retryButton.style.display = 'none';
110115
this.rejoiningAnimation.style.display = 'none';
@@ -129,10 +134,16 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
129134
failed(): void {
130135
this.rejoiningAnimation.style.display = 'none';
131136
if (this.operation === 'pause') {
132-
// The client expected to be able to resume the circuit and it failed.
133-
// This typically happens when the server has been restarted and the circuit state is lost.
134-
// This is effectively the same as the circuit being rejected during reconnect.
135-
this.rejected();
137+
if (this.graceful) {
138+
// Circuit failed to resume after a graceful (client-requested) pause.
139+
// We show a retry UI to allow the user to try to continue without losing the state.
140+
this.resumeButton.style.display = 'block';
141+
this.status.innerHTML = 'Failed to resume.<br />Please retry or reload the page.';
142+
} else {
143+
// Circuit failed to resume after an ungraceful pause (e.g., server restart).
144+
// We treat this as non-recoverable rejection.
145+
this.rejected();
146+
}
136147
} else {
137148
this.retryButton.style.display = 'block';
138149
this.status.innerHTML = 'Failed to rejoin.<br />Please retry or reload the page.';
@@ -158,7 +169,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
158169
const successful = await Blazor.reconnect!();
159170
if (!successful) {
160171
// Try to resume the circuit if the reconnect failed
161-
this.update({ type: 'pause', remote: this.remote });
172+
this.update({ type: 'pause', remote: this.remote, graceful: this.graceful });
162173
const resumeSuccessful = await Blazor.resumeCircuit!();
163174
if (!resumeSuccessful) {
164175
this.failed();

src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectionHandler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class ReconnectionProcess {
7575
const displayOptions: ReconnectDisplayUpdateOptions = {
7676
type: isGracefulPause ? 'pause' : 'reconnect',
7777
remote: this.isRemote,
78+
graceful: !!isGracefulPause,
7879
currentAttempt: 0,
7980
secondsToNextAttempt: 0,
8081
};
@@ -85,6 +86,7 @@ class ReconnectionProcess {
8586
this.reconnectDisplay.update({
8687
type: 'pause',
8788
remote: this.isRemote,
89+
graceful: true,
8890
});
8991
}
9092
}
@@ -126,7 +128,7 @@ class ReconnectionProcess {
126128
if (!result) {
127129
// Try to resume the circuit if the reconnect failed
128130
// If the server responded and refused to reconnect, stop auto-retrying.
129-
this.reconnectDisplay.update({ type: 'pause', remote: true });
131+
this.reconnectDisplay.update({ type: 'pause', remote: true, graceful: false });
130132
const resumeResult = await this.resumeCallback();
131133
if (resumeResult) {
132134
return;

src/Components/Web.JS/src/Platform/Circuits/ReconnectDisplay.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export type ReconnectDisplayUpdateOptions = ReconnectOptions | PauseOptions;
1313

1414
export type PauseOptions = {
1515
type: 'pause',
16-
remote: boolean
16+
remote: boolean,
17+
graceful: boolean
1718
};
1819

1920
export type ReconnectOptions = {

src/Components/Web.JS/src/Platform/Circuits/ReconnectStateChangedEvent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export interface ReconnectStateChangedEvent {
33
currentAttempt?: number;
44
secondsToNextAttempt?: number;
55
remote?: boolean;
6+
graceful?: boolean;
67
}

src/Components/Web.JS/src/Platform/Circuits/UserSpecifiedDisplay.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
7171
}
7272
if (options.type === 'pause') {
7373
const remote = options.remote;
74+
const graceful = options.graceful;
7475
this.dialog.classList.remove(UserSpecifiedDisplay.ShowClassName, UserSpecifiedDisplay.RetryingClassName);
7576
this.dialog.classList.add(UserSpecifiedDisplay.PausedClassName);
76-
this.dispatchReconnectStateChangedEvent({ state: 'paused', remote: remote });
77+
this.dispatchReconnectStateChangedEvent({ state: 'paused', remote: remote, graceful: graceful });
7778
}
7879
}
7980

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Layout/ReconnectModal.razor

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
<p class="components-pause-visible">
2626
The session has been paused by the server.
2727
</p>
28-
<button id="components-resume-button" class="components-pause-visible">
29-
Resume
30-
</button>
3128
<p class="components-resume-failed-visible">
32-
Failed to resume the session.<br />Please reload the page.
29+
Failed to resume the session.<br />Please retry or reload the page.
3330
</p>
31+
<button id="components-resume-button" class="components-pause-visible components-resume-failed-visible">
32+
Resume
33+
</button>
3434
</div>
3535
</dialog>

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Layout/ReconnectModal.razor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function handleReconnectStateChanged(event) {
1515
reconnectModal.close();
1616
} else if (event.detail.state === "failed") {
1717
document.addEventListener("visibilitychange", retryWhenDocumentBecomesVisible);
18-
} else if (event.detail.state === "rejected" || event.detail.state === "resume-failed") {
18+
} else if (event.detail.state === "rejected" || (event.detail.state === "resume-failed" && !!event.detail.graceful)) {
1919
location.reload();
2020
}
2121
}

0 commit comments

Comments
 (0)