maxpool 1.5.7 → 1.5.8
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/package.json +1 -1
- package/src/restart-controller.js +29 -2
package/package.json
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
const NON_UPSTREAM_ROUTES = new Set(['(queued)', '(none available)']);
|
|
2
2
|
|
|
3
3
|
export class RestartController {
|
|
4
|
-
constructor({
|
|
4
|
+
constructor({
|
|
5
|
+
pauseAdmission,
|
|
6
|
+
restartNow,
|
|
7
|
+
log = console.log,
|
|
8
|
+
// Bounded drain: wait at most this long for in-flight upstream requests to
|
|
9
|
+
// finish, then force the restart anyway. Without a bound, a single long
|
|
10
|
+
// streaming/thinking request (minutes) — or a held stream on the 7-day
|
|
11
|
+
// heartbeat — pins the restart on "Restart pending…" forever (the stuck-`r`
|
|
12
|
+
// bug). Dropped requests reconnect after restart, as the message promises.
|
|
13
|
+
drainTimeoutMs = 10_000,
|
|
14
|
+
setTimeoutFn = setTimeout,
|
|
15
|
+
clearTimeoutFn = clearTimeout,
|
|
16
|
+
}) {
|
|
5
17
|
this.pauseAdmission = pauseAdmission;
|
|
6
18
|
this.restartNow = restartNow;
|
|
7
19
|
this.log = log;
|
|
20
|
+
this.drainTimeoutMs = drainTimeoutMs;
|
|
21
|
+
this.setTimeoutFn = setTimeoutFn;
|
|
22
|
+
this.clearTimeoutFn = clearTimeoutFn;
|
|
8
23
|
this.activeRequests = new Set();
|
|
9
24
|
this.upstreamRequests = new Set();
|
|
10
25
|
this.pending = false;
|
|
11
26
|
this.restarting = false;
|
|
27
|
+
this._drainTimer = null;
|
|
12
28
|
}
|
|
13
29
|
|
|
14
30
|
requestStarted(id) {
|
|
@@ -41,7 +57,14 @@ export class RestartController {
|
|
|
41
57
|
|
|
42
58
|
this.pending = true;
|
|
43
59
|
const queuedOrIdle = Math.max(0, this.activeRequests.size - this.upstreamRequests.size);
|
|
44
|
-
this.log(`[Maxpool] Restart pending; admission paused while ${this.upstreamRequests.size} upstream request(s) finish. ${queuedOrIdle} queued/idle request(s) will reconnect after restart.`);
|
|
60
|
+
this.log(`[Maxpool] Restart pending; admission paused while ${this.upstreamRequests.size} upstream request(s) finish (up to ${Math.round(this.drainTimeoutMs / 1000)}s). ${queuedOrIdle} queued/idle request(s) will reconnect after restart.`);
|
|
61
|
+
// Force the restart if the drain overruns — never hang on a long stream.
|
|
62
|
+
this._drainTimer = this.setTimeoutFn(() => {
|
|
63
|
+
if (!this.pending || this.restarting) return;
|
|
64
|
+
this.log(`[Maxpool] Restart drain timed out; forcing restart with ${this.upstreamRequests.size} upstream request(s) still in flight (they will reconnect).`);
|
|
65
|
+
this._restart();
|
|
66
|
+
}, this.drainTimeoutMs);
|
|
67
|
+
this._drainTimer?.unref?.();
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
_maybeRestart() {
|
|
@@ -53,6 +76,10 @@ export class RestartController {
|
|
|
53
76
|
if (this.restarting) return;
|
|
54
77
|
this.restarting = true;
|
|
55
78
|
this.pending = false;
|
|
79
|
+
if (this._drainTimer) {
|
|
80
|
+
this.clearTimeoutFn(this._drainTimer);
|
|
81
|
+
this._drainTimer = null;
|
|
82
|
+
}
|
|
56
83
|
this.restartNow();
|
|
57
84
|
}
|
|
58
85
|
}
|