@fluojs/websockets 1.0.0-beta.3 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +13 -11
- package/README.md +13 -11
- package/dist/bun/bun-service.d.ts +11 -0
- package/dist/bun/bun-service.d.ts.map +1 -1
- package/dist/bun/bun-service.js +185 -5
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts +11 -0
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts.map +1 -1
- package/dist/cloudflare-workers/cloudflare-workers-service.js +218 -49
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +2 -2
- package/dist/deno/deno-service.d.ts +11 -0
- package/dist/deno/deno-service.d.ts.map +1 -1
- package/dist/deno/deno-service.js +217 -48
- package/package.json +8 -8
|
@@ -11,6 +11,7 @@ import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
|
11
11
|
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
12
12
|
const DEFAULT_MAX_WEBSOCKET_CONNECTIONS = 1_000;
|
|
13
13
|
const DEFAULT_MAX_WEBSOCKET_PAYLOAD_BYTES = 1_048_576;
|
|
14
|
+
const DEFAULT_WEBSOCKET_SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
14
15
|
const LIFECYCLE_LOG_CONTEXT = 'WebSocketGatewayLifecycleService';
|
|
15
16
|
const WEBSOCKET_OPEN_READY_STATE = 1;
|
|
16
17
|
function hasCloudflareWorkerWebSocketBindingHost(adapter) {
|
|
@@ -44,6 +45,16 @@ function resolveMessageByteLength(message) {
|
|
|
44
45
|
}
|
|
45
46
|
return message.byteLength;
|
|
46
47
|
}
|
|
48
|
+
function createCompletionSignal() {
|
|
49
|
+
let resolve;
|
|
50
|
+
const promise = new Promise(res => {
|
|
51
|
+
resolve = res;
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
promise,
|
|
55
|
+
resolve
|
|
56
|
+
};
|
|
57
|
+
}
|
|
47
58
|
|
|
48
59
|
/**
|
|
49
60
|
* Boots Cloudflare Workers websocket gateways and manages their room lifecycle state.
|
|
@@ -53,11 +64,14 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
53
64
|
static {
|
|
54
65
|
[_CloudflareWorkersWeb, _initClass] = _applyDecs(this, [Inject(RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER, HTTP_APPLICATION_ADAPTER, WEBSOCKET_OPTIONS_INTERNAL)], []).c;
|
|
55
66
|
}
|
|
67
|
+
isShuttingDown = false;
|
|
68
|
+
pendingUpgradeOperations = new Set();
|
|
56
69
|
pendingUpgradeReservations = 0;
|
|
57
70
|
roomSockets = new Map();
|
|
58
71
|
shutdownPromise;
|
|
59
72
|
socketRegistry = new Map();
|
|
60
73
|
socketRooms = new Map();
|
|
74
|
+
socketStates = new Map();
|
|
61
75
|
constructor(runtimeContainer, compiledModules, logger, adapter, moduleOptions) {
|
|
62
76
|
this.runtimeContainer = runtimeContainer;
|
|
63
77
|
this.compiledModules = compiledModules;
|
|
@@ -93,54 +107,61 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
93
107
|
createBinding(descriptors) {
|
|
94
108
|
const descriptorsByPath = this.groupDescriptorsByPath(descriptors);
|
|
95
109
|
return {
|
|
96
|
-
fetch:
|
|
97
|
-
if (!isWebSocketUpgradeRequest(request)) {
|
|
98
|
-
return new Response(null, {
|
|
99
|
-
status: 426
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
let targetPath;
|
|
103
|
-
try {
|
|
104
|
-
targetPath = normalizeGatewayPath(new URL(request.url).pathname);
|
|
105
|
-
} catch {
|
|
106
|
-
return new Response(null, {
|
|
107
|
-
status: 400
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
const matchedDescriptors = descriptorsByPath.get(targetPath);
|
|
111
|
-
if (!matchedDescriptors) {
|
|
112
|
-
return new Response(null, {
|
|
113
|
-
status: 404
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
const rejection = await this.resolveUpgradeRejection(request, targetPath);
|
|
117
|
-
if (rejection) {
|
|
118
|
-
return new Response(rejection.body ?? null, {
|
|
119
|
-
headers: rejection.headers,
|
|
120
|
-
status: rejection.status
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
let response;
|
|
124
|
-
let serverSocket;
|
|
125
|
-
try {
|
|
126
|
-
({
|
|
127
|
-
response,
|
|
128
|
-
serverSocket
|
|
129
|
-
} = host.upgrade(request));
|
|
130
|
-
} catch (error) {
|
|
131
|
-
this.releaseUpgradeReservation();
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
serverSocket.accept();
|
|
135
|
-
void this.bindConnectionHandlers(serverSocket, request, matchedDescriptors).catch(error => {
|
|
136
|
-
this.unregisterSocket(this.findSocketId(serverSocket));
|
|
137
|
-
this.logger.error('WebSocket gateway open lifecycle failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
138
|
-
serverSocket.close(1011, 'Internal server error');
|
|
139
|
-
});
|
|
140
|
-
return response;
|
|
141
|
-
}
|
|
110
|
+
fetch: (request, host) => this.trackPendingUpgradeOperation(this.handleUpgradeRequest(request, host, descriptorsByPath))
|
|
142
111
|
};
|
|
143
112
|
}
|
|
113
|
+
async handleUpgradeRequest(request, host, descriptorsByPath) {
|
|
114
|
+
if (!isWebSocketUpgradeRequest(request)) {
|
|
115
|
+
return new Response(null, {
|
|
116
|
+
status: 426
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
let targetPath;
|
|
120
|
+
try {
|
|
121
|
+
targetPath = normalizeGatewayPath(new URL(request.url).pathname);
|
|
122
|
+
} catch {
|
|
123
|
+
return new Response(null, {
|
|
124
|
+
status: 400
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const matchedDescriptors = descriptorsByPath.get(targetPath);
|
|
128
|
+
if (!matchedDescriptors) {
|
|
129
|
+
return new Response(null, {
|
|
130
|
+
status: 404
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const rejection = await this.resolveUpgradeRejection(request, targetPath);
|
|
134
|
+
if (rejection) {
|
|
135
|
+
return new Response(rejection.body ?? null, {
|
|
136
|
+
headers: rejection.headers,
|
|
137
|
+
status: rejection.status
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (this.isShuttingDown) {
|
|
141
|
+
this.releaseUpgradeReservation();
|
|
142
|
+
return new Response('WebSocket server is shutting down.', {
|
|
143
|
+
status: 503
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
let response;
|
|
147
|
+
let serverSocket;
|
|
148
|
+
try {
|
|
149
|
+
({
|
|
150
|
+
response,
|
|
151
|
+
serverSocket
|
|
152
|
+
} = host.upgrade(request));
|
|
153
|
+
} catch (error) {
|
|
154
|
+
this.releaseUpgradeReservation();
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
serverSocket.accept();
|
|
158
|
+
void this.trackPendingUpgradeOperation(this.bindConnectionHandlers(serverSocket, request, matchedDescriptors)).catch(error => {
|
|
159
|
+
this.unregisterSocket(this.findSocketId(serverSocket));
|
|
160
|
+
this.logger.error('WebSocket gateway open lifecycle failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
161
|
+
serverSocket.close(1011, 'Internal server error');
|
|
162
|
+
});
|
|
163
|
+
return response;
|
|
164
|
+
}
|
|
144
165
|
groupDescriptorsByPath(descriptors) {
|
|
145
166
|
const descriptorsByPath = new Map();
|
|
146
167
|
for (const descriptor of descriptors) {
|
|
@@ -157,17 +178,35 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
157
178
|
const state = this.createConnectionHandlerState(request, descriptors);
|
|
158
179
|
this.releaseUpgradeReservation();
|
|
159
180
|
this.socketRegistry.set(state.socketId, socket);
|
|
181
|
+
this.socketStates.set(state.socketId, state);
|
|
160
182
|
this.attachConnectionListeners(state, socket, request);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
183
|
+
try {
|
|
184
|
+
await this.resolveConnectionGateways(state);
|
|
185
|
+
await this.runConnectHandlers(state, socket);
|
|
186
|
+
await this.finalizeConnectionBinding(state, socket, request);
|
|
187
|
+
if (this.isShuttingDown && socket.readyState === WEBSOCKET_OPEN_READY_STATE) {
|
|
188
|
+
socket.close(1001, 'Server shutting down');
|
|
189
|
+
await state.disconnectLifecyclePromise;
|
|
190
|
+
}
|
|
191
|
+
} finally {
|
|
192
|
+
if (!state.handlersReady && state.bufferedDisconnect) {
|
|
193
|
+
this.settleDisconnectLifecycle(state);
|
|
194
|
+
}
|
|
195
|
+
this.settleConnectLifecycle(state);
|
|
196
|
+
}
|
|
164
197
|
}
|
|
165
198
|
createConnectionHandlerState(request, descriptors) {
|
|
199
|
+
const connectLifecycle = createCompletionSignal();
|
|
200
|
+
const disconnectLifecycle = createCompletionSignal();
|
|
166
201
|
return {
|
|
167
202
|
bufferedDisconnect: undefined,
|
|
168
203
|
bufferedMessages: [],
|
|
169
204
|
bufferedMessagesStartIndex: 0,
|
|
205
|
+
connectLifecycleSettled: false,
|
|
206
|
+
connectLifecyclePromise: connectLifecycle.promise,
|
|
170
207
|
descriptors,
|
|
208
|
+
disconnectLifecycleSettled: false,
|
|
209
|
+
disconnectLifecyclePromise: disconnectLifecycle.promise,
|
|
171
210
|
enqueuedMessageCount: 0,
|
|
172
211
|
handlerQueue: Promise.resolve(),
|
|
173
212
|
handlersReady: false,
|
|
@@ -175,10 +214,26 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
175
214
|
queuedMessages: [],
|
|
176
215
|
queuedMessagesStartIndex: 0,
|
|
177
216
|
request,
|
|
217
|
+
resolveConnectLifecycle: connectLifecycle.resolve,
|
|
218
|
+
resolveDisconnectLifecycle: disconnectLifecycle.resolve,
|
|
178
219
|
resolved: [],
|
|
179
220
|
socketId: crypto.randomUUID()
|
|
180
221
|
};
|
|
181
222
|
}
|
|
223
|
+
settleConnectLifecycle(state) {
|
|
224
|
+
if (state.connectLifecycleSettled) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
state.connectLifecycleSettled = true;
|
|
228
|
+
state.resolveConnectLifecycle();
|
|
229
|
+
}
|
|
230
|
+
settleDisconnectLifecycle(state) {
|
|
231
|
+
if (state.disconnectLifecycleSettled) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
state.disconnectLifecycleSettled = true;
|
|
235
|
+
state.resolveDisconnectLifecycle();
|
|
236
|
+
}
|
|
182
237
|
attachConnectionListeners(state, socket, request) {
|
|
183
238
|
socket.addEventListener('message', event => {
|
|
184
239
|
if (this.closeOversizedPayload(state.socketId, socket, event.data)) {
|
|
@@ -316,6 +371,8 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
316
371
|
await dispatchGatewayDisconnect(state.resolved, socket, disconnectEvent.code, disconnectEvent.reason, state.socketId, this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
317
372
|
}).catch(error => {
|
|
318
373
|
this.logger.error('WebSocket gateway disconnect dispatch failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
374
|
+
}).finally(() => {
|
|
375
|
+
this.settleDisconnectLifecycle(state);
|
|
319
376
|
});
|
|
320
377
|
}
|
|
321
378
|
async resolveConnectionGateways(state) {
|
|
@@ -366,6 +423,12 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
366
423
|
return '';
|
|
367
424
|
}
|
|
368
425
|
async resolveUpgradeRejection(request, path) {
|
|
426
|
+
if (this.isShuttingDown) {
|
|
427
|
+
return {
|
|
428
|
+
body: 'WebSocket server is shutting down.',
|
|
429
|
+
status: 503
|
|
430
|
+
};
|
|
431
|
+
}
|
|
369
432
|
if (!this.tryReserveUpgradeSlot()) {
|
|
370
433
|
return {
|
|
371
434
|
body: 'WebSocket connection limit exceeded.',
|
|
@@ -442,6 +505,13 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
442
505
|
}
|
|
443
506
|
return configured;
|
|
444
507
|
}
|
|
508
|
+
resolveShutdownTimeoutMs() {
|
|
509
|
+
const configured = this.moduleOptions.shutdown?.timeoutMs;
|
|
510
|
+
if (typeof configured !== 'number' || !Number.isFinite(configured) || configured <= 0) {
|
|
511
|
+
return DEFAULT_WEBSOCKET_SHUTDOWN_TIMEOUT_MS;
|
|
512
|
+
}
|
|
513
|
+
return Math.floor(configured);
|
|
514
|
+
}
|
|
445
515
|
async shutdown() {
|
|
446
516
|
if (this.shutdownPromise) {
|
|
447
517
|
await this.shutdownPromise;
|
|
@@ -451,14 +521,112 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
451
521
|
await this.shutdownPromise;
|
|
452
522
|
}
|
|
453
523
|
async runShutdownLifecycle() {
|
|
524
|
+
this.isShuttingDown = true;
|
|
454
525
|
if (hasCloudflareWorkerWebSocketBindingHost(this.adapter)) {
|
|
455
526
|
this.adapter.configureWebSocketBinding(undefined);
|
|
456
527
|
}
|
|
528
|
+
const shutdownTimeoutMs = this.resolveShutdownTimeoutMs();
|
|
529
|
+
await this.awaitPendingUpgradeOperations(shutdownTimeoutMs);
|
|
530
|
+
await this.closeActiveSockets(shutdownTimeoutMs);
|
|
457
531
|
this.pendingUpgradeReservations = 0;
|
|
458
532
|
this.socketRegistry.clear();
|
|
459
533
|
this.socketRooms.clear();
|
|
534
|
+
this.socketStates.clear();
|
|
460
535
|
this.roomSockets.clear();
|
|
461
536
|
}
|
|
537
|
+
trackPendingUpgradeOperation(operation) {
|
|
538
|
+
if (typeof operation === 'function') {
|
|
539
|
+
return (...args) => this.trackPendingUpgradeOperation(operation(...args));
|
|
540
|
+
}
|
|
541
|
+
let trackedOperation;
|
|
542
|
+
trackedOperation = operation.then(() => undefined, () => undefined).finally(() => {
|
|
543
|
+
if (trackedOperation) {
|
|
544
|
+
this.pendingUpgradeOperations.delete(trackedOperation);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
this.pendingUpgradeOperations.add(trackedOperation);
|
|
548
|
+
return operation;
|
|
549
|
+
}
|
|
550
|
+
async awaitPendingUpgradeOperations(timeoutMs) {
|
|
551
|
+
if (this.pendingUpgradeOperations.size === 0) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
await new Promise((resolve, reject) => {
|
|
555
|
+
let settled = false;
|
|
556
|
+
const timeout = setTimeout(() => {
|
|
557
|
+
if (settled) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
settled = true;
|
|
561
|
+
reject(new Error(`Timed out while waiting for in-flight Cloudflare Worker websocket upgrades after ${String(timeoutMs)}ms.`));
|
|
562
|
+
}, timeoutMs);
|
|
563
|
+
Promise.all([...this.pendingUpgradeOperations]).then(() => {
|
|
564
|
+
if (settled) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
settled = true;
|
|
568
|
+
clearTimeout(timeout);
|
|
569
|
+
resolve();
|
|
570
|
+
}).catch(error => {
|
|
571
|
+
if (settled) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
settled = true;
|
|
575
|
+
clearTimeout(timeout);
|
|
576
|
+
reject(error);
|
|
577
|
+
});
|
|
578
|
+
}).catch(error => {
|
|
579
|
+
this.logger.error(`Failed to wait for in-flight Cloudflare Worker websocket upgrades within ${String(timeoutMs)}ms.`, error, LIFECYCLE_LOG_CONTEXT);
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
async closeActiveSockets(timeoutMs) {
|
|
583
|
+
const activeSockets = [...this.socketRegistry.entries()];
|
|
584
|
+
if (activeSockets.length === 0) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const activeStates = activeSockets.map(([socketId]) => this.socketStates.get(socketId)).filter(state => state !== undefined);
|
|
588
|
+
for (const [, socket] of activeSockets) {
|
|
589
|
+
if (socket.readyState === WEBSOCKET_OPEN_READY_STATE) {
|
|
590
|
+
socket.close(1001, 'Server shutting down');
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
await this.awaitHandlerQueueDrain(activeStates, timeoutMs);
|
|
594
|
+
}
|
|
595
|
+
async awaitHandlerQueueDrain(states, timeoutMs) {
|
|
596
|
+
if (states.length === 0) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
await new Promise((resolve, reject) => {
|
|
600
|
+
let settled = false;
|
|
601
|
+
const timeout = setTimeout(() => {
|
|
602
|
+
if (settled) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
settled = true;
|
|
606
|
+
reject(new Error(`Timed out while closing Cloudflare Worker websocket connections after ${String(timeoutMs)}ms.`));
|
|
607
|
+
}, timeoutMs);
|
|
608
|
+
Promise.all(states.map(async state => {
|
|
609
|
+
await state.connectLifecyclePromise;
|
|
610
|
+
await state.disconnectLifecyclePromise;
|
|
611
|
+
})).then(() => {
|
|
612
|
+
if (settled) {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
settled = true;
|
|
616
|
+
clearTimeout(timeout);
|
|
617
|
+
resolve();
|
|
618
|
+
}).catch(error => {
|
|
619
|
+
if (settled) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
settled = true;
|
|
623
|
+
clearTimeout(timeout);
|
|
624
|
+
reject(error);
|
|
625
|
+
});
|
|
626
|
+
}).catch(error => {
|
|
627
|
+
this.logger.error(`Failed to close Cloudflare Worker websocket connections within ${String(timeoutMs)}ms.`, error, LIFECYCLE_LOG_CONTEXT);
|
|
628
|
+
});
|
|
629
|
+
}
|
|
462
630
|
joinRoom(socketId, room) {
|
|
463
631
|
let rooms = this.socketRooms.get(socketId);
|
|
464
632
|
if (!rooms) {
|
|
@@ -519,6 +687,7 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
519
687
|
return;
|
|
520
688
|
}
|
|
521
689
|
this.socketRegistry.delete(socketId);
|
|
690
|
+
this.socketStates.delete(socketId);
|
|
522
691
|
const rooms = this.socketRooms.get(socketId);
|
|
523
692
|
if (rooms) {
|
|
524
693
|
for (const room of rooms) {
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAmC,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG9G,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAmC,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG9G,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AA8DrD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,uBAA4B,GACpC,kBAAkB,CAMpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CACvB,OAAO,SAAS,iBAAiB,GAAG,iBAAiB,EACrD,CAAC,SAAS,MAAM,OAAO,GAAG,MAAM,OAAO,EACvC,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,mBAAmB,CAKzC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,mBAAmB,CAI/C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,mBAAmB,CAIlD"}
|
package/dist/decorators.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ensureMetadataSymbol } from '@fluojs/core/internal';
|
|
2
2
|
import { webSocketGatewayMetadataSymbol, webSocketHandlerMetadataSymbol } from './metadata.js';
|
|
3
|
+
ensureMetadataSymbol();
|
|
3
4
|
function getStandardMetadataBag(metadata) {
|
|
4
|
-
void metadataSymbol;
|
|
5
5
|
return metadata;
|
|
6
6
|
}
|
|
7
7
|
function normalizeGatewayPath(path) {
|
|
@@ -12,20 +12,26 @@ export declare class DenoWebSocketGatewayLifecycleService implements OnApplicati
|
|
|
12
12
|
private readonly logger;
|
|
13
13
|
private readonly adapter;
|
|
14
14
|
private readonly moduleOptions;
|
|
15
|
+
private isShuttingDown;
|
|
16
|
+
private readonly pendingUpgradeOperations;
|
|
15
17
|
private pendingUpgradeReservations;
|
|
16
18
|
private readonly roomSockets;
|
|
17
19
|
private shutdownPromise;
|
|
18
20
|
private readonly socketRegistry;
|
|
19
21
|
private readonly socketRooms;
|
|
22
|
+
private readonly socketStates;
|
|
20
23
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, adapter: HttpApplicationAdapter, moduleOptions: WebSocketModuleOptions);
|
|
21
24
|
onApplicationBootstrap(): Promise<void>;
|
|
22
25
|
private assertNoServerBackedGatewayOptIn;
|
|
23
26
|
onApplicationShutdown(): Promise<void>;
|
|
24
27
|
onModuleDestroy(): Promise<void>;
|
|
25
28
|
private createBinding;
|
|
29
|
+
private handleUpgradeRequest;
|
|
26
30
|
private groupDescriptorsByPath;
|
|
27
31
|
private bindConnectionHandlers;
|
|
28
32
|
private createConnectionHandlerState;
|
|
33
|
+
private settleConnectLifecycle;
|
|
34
|
+
private settleDisconnectLifecycle;
|
|
29
35
|
private attachConnectionListeners;
|
|
30
36
|
private getBufferedMessageCount;
|
|
31
37
|
private getQueuedMessageCount;
|
|
@@ -50,8 +56,13 @@ export declare class DenoWebSocketGatewayLifecycleService implements OnApplicati
|
|
|
50
56
|
private tryReserveUpgradeSlot;
|
|
51
57
|
private releaseUpgradeReservation;
|
|
52
58
|
private resolveMaxPayloadBytes;
|
|
59
|
+
private resolveShutdownTimeoutMs;
|
|
53
60
|
private shutdown;
|
|
54
61
|
private runShutdownLifecycle;
|
|
62
|
+
private trackPendingUpgradeOperation;
|
|
63
|
+
private awaitPendingUpgradeOperations;
|
|
64
|
+
private closeActiveSockets;
|
|
65
|
+
private awaitHandlerQueueDrain;
|
|
55
66
|
joinRoom(socketId: string, room: string): void;
|
|
56
67
|
leaveRoom(socketId: string, room: string): void;
|
|
57
68
|
broadcastToRoom(room: string, event: string, data: unknown): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deno-service.d.ts","sourceRoot":"","sources":["../../src/deno/deno-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEzI,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAa3D,OAAO,KAAK,EAA8B,oBAAoB,EAA6B,MAAM,aAAa,CAAC;AAC/G,OAAO,KAAK,EAKV,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"deno-service.d.ts","sourceRoot":"","sources":["../../src/deno/deno-service.ts"],"names":[],"mappings":"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"}
|