Commit e6dc8a6
fix(jobs): unref parentPort after job completes to prevent Bun NAPI crash (#1227)
* fix(jobs): keep Bun event loop alive during job worker NAPI async work
Bun does not count NAPI-held JS callbacks (e.g. the resolve/reject passed
into RocksDB's native commit) as ref'd event-loop work. Job workers have no
other ref'd work (no HTTP server, all sibling ports are unref'd), so Bun
can drain and exit the event loop before the commit callback fires.
The symptom: csv_data_load jobs that trigger getNewId() (upsert with no
primary key column) hang indefinitely on Bun — the job stays IN_PROGRESS
because the worker exits silently before updateJob() is reached. HTTP
workers are unaffected because their HTTP server always holds a ref.
Fix: hold a ref'd setInterval for the duration of the job (including
updateJob) and clear it just before the unref'd exit setTimeout. Node is
unaffected (the interval is only created when globalThis.Bun is present).
Fixes #1222
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(jobs): unref parentPort after job completes to prevent Bun NAPI crash
The prior commit's premise was wrong. The actual root cause is a Bun 1.3.13
bug: calling process.exit() in a worker_threads.Worker that has lmdb-js
loaded, while sibling workers are running, triggers a NAPI fatal error
(panic: NAPI FATAL ERROR: Error::New napi_create_error) crashing the whole
process.
The crash chain for the CSV upsert integration test:
1. northnwd.suppliers has schemaDefined=false (create_table without attributes)
2. CSV upsert with a new column triggers addAttributes → signalSchemaChange
→ broadcastWithAcknowledgement, which calls port.ref() on ALL ports
including parentPort
3. After ACKs received, parentPort is never unref'd (by design for regular
workers, but wrong for job workers)
4. parentPort ref keeps the event loop alive until the 3s unref'd timer fires
5. realExit() → process.exit() in the lmdb-bearing job worker → Bun crash
Fix: unref parentPort after updateJob so the event loop drains naturally,
avoiding process.exit() entirely. Remove the setInterval keepalive which
was based on the incorrect premise.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent ca69f10 commit e6dc8a6
1 file changed
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
80 | 86 | | |
81 | 87 | | |
82 | 88 | | |
| |||
0 commit comments