Skip to content

Commit 3638692

Browse files
committed
Improved stability, better timeout system
1 parent 9744cd2 commit 3638692

File tree

7 files changed

+158
-100
lines changed

7 files changed

+158
-100
lines changed

src/Components/Web.JS/src/Boot.Server.Common.ts

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { CircuitDotNetCallDispatcher } from './Platform/Circuits/CircuitDotNetCa
2323

2424
let renderingFailed = false;
2525
let started = false;
26+
let circuitActive = false;
2627
let startCircuitPromise: Promise<boolean> | undefined;
2728
let connection: HubConnection;
2829
let circuit: CircuitDescriptor;
@@ -113,6 +114,7 @@ export function startCircuit(components: RootComponentManager<ServerComponentDes
113114
throw new Error('Cannot start the circuit until Blazor Server has started.');
114115
}
115116

117+
circuitActive = true;
116118
startCircuitPromise ??= (async () => {
117119
const appState = discoverPersistedState(document);
118120
renderQueue = new RenderQueue(logger);
@@ -132,29 +134,21 @@ export function startCircuit(components: RootComponentManager<ServerComponentDes
132134
return startCircuitPromise;
133135
}
134136

135-
export function hasStartedServer(): boolean {
136-
return started;
137-
}
138-
139-
export function isCircuitActive(): boolean {
140-
return startCircuitPromise !== undefined;
141-
}
142-
143-
export function attachCircuitAfterRenderCallback(callback: typeof afterRenderCallback) {
144-
if (afterRenderCallback) {
145-
throw new Error('A Blazor Server after render batch callback was already attached.');
137+
export async function disposeCircuit() {
138+
if (!circuitActive) {
139+
return;
146140
}
147141

148-
afterRenderCallback = callback;
149-
}
142+
circuitActive = false;
150143

151-
export function disposeCircuit() {
152-
if (startCircuitPromise === undefined) {
144+
await startCircuitPromise;
145+
146+
if (circuitActive) {
147+
// A call to 'startCircuit' was made while we were waiting to dispose the circuit.
148+
// Therefore, we should abort the disposal.
153149
return;
154150
}
155151

156-
startCircuitPromise = undefined;
157-
158152
// We dispose the .NET dispatcher to prevent it from being used in the future.
159153
// This avoids cases where, for example, .NET object references from a
160154
// disconnected circuit start pointing to .NET objects for a new circuit.
@@ -163,6 +157,25 @@ export function disposeCircuit() {
163157
connection.stop();
164158

165159
detachWebRendererInterop(WebRendererId.Server);
160+
161+
// Setting this to undefined allows a new circuit to be started in the future.
162+
startCircuitPromise = undefined;
163+
}
164+
165+
export function hasStartedServer(): boolean {
166+
return started;
167+
}
168+
169+
export function isCircuitActive(): boolean {
170+
return circuitActive;
171+
}
172+
173+
export function attachCircuitAfterRenderCallback(callback: typeof afterRenderCallback) {
174+
if (afterRenderCallback) {
175+
throw new Error('A Blazor Server after render batch callback was already attached.');
176+
}
177+
178+
afterRenderCallback = callback;
166179
}
167180

168181
async function initializeConnection(logger: Logger, circuit: CircuitDescriptor): Promise<HubConnection> {

src/Components/Web.JS/src/Boot.Web.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { attachComponentDescriptorHandler, registerAllComponentDescriptors } fro
2121
import { hasProgrammaticEnhancedNavigationHandler, performProgrammaticEnhancedNavigation } from './Services/NavigationUtils';
2222

2323
let started = false;
24-
const rootComponentManager = new WebRootComponentManager();
24+
let rootComponentManager: WebRootComponentManager;
2525

2626
function boot(options?: Partial<WebStartOptions>) : Promise<void> {
2727
if (started) {
@@ -43,6 +43,8 @@ function boot(options?: Partial<WebStartOptions>) : Promise<void> {
4343
setCircuitOptions(options?.circuit);
4444
setWebAssemblyOptions(options?.webAssembly);
4545

46+
rootComponentManager = new WebRootComponentManager(options?.ssr?.circuitInactivityTimeoutMs ?? 2000);
47+
4648
attachComponentDescriptorHandler(rootComponentManager);
4749
attachStreamingRenderingListener(options?.ssr, rootComponentManager);
4850

src/Components/Web.JS/src/Platform/SsrStartOptions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,10 @@ export interface SsrStartOptions {
77
* (for example, during enhanced navigation or streaming rendering).
88
*/
99
disableDomPreservation?: boolean;
10+
11+
/**
12+
* Configures how long to wait after all Blazor Server components have been removed from the document
13+
* before closing the circuit.
14+
*/
15+
circuitInactivityTimeoutMs?: number;
1016
}

src/Components/Web.JS/src/Rendering/DomMerging/DomSync.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { UpdateCost, ItemList, Operation, computeEditScript } from './EditScript
1111
let descriptorHandler: DescriptorHandler | null = null;
1212

1313
export interface DescriptorHandler {
14-
registerComponentDescriptor(descriptor: ComponentDescriptor): void;
14+
registerComponent(descriptor: ComponentDescriptor): void;
1515
}
1616

1717
export function attachComponentDescriptorHandler(handler: DescriptorHandler) {
@@ -22,7 +22,7 @@ export function registerAllComponentDescriptors(root: Node) {
2222
const descriptors = upgradeComponentCommentsToLogicalRootComments(root);
2323

2424
for (const descriptor of descriptors) {
25-
descriptorHandler?.registerComponentDescriptor(descriptor);
25+
descriptorHandler?.registerComponent(descriptor);
2626
}
2727
}
2828

@@ -244,7 +244,7 @@ function treatAsInsertion(nodeToInsert: Node, nextNode: Node | null, parentNode:
244244
while (iterator.nextNode()) {
245245
const logicalRootDescriptor = getLogicalRootDescriptor(iterator.referenceNode as unknown as LogicalElement);
246246
if (logicalRootDescriptor) {
247-
descriptorHandler?.registerComponentDescriptor(logicalRootDescriptor);
247+
descriptorHandler?.registerComponent(logicalRootDescriptor);
248248
}
249249
}
250250
}

0 commit comments

Comments
 (0)