rollbridge 0.1.23 → 0.1.25
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/AGENTS.md +55 -0
- package/README.md +63 -39
- package/TODO.md +5 -4
- package/docs/cli.md +26 -6
- package/docs/config.md +28 -8
- package/docs/nginx.md +5 -4
- package/docs/tensorbuzz-runbook.md +91 -125
- package/docs/troubleshooting.md +18 -9
- package/docs/velocious.md +93 -170
- package/docs/workers.md +81 -103
- package/package.json +1 -1
- package/src/daemon.js +3 -2
- package/test/shutdown-completion.test.js +57 -3
package/AGENTS.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Rollbridge contributor guidance
|
|
2
|
+
|
|
3
|
+
Rollbridge is the process supervisor and local traffic switcher. Keep deployment
|
|
4
|
+
tool concerns outside this repository: Rampway owns activation transactions,
|
|
5
|
+
deploy locks, release-retention metadata, and on-disk cleanup; Rollbridge owns
|
|
6
|
+
process lifecycle, retained generations, ports, and recovery state.
|
|
7
|
+
|
|
8
|
+
## Background-jobs lifecycle invariant
|
|
9
|
+
|
|
10
|
+
- One runtime generation is one release-scoped `background-jobs-main` plus its
|
|
11
|
+
worker pool. Start the complete candidate generation before activation.
|
|
12
|
+
- After activation, retire the old generation as one unit. Its main stops
|
|
13
|
+
schedules, new dispatch, and new ordinary worker handoffs; its workers stop
|
|
14
|
+
accepting handoffs. The old main remains running with those workers and owns
|
|
15
|
+
their connections, lease fencing, report acceptance and acknowledgement, and
|
|
16
|
+
durable store transitions. The worker/reporting side durably retries terminal
|
|
17
|
+
reports, tracks outstanding report promises, enforces per-job execution
|
|
18
|
+
timeouts, and owns and reaps child runners. Main and workers remain one release
|
|
19
|
+
generation until every accepted handoff settles.
|
|
20
|
+
- Returned or retried work may be dispatched by the new active generation. A
|
|
21
|
+
retired main never dispatches it again. Old workers never reconnect or hand
|
|
22
|
+
over to the new main during a normal deploy.
|
|
23
|
+
- Jobs generations may overlap for hours on release-scoped endpoints. Beacon may
|
|
24
|
+
remain shared on `7330`; jobs-main must use a per-release port range.
|
|
25
|
+
- Deploy success is candidate activation and health. Deploy completion must not
|
|
26
|
+
wait for retired jobs generations, workers, jobs, HTTP/WebSocket connections,
|
|
27
|
+
or other retained services. HTTP and jobs drains are independent; an HTTP
|
|
28
|
+
drain finishing or timing out must not stop a live jobs generation.
|
|
29
|
+
- Persist and recover retired-generation ownership across later deploys and
|
|
30
|
+
supervisor/host recovery. Multiple generations may drain concurrently. Report
|
|
31
|
+
release references so the deployment tool can keep them pinned until no
|
|
32
|
+
retained process uses them.
|
|
33
|
+
- Runtime-owner replacement transfers or preserves this durable supervision and
|
|
34
|
+
returns once the replacement is healthy. It is never a synchronous full
|
|
35
|
+
shutdown. Per-job timeouts remain valid, but a normal worker-shutdown timeout
|
|
36
|
+
is not the deploy solution; legitimate multi-hour drains are valid.
|
|
37
|
+
|
|
38
|
+
Documentation must distinguish required architecture from behavior not yet
|
|
39
|
+
implemented. Do not claim production compliance when source/config still uses a
|
|
40
|
+
fixed jobs-main, worker adoption by a new main, destructive orphan recovery, or
|
|
41
|
+
synchronous cleanup.
|
|
42
|
+
|
|
43
|
+
## Validation and publication
|
|
44
|
+
|
|
45
|
+
The project is ESM JavaScript with JSDoc type checking. Package scripts are the
|
|
46
|
+
source of truth: `npm run typecheck`, `npm run lint`, `npm test`, and the combined
|
|
47
|
+
`npm run all-checks`. Run focused checks for the files changed; documentation-only
|
|
48
|
+
work requires at least `git diff --check` plus any existing repository-owned
|
|
49
|
+
Markdown/link check, without installing dependencies.
|
|
50
|
+
|
|
51
|
+
Work on a feature branch and open a normal pull request against `master`; never
|
|
52
|
+
push feature work directly to `master`. Releases are maintainer-only and use
|
|
53
|
+
`npm run release:patch` from an up-to-date clean default branch after
|
|
54
|
+
`npm run all-checks`; do not edit package versions or publish during ordinary PR
|
|
55
|
+
work. See `docs/releasing.md` for the complete release checklist.
|
package/README.md
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Rollbridge is a Node.js process supervisor and local traffic switcher for zero-downtime deploys.
|
|
4
4
|
|
|
5
|
-
Nginx points at one stable Rollbridge proxy port. Deploy tooling asks Rollbridge to start a new release, health-check it, switch new traffic to it
|
|
5
|
+
Nginx points at one stable Rollbridge proxy port. Deploy tooling asks Rollbridge to start a new release, health-check it, and switch new traffic to it. Retirement then continues asynchronously: HTTP/WebSocket connections and retained process generations drain independently after the deploy command returns.
|
|
6
|
+
|
|
7
|
+
> **Required jobs-generation contract:** a release-scoped background-jobs
|
|
8
|
+
> runtime is its own `background-jobs-main` plus worker pool. Rollbridge starts a
|
|
9
|
+
> complete candidate generation before activation. After activation the retired
|
|
10
|
+
> main stops schedules, new dispatch, and new worker handoffs, but remains with
|
|
11
|
+
> its old workers to supervise every handoff it already made until all jobs and
|
|
12
|
+
> workers settle. Old workers never move to the new main. Generations may overlap
|
|
13
|
+
> for hours on separate ports, and neither deploy completion nor HTTP drain
|
|
14
|
+
> completion waits for or kills them. See [Background-job worker
|
|
15
|
+
> deployment](docs/workers.md) and the [Velocious deployment
|
|
16
|
+
> guide](docs/velocious.md).
|
|
17
|
+
|
|
18
|
+
This is the required architecture, not evidence that every released runtime or
|
|
19
|
+
consumer config already implements durable recovery and release-reference
|
|
20
|
+
reporting; verify source and config before claiming compliance.
|
|
6
21
|
|
|
7
22
|
## Install
|
|
8
23
|
|
|
@@ -47,23 +62,28 @@ export default {
|
|
|
47
62
|
processes: [
|
|
48
63
|
{
|
|
49
64
|
id: "beacon",
|
|
50
|
-
policy: "
|
|
65
|
+
policy: "service",
|
|
51
66
|
cwd: "{{releasePath}}",
|
|
52
67
|
command: "env VELOCIOUS_BEACON_PORT={{port}} npx velocious beacon",
|
|
53
|
-
port:
|
|
68
|
+
port: 7330
|
|
54
69
|
},
|
|
55
70
|
{
|
|
56
71
|
id: "background-jobs-worker",
|
|
57
72
|
policy: "companion",
|
|
58
73
|
cwd: "{{releasePath}}",
|
|
74
|
+
env: {VELOCIOUS_BACKGROUND_JOBS_PORT: "{{ports.background-jobs-main}}"},
|
|
59
75
|
command: "npx velocious background-jobs-worker",
|
|
76
|
+
nonBlockingDrain: true,
|
|
77
|
+
gracefulStopMs: "indefinite",
|
|
60
78
|
outputLines: 200
|
|
61
79
|
},
|
|
62
80
|
{
|
|
63
81
|
id: "background-jobs-main",
|
|
64
82
|
policy: "service",
|
|
83
|
+
deployStrategy: "handoff",
|
|
65
84
|
cwd: "{{releasePath}}",
|
|
66
|
-
command: "npx velocious background-jobs-main"
|
|
85
|
+
command: "env VELOCIOUS_BACKGROUND_JOBS_PORT={{port}} npx velocious background-jobs-main",
|
|
86
|
+
port: {from: 7331, to: 7399}
|
|
67
87
|
},
|
|
68
88
|
{
|
|
69
89
|
id: "web",
|
|
@@ -118,10 +138,11 @@ See [`docs/config.md`](docs/config.md#processesmemory).
|
|
|
118
138
|
memory: {limitBytes: 536870912, warnBytes: 402653184, checkIntervalMs: 5000}
|
|
119
139
|
```
|
|
120
140
|
|
|
121
|
-
Set a process's `stopSignal` (default `"SIGTERM"`) to the signal it quiets on
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
Set a process's `stopSignal` (default `"SIGTERM"`) to the signal it quiets on.
|
|
142
|
+
This is a process-level stop mechanism, not the primary deploy-completion
|
|
143
|
+
mechanism for a release-scoped jobs generation. A retired generation may remain
|
|
144
|
+
for hours, and its old jobs-main must stay available until its workers finish.
|
|
145
|
+
For example, a generic worker that drains on `SIGINT`:
|
|
125
146
|
|
|
126
147
|
```js
|
|
127
148
|
{id: "worker", policy: "companion", command: "…", stopSignal: "SIGINT", gracefulStopMs: 60000}
|
|
@@ -138,18 +159,19 @@ queue. See [`docs/config.md`](docs/config.md#processesreplicas).
|
|
|
138
159
|
{id: "worker", policy: "companion", command: "npx velocious background-jobs-worker", replicas: 4}
|
|
139
160
|
```
|
|
140
161
|
|
|
141
|
-
For workers that quiesce or drain via a command, set a `lifecycle` block —
|
|
162
|
+
For generic workers that quiesce or drain via a command, set a `lifecycle` block —
|
|
142
163
|
Rollbridge runs `quietCommand`, then drains (`drainCommand`/`drainTimeoutMs`),
|
|
143
164
|
then `stopCommand`/`stopSignal`, then `SIGKILL` after `gracefulStopMs` when
|
|
144
165
|
gracefully stopping the process. Each hook is bounded so it can't wedge a stop.
|
|
145
166
|
|
|
146
|
-
Set `nonBlockingDrain: true` on a worker companion
|
|
147
|
-
|
|
148
|
-
|
|
167
|
+
Set `nonBlockingDrain: true` on a jobs worker companion so it stops accepting new
|
|
168
|
+
handoffs as soon as its release retires, independently of the proxied connection
|
|
169
|
+
drain. Its release-scoped handoff jobs-main remains running to supervise existing
|
|
170
|
+
handoffs and exits only after the worker pool has drained.
|
|
149
171
|
|
|
150
|
-
See [`docs/workers.md`](docs/workers.md) for the full
|
|
151
|
-
deployment pattern
|
|
152
|
-
|
|
172
|
+
See [`docs/workers.md`](docs/workers.md) for the full release-generation
|
|
173
|
+
deployment pattern: a handoff `background-jobs-main`, its companion worker pool,
|
|
174
|
+
independent quiescence, and durable supervision while retained generations drain.
|
|
153
175
|
|
|
154
176
|
Set `releaseRetention` to bound how many stopped (drained) releases the daemon
|
|
155
177
|
keeps in memory and reports in `status`. `keep` (default `10`) retains the most
|
|
@@ -270,8 +292,9 @@ A release-scoped helper (for example a background worker bound to one release).
|
|
|
270
292
|
It starts **before** the proxied process in the same release, so release-local
|
|
271
293
|
dependencies are ready before the health check, and it is auto-restarted while
|
|
272
294
|
its release is active. Each release gets its own companions; a release's
|
|
273
|
-
companions stop when that release is drained and retired after a newer
|
|
274
|
-
takes over.
|
|
295
|
+
companions normally stop when that release is drained and retired after a newer
|
|
296
|
+
release takes over. A jobs worker configured with `nonBlockingDrain` instead
|
|
297
|
+
quiesces at retirement and drains independently of HTTP/WebSocket connections.
|
|
275
298
|
|
|
276
299
|
```js
|
|
277
300
|
{
|
|
@@ -279,7 +302,8 @@ takes over.
|
|
|
279
302
|
policy: "companion",
|
|
280
303
|
cwd: "{{releasePath}}",
|
|
281
304
|
command: "npx velocious background-jobs-worker",
|
|
282
|
-
|
|
305
|
+
nonBlockingDrain: true,
|
|
306
|
+
gracefulStopMs: "indefinite"
|
|
283
307
|
}
|
|
284
308
|
```
|
|
285
309
|
|
|
@@ -301,36 +325,36 @@ new copies simultaneously during a deploy would be unsafe.
|
|
|
301
325
|
|
|
302
326
|
### `service`
|
|
303
327
|
|
|
304
|
-
A daemon-wide
|
|
305
|
-
Velocious Beacon
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
it restarts from the newest good release. It keeps restarting until the daemon
|
|
310
|
-
shuts down.
|
|
328
|
+
A service can be daemon-wide and persistent, or release-scoped with
|
|
329
|
+
`deployStrategy: "handoff"`. Velocious Beacon is normally persistent on a stable
|
|
330
|
+
port. `background-jobs-main` is not: it must be a handoff service with one port
|
|
331
|
+
per release so old workers keep their old coordinator while new workers use the
|
|
332
|
+
candidate coordinator.
|
|
311
333
|
|
|
312
334
|
```js
|
|
313
335
|
{
|
|
314
336
|
id: "background-jobs-main",
|
|
315
337
|
policy: "service",
|
|
338
|
+
deployStrategy: "handoff",
|
|
316
339
|
cwd: "{{releasePath}}",
|
|
317
340
|
command: "npx velocious background-jobs-main",
|
|
318
|
-
port: 7331
|
|
341
|
+
port: {from: 7331, to: 7399}
|
|
319
342
|
}
|
|
320
343
|
```
|
|
321
344
|
|
|
322
345
|
### Deploy ordering
|
|
323
346
|
|
|
324
|
-
On `rollbridge deploy`,
|
|
347
|
+
On `rollbridge deploy`, the required ordering is:
|
|
325
348
|
|
|
326
|
-
1. starts any
|
|
349
|
+
1. starts any missing persistent service and the candidate's handoff services;
|
|
327
350
|
2. starts the new release's `companion`s, then its `proxied` process, and
|
|
328
351
|
health-checks the proxied process;
|
|
329
352
|
3. switches new traffic to the new release;
|
|
330
|
-
4.
|
|
353
|
+
4. marks the previous jobs-main and worker pool retired as one generation;
|
|
331
354
|
5. replaces `singleton`s (stops the old one, then starts the new one);
|
|
332
|
-
6.
|
|
333
|
-
|
|
355
|
+
6. returns success without waiting for the previous generation or its independent
|
|
356
|
+
HTTP/WebSocket drain; Rollbridge supervises all retained drains in the
|
|
357
|
+
background and reaps each generation only after its handoffs and workers end.
|
|
334
358
|
|
|
335
359
|
If the new release fails to start or health-check, the previous release stays
|
|
336
360
|
active and any service started during this deploy is rolled back.
|
|
@@ -413,13 +437,13 @@ rollbridge daemon --config /srv/ticket-server/rollbridge.js \
|
|
|
413
437
|
```
|
|
414
438
|
|
|
415
439
|
External supervisors that need to replace a foreground owner without waiting
|
|
416
|
-
for
|
|
417
|
-
health-checks the exact release first. Only then does it retire the accepted
|
|
418
|
-
owner's proxy/control listeners
|
|
419
|
-
|
|
420
|
-
binds the stable listeners
|
|
421
|
-
owner untouched. This is opt-in;
|
|
422
|
-
their existing behavior.
|
|
440
|
+
for retained generations to drain add `--takeover-owner`. The candidate starts
|
|
441
|
+
and health-checks the exact release first. Only then does it retire the accepted
|
|
442
|
+
owner's proxy/control listeners. Durable supervision of old jobs-main/worker
|
|
443
|
+
generations must be preserved or transferred while the attested replacement
|
|
444
|
+
binds the stable listeners; replacement does not mean full synchronous shutdown.
|
|
445
|
+
Candidate bootstrap failure leaves the accepted owner untouched. This is opt-in;
|
|
446
|
+
ordinary daemon bootstrap and `shutdown` keep their existing behavior.
|
|
423
447
|
|
|
424
448
|
The four bootstrap inputs are all-or-nothing and use absolute config/release
|
|
425
449
|
paths. Rollbridge binds its proxy, activates the release through the normal
|
|
@@ -600,7 +624,7 @@ daemon holds its log file open, so logrotate needs `copytruncate`.
|
|
|
600
624
|
|
|
601
625
|
## Deployment Notes
|
|
602
626
|
|
|
603
|
-
Run migrations before `rollbridge deploy`, and keep migrations backwards-compatible while old and new web
|
|
627
|
+
Run migrations before `rollbridge deploy`, and keep migrations backwards-compatible while old and new web and jobs generations overlap. Velocious Beacon may be a persistent fixed-port `service`; configure `background-jobs-main` as a release-scoped handoff service on a port range. A normal deploy may leave several retired generations draining concurrently.
|
|
604
628
|
|
|
605
629
|
See [`docs/deploy-recipes.md`](docs/deploy-recipes.md) for ready-to-use shell, CI, and Capistrano recipes that drive Rollbridge through its CLI, and [`docs/troubleshooting.md`](docs/troubleshooting.md) for diagnosing health-check failures, port conflicts, stale sockets, crash loops, and stuck draining releases.
|
|
606
630
|
|
package/TODO.md
CHANGED
|
@@ -30,11 +30,12 @@ This roadmap tracks planned Rollbridge features and documentation. Rollbridge sh
|
|
|
30
30
|
- [x] Distinguish crash restarts, deploy replacements, manual restarts, and memory restarts in status/events. (Per-process `lastStartReason` + a `reason` on the `process started` event; the `memory` reason is wired and fires once memory supervision restarts a process.)
|
|
31
31
|
- [x] Add a `restart` CLI command for a single process, a policy group, or all non-proxied workers.
|
|
32
32
|
- [x] Keep restart behavior safe for job workers by using lifecycle hooks before termination. (Manual restart, memory restart, and deploy-drain stops all run the `lifecycle` hooks via `stop()`.)
|
|
33
|
-
- [x] Graceful
|
|
33
|
+
- [x] Graceful process-stop controls for job workers.
|
|
34
34
|
- [x] Add generic lifecycle hooks such as `quietCommand`, `drainCommand`, `drainTimeoutMs`, and `stopCommand` (per-process `lifecycle`).
|
|
35
35
|
- [x] Support signal-only lifecycle steps for workers that can quiet on a Unix signal. (Per-process `stopSignal`; sent before the `SIGKILL`-after-`gracefulStopMs` fallback.)
|
|
36
|
-
- [x] Add a non-blocking drain mode so
|
|
37
|
-
- [x] Document
|
|
36
|
+
- [x] Add a non-blocking drain mode so a worker can quiesce at release retirement independently of the HTTP/WebSocket connection drain (`nonBlockingDrain`). This control alone does not provide durable retired-generation supervision.
|
|
37
|
+
- [x] Document the required Velocious release-generation contract (`docs/velocious.md` and `docs/workers.md`) without treating documentation as proof that the runtime implements it.
|
|
38
|
+
- [ ] Implement and verify durable release-scoped jobs-main retirement: owned-handoff supervision, recovery across daemon/host replacement, multiple concurrent retired generations, and release-reference reporting for cleanup pins.
|
|
38
39
|
- [x] Replicas and stable worker indexes. (Supported on port-less `companion` processes; `proxied`/`singleton`/ported processes stay single.)
|
|
39
40
|
- [x] Allow one process config to start multiple replicas (`replicas`, companion-only for now).
|
|
40
41
|
- [x] Expose `ROLLBRIDGE_REPLICA_INDEX`, replica count, and per-replica template context (`{{replicaIndex}}`/`{{replicaCount}}`).
|
|
@@ -91,7 +92,7 @@ This roadmap tracks planned Rollbridge features and documentation. Rollbridge sh
|
|
|
91
92
|
- [x] Write a CLI reference for `daemon`, `ensure-daemon`, `deploy`, `status`, `stop`, `shutdown`, and future commands (`docs/cli.md`).
|
|
92
93
|
- [x] Expand process policy docs with deployment examples for `proxied`, `companion`, `singleton`, and `service`.
|
|
93
94
|
- [x] Document memory checks and auto-restart behavior after the feature lands (`docs/config.md` → `processes[].memory`).
|
|
94
|
-
- [x] Document
|
|
95
|
+
- [x] Document the required background-job generation pattern (`docs/workers.md`: release-scoped jobs-main + worker pool, independent quiescence, durable retained supervision, and deploy completion that does not wait for drains).
|
|
95
96
|
- [x] Document worker lifecycle hooks (`docs/config.md` → `processes[].lifecycle`, `docs/workers.md`).
|
|
96
97
|
- [x] Add a Velocious deployment guide with Beacon, background-jobs-main, background-jobs-worker, and web process examples (`docs/velocious.md`).
|
|
97
98
|
- [x] Add an Nginx guide with WebSocket headers, timeouts, and common failure modes (`docs/nginx.md`).
|
package/docs/cli.md
CHANGED
|
@@ -66,10 +66,16 @@ and waits for control-socket deployments.
|
|
|
66
66
|
|
|
67
67
|
`--takeover-owner` requires the complete bootstrap tuple. It bootstraps and
|
|
68
68
|
health-checks the replacement before sending the current daemon the private
|
|
69
|
-
retirement command.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
retirement command. The current `performOwnerRetirement` path quiesces every
|
|
70
|
+
service, singleton, starting release, and retained release, releases the stable
|
|
71
|
+
listeners, and starts asynchronous `stop()` calls for all of them. It neither
|
|
72
|
+
preserves nor transfers retained-generation supervision to the replacement.
|
|
73
|
+
The replacement can bind before those stops finish. A bootstrap failure occurs
|
|
74
|
+
before retirement, so the previously accepted owner remains available.
|
|
75
|
+
|
|
76
|
+
A compliant future owner handoff must instead preserve or transfer durable
|
|
77
|
+
supervision of retained generations without handing old workers to a new
|
|
78
|
+
jobs-main. Current `--takeover-owner` does not provide that behavior.
|
|
73
79
|
|
|
74
80
|
## `ensure-daemon`
|
|
75
81
|
|
|
@@ -120,12 +126,26 @@ rollbridge deploy --release-path <path>
|
|
|
120
126
|
[--daemon-start-timeout-ms <ms>]
|
|
121
127
|
```
|
|
122
128
|
|
|
123
|
-
Starts the prepared release, health-checks the proxied
|
|
124
|
-
traffic to it
|
|
129
|
+
Starts the complete prepared release generation, health-checks the proxied
|
|
130
|
+
process, and switches new traffic to it. The current daemon then starts
|
|
131
|
+
retirement of the previous release asynchronously, so the command does not wait
|
|
132
|
+
for old workers, jobs, or HTTP/WebSocket connections to finish. Prints
|
|
125
133
|
`{"status": "success", "activeReleaseId": "...", "previousReleaseId": "..."}`.
|
|
126
134
|
If the new release fails to start or health-check, the previous release stays
|
|
127
135
|
active and the command errors.
|
|
128
136
|
|
|
137
|
+
After candidate activation, `Daemon.deploy()` synchronously waits for singleton
|
|
138
|
+
replacement before starting `drainAndPrune` and returning. A replacement failure
|
|
139
|
+
can therefore return a non-zero result while the candidate remains active, and a
|
|
140
|
+
slow replacement delays both the response and retirement of the old release.
|
|
141
|
+
|
|
142
|
+
This is a process-lifetime non-blocking drain, not durable supervision across a
|
|
143
|
+
daemon or host restart. It continues across later deploys only while the same
|
|
144
|
+
daemon remains alive. After a restart, surviving PIDs from persisted state are
|
|
145
|
+
advisory orphans that Rollbridge cannot re-adopt; explicit `recover --force`
|
|
146
|
+
stops them. Restart-surviving retained-generation ownership and recovery remain
|
|
147
|
+
required future behavior.
|
|
148
|
+
|
|
129
149
|
Before each deploy, the daemon reloads the config path it was started with.
|
|
130
150
|
Compatible process and lifecycle changes apply to the new release and govern
|
|
131
151
|
how the previous release retires, including updated `nonBlockingDrain`,
|
package/docs/config.md
CHANGED
|
@@ -75,7 +75,7 @@ to let a deploy group talk to the daemon.
|
|
|
75
75
|
| `proxy.upstreamHost` | string | `proxy.host`, or `"127.0.0.1"` when `proxy.host` is `0.0.0.0`/`::` | Host Rollbridge uses for release health checks and proxy targets. |
|
|
76
76
|
| `proxy.healthPath` | string | `"/ping"` | Default health-check path for proxied processes. |
|
|
77
77
|
| `proxy.healthTimeoutMs` | number | `30000` | Default health-check timeout for proxied processes. |
|
|
78
|
-
| `proxy.drainTimeoutMs` | number | `60000` | How long to drain
|
|
78
|
+
| `proxy.drainTimeoutMs` | number | `60000` | How long to drain HTTP/WebSocket connections before stopping the retired proxied process. Expiry never stops an independently draining jobs generation. |
|
|
79
79
|
| `proxy.forceStopTimeoutMs` | number | `10000` | Default per-process graceful-stop timeout (`SIGTERM`, then `SIGKILL`). |
|
|
80
80
|
|
|
81
81
|
## `releaseRetention`
|
|
@@ -212,6 +212,20 @@ range** so old and new instances can run at the same time:
|
|
|
212
212
|
|
|
213
213
|
Reference it from same-release processes with `{{ports.background-jobs-main}}`.
|
|
214
214
|
During a deploy, old workers keep the old port and new workers get the new port.
|
|
215
|
+
For background jobs, the required compliant architecture makes the handoff
|
|
216
|
+
service and its workers one release generation. Immediately after activation,
|
|
217
|
+
retirement must quiesce the old jobs-main's scheduling, dispatch, and new worker
|
|
218
|
+
handoffs while keeping it with its workers until their accepted work settles.
|
|
219
|
+
Workers are not adopted by the new service.
|
|
220
|
+
|
|
221
|
+
That immediate old-main quiescence is **required future compliance behavior**,
|
|
222
|
+
not current `deployStrategy: "handoff"` behavior. Today the release group starts
|
|
223
|
+
`stop()` for `nonBlockingDrain` companions at retirement but sends no retirement
|
|
224
|
+
or quiescence notice to the handoff service. It waits for the connection drain,
|
|
225
|
+
stops other dependent processes, waits for the non-blocking companion stops, and
|
|
226
|
+
only then stops the handoff service. Consequently, old and new jobs-main
|
|
227
|
+
instances can overlap scheduling and dispatch ownership. Do not treat the
|
|
228
|
+
configuration above alone as compliance with the background-jobs contract.
|
|
215
229
|
|
|
216
230
|
### `processes[].lifecycle`
|
|
217
231
|
|
|
@@ -220,6 +234,11 @@ deploy's drain, a `rollbridge restart`, a memory restart, or shutdown. They let
|
|
|
220
234
|
job worker quiesce and finish in-flight work before it is terminated. Omit
|
|
221
235
|
`lifecycle` for the default behavior (just `stopSignal` then `SIGKILL`).
|
|
222
236
|
|
|
237
|
+
These hooks describe an individual process stop. They do not define when a
|
|
238
|
+
deploy completes and must not impose a short normal-drain deadline on a jobs
|
|
239
|
+
generation. Per-job timeouts remain the correct bound for genuinely hung jobs;
|
|
240
|
+
legitimate hours-long generation drains are valid.
|
|
241
|
+
|
|
223
242
|
| Field | Type | Default | Description |
|
|
224
243
|
| --- | --- | --- | --- |
|
|
225
244
|
| `lifecycle.quietCommand` | string | unset | Run first to tell the process to stop accepting new work. |
|
|
@@ -253,15 +272,16 @@ That keeps a worker alive in case the draining web process still depends on it
|
|
|
253
272
|
but it also holds a background worker open for the whole connection drain.
|
|
254
273
|
|
|
255
274
|
Set `nonBlockingDrain: true` on a `companion` whose work is independent of the
|
|
256
|
-
proxied process (a job worker on a shared queue).
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
275
|
+
proxied process (a job worker on a shared queue). Rollbridge starts that
|
|
276
|
+
companion's configured stop sequence **as soon as the release is retired**, in
|
|
277
|
+
parallel with the connection drain, rather than after it. Its quiet command or
|
|
278
|
+
signal must make the worker stop accepting new handoffs. The asynchronous
|
|
279
|
+
release drain continues after the deploy response. As described above, current
|
|
280
|
+
Rollbridge does not simultaneously quiesce the handoff service, so this setting
|
|
281
|
+
alone does not prevent overlapping jobs-main scheduling or dispatch ownership.
|
|
262
282
|
|
|
263
283
|
```js
|
|
264
|
-
{id: "worker", policy: "companion", command: "…", nonBlockingDrain: true, stopSignal: "SIGINT", gracefulStopMs:
|
|
284
|
+
{id: "worker", policy: "companion", command: "…", nonBlockingDrain: true, stopSignal: "SIGINT", gracefulStopMs: "indefinite"}
|
|
265
285
|
```
|
|
266
286
|
|
|
267
287
|
### `processes[].restart`
|
package/docs/nginx.md
CHANGED
|
@@ -67,10 +67,11 @@ Related Rollbridge timeouts (configured in `rollbridge.js`, not Nginx):
|
|
|
67
67
|
|
|
68
68
|
- `proxy.healthTimeoutMs` gates how long a new release has to become healthy
|
|
69
69
|
before a deploy aborts — it does not affect request timeouts.
|
|
70
|
-
- `proxy.drainTimeoutMs` is how long Rollbridge keeps an old
|
|
71
|
-
in-flight connections during a deploy. Keep Nginx's
|
|
72
|
-
WebSocket locations comfortably above it so the front
|
|
73
|
-
connections Rollbridge is still draining.
|
|
70
|
+
- `proxy.drainTimeoutMs` is how long Rollbridge keeps an old proxied web process
|
|
71
|
+
alive for in-flight connections during a deploy. Keep Nginx's
|
|
72
|
+
`proxy_read_timeout` for WebSocket locations comfortably above it so the front
|
|
73
|
+
end doesn't cut connections Rollbridge is still draining. Retained jobs
|
|
74
|
+
generations drain independently and are not stopped when this timeout expires.
|
|
74
75
|
|
|
75
76
|
## Forwarded headers
|
|
76
77
|
|