Commit 74d9529
fix: reject in-flight task promises when worker crashes (#146)
* fix: reject in-flight task promises when worker crashes
When a worker crashes (onerror event), tasks already dispatched to it had
their promises stored in promiseResponseMap but were never settled. The
error handler only restarted the worker and redistributed queued tasks —
in-flight tasks were silently dropped, causing pool.execute() callers to
hang indefinitely.
The fix iterates promiseResponseMap on worker error, finds all entries
targeting the crashed worker by stable workerId, and rejects them with a
descriptive error before termination.
Changes:
- Replace workerNodeKey (array index) with stable workerId in
PromiseResponseWrapper — indices become stale after removeWorkerNode
- Add handleWorkerNodeCrash() to unify crash recovery logic
- Add rejectInFlightTaskPromises() and rejectRemainingQueuedTaskPromises()
- Add updatePromiseResponseWorkerId() for task steal/redistribute tracking
- Resolve workerNodeKey dynamically from message.workerId at response time
- Gate exit handler worker restart on restartWorkerOnError option
- Add crash worker test and regression test for promise rejection
Port of poolifier/poolifier#3211
* [autofix.ci] apply automated fixes
* fix: add crashHandled flag, improve rejection logic and harden guards
- Add crashHandled flag to WorkerInfo to prevent double crash handling
between onerror and exit handlers
- Move rejectRemainingQueuedTaskPromises outside started/destroying guard
(queued promises must always be settled regardless of pool state)
- Handle workerId == null case in rejectInFlightTaskPromises (crash before
worker ID assignment)
- Add { cause } to crash Error constructors for error chain traceability
- Update task statistics (executing/failed) on crash rejection
- Add workerNodeKey === -1 guards in updatePromiseResponseWorkerId and
handleWorkerReadyResponse
- Exit handler: detect unexpected exit via crashHandled flag, condition
restart on restartWorkerOnError or normal exit
- Tighten test bounds for stolen/sequentiallyStolen task counts
Aligns with poolifier/poolifier#3211 latest changes
* fix: harden crash-handling guards and eliminate DRY violations
- Guard getWorkerNodeKeyByWorkerId against undefined workerId to prevent
erroneous matching of uninitialized worker nodes
- Call updatePromiseResponseWorkerId BEFORE handleTask in redistribute
and stealTask for correctness-by-construction (prevents stale workerId
if task response arrives synchronously)
- Construct crashError once in handleWorkerNodeCrash and pass as param
to rejectInFlightTaskPromises/rejectRemainingQueuedTaskPromises (DRY)
- Add executing--/failed++ stats in rejectInFlightTaskPromises null-path
for consistency with the non-null path
- Fix handleWorkerNodeCrash JSDoc to accurately describe behavior
* fix: add flushWorkerNodePromises catch-all for unsettled promises on exit
Add flushWorkerNodePromises() method as a catch-all to reject any
unsettled promises when a worker node exits without crash handling
(e.g., unexpected exit without onerror, or termination during pool
destroy).
The exit handler now has three distinct blocks:
1. Crash detection: handleWorkerNodeCrash if ready && !crashHandled
2. Promise flush: flushWorkerNodePromises for remaining unsettled
promises (guarded by ready && !crashHandled to skip intentional exits)
3. Cleanup: removeWorkerNode + conditional restart
Aligns with poolifier/poolifier#3211 latest changes (flushWorkerNodePromises
catch-all pattern)
* fix: add crashHandled to WorkerInfo test expectations
* [autofix.ci] apply automated fixes
* refactor: address review findings — DRY helper, fallback workerId, simplify null-path
- Extract rejectTaskPromise() helper to eliminate duplicated reject +
delete + stats + taskFinished pattern across 3 methods
- Add fallback to promiseResponse.workerId in handleTaskExecutionResponse
when message.workerId lookup fails (worker already removed)
- Simplify rejectInFlightTaskPromises null-ID path to early-return
- Keep flush guard as workerNode.info.ready (not this.destroying) since
synchronous terminate in web workers causes unhandled rejections during
pool.destroy() — destroyWorkerNode already handles graceful shutdown
* [autofix.ci] apply automated fixes
* chore: remove unrelated config files added by mistake
* docs: fix flushWorkerNodePromises JSDoc to match actual behavior
The JSDoc was copied from upstream where exitCode !== 0 allows flush
during pool destroy. In our web worker adaptation, synchronous terminate
causes unhandled rejections if flush runs during destroy, so the guard
uses workerNode.info.ready instead. Updated doc to reflect this.
* fix: resolve abort target dynamically via promiseResponseMap
The abort signal handler captured workerNodeKey at task submission time.
After steal/redistribute, the stale index dispatches abortTask to the
wrong worker node. Resolve the current worker dynamically from the
stored workerId (kept up-to-date by updatePromiseResponseWorkerId).
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>1 parent fa8b814 commit 74d9529
9 files changed
Lines changed: 332 additions & 37 deletions
File tree
- src
- pools
- tests
- pools
- thread
- worker-files/thread
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
559 | 559 | | |
560 | 560 | | |
561 | 561 | | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
562 | 565 | | |
563 | 566 | | |
564 | 567 | | |
| |||
1173 | 1176 | | |
1174 | 1177 | | |
1175 | 1178 | | |
1176 | | - | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
1177 | 1190 | | |
1178 | 1191 | | |
1179 | 1192 | | |
1180 | | - | |
| 1193 | + | |
1181 | 1194 | | |
1182 | 1195 | | |
1183 | 1196 | | |
| |||
1187 | 1200 | | |
1188 | 1201 | | |
1189 | 1202 | | |
1190 | | - | |
| 1203 | + | |
1191 | 1204 | | |
1192 | 1205 | | |
1193 | 1206 | | |
| |||
1672 | 1685 | | |
1673 | 1686 | | |
1674 | 1687 | | |
1675 | | - | |
1676 | | - | |
1677 | | - | |
1678 | | - | |
1679 | | - | |
1680 | | - | |
1681 | | - | |
1682 | | - | |
1683 | | - | |
1684 | | - | |
1685 | | - | |
1686 | | - | |
1687 | | - | |
1688 | | - | |
1689 | | - | |
1690 | | - | |
| 1688 | + | |
| 1689 | + | |
1691 | 1690 | | |
1692 | 1691 | | |
1693 | 1692 | | |
| |||
1701 | 1700 | | |
1702 | 1701 | | |
1703 | 1702 | | |
| 1703 | + | |
| 1704 | + | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
| 1712 | + | |
| 1713 | + | |
| 1714 | + | |
| 1715 | + | |
| 1716 | + | |
| 1717 | + | |
| 1718 | + | |
| 1719 | + | |
| 1720 | + | |
| 1721 | + | |
| 1722 | + | |
| 1723 | + | |
| 1724 | + | |
| 1725 | + | |
| 1726 | + | |
| 1727 | + | |
| 1728 | + | |
| 1729 | + | |
| 1730 | + | |
1704 | 1731 | | |
1705 | 1732 | | |
1706 | 1733 | | |
1707 | 1734 | | |
1708 | | - | |
| 1735 | + | |
| 1736 | + | |
| 1737 | + | |
1709 | 1738 | | |
1710 | 1739 | | |
1711 | 1740 | | |
| |||
1916 | 1945 | | |
1917 | 1946 | | |
1918 | 1947 | | |
1919 | | - | |
1920 | | - | |
1921 | | - | |
1922 | | - | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
| 1953 | + | |
| 1954 | + | |
| 1955 | + | |
| 1956 | + | |
| 1957 | + | |
| 1958 | + | |
| 1959 | + | |
| 1960 | + | |
| 1961 | + | |
| 1962 | + | |
| 1963 | + | |
| 1964 | + | |
| 1965 | + | |
| 1966 | + | |
| 1967 | + | |
| 1968 | + | |
| 1969 | + | |
| 1970 | + | |
| 1971 | + | |
| 1972 | + | |
| 1973 | + | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
| 1977 | + | |
| 1978 | + | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
| 1983 | + | |
| 1984 | + | |
| 1985 | + | |
| 1986 | + | |
| 1987 | + | |
| 1988 | + | |
| 1989 | + | |
| 1990 | + | |
| 1991 | + | |
| 1992 | + | |
| 1993 | + | |
| 1994 | + | |
| 1995 | + | |
| 1996 | + | |
| 1997 | + | |
| 1998 | + | |
| 1999 | + | |
| 2000 | + | |
| 2001 | + | |
| 2002 | + | |
| 2003 | + | |
| 2004 | + | |
| 2005 | + | |
| 2006 | + | |
| 2007 | + | |
| 2008 | + | |
| 2009 | + | |
| 2010 | + | |
| 2011 | + | |
| 2012 | + | |
| 2013 | + | |
| 2014 | + | |
| 2015 | + | |
| 2016 | + | |
| 2017 | + | |
| 2018 | + | |
| 2019 | + | |
| 2020 | + | |
| 2021 | + | |
| 2022 | + | |
| 2023 | + | |
| 2024 | + | |
| 2025 | + | |
| 2026 | + | |
| 2027 | + | |
| 2028 | + | |
| 2029 | + | |
| 2030 | + | |
| 2031 | + | |
| 2032 | + | |
| 2033 | + | |
| 2034 | + | |
| 2035 | + | |
| 2036 | + | |
| 2037 | + | |
| 2038 | + | |
| 2039 | + | |
| 2040 | + | |
| 2041 | + | |
| 2042 | + | |
| 2043 | + | |
| 2044 | + | |
| 2045 | + | |
| 2046 | + | |
| 2047 | + | |
| 2048 | + | |
| 2049 | + | |
| 2050 | + | |
| 2051 | + | |
| 2052 | + | |
| 2053 | + | |
| 2054 | + | |
| 2055 | + | |
| 2056 | + | |
| 2057 | + | |
| 2058 | + | |
| 2059 | + | |
| 2060 | + | |
| 2061 | + | |
| 2062 | + | |
| 2063 | + | |
| 2064 | + | |
| 2065 | + | |
| 2066 | + | |
| 2067 | + | |
| 2068 | + | |
| 2069 | + | |
| 2070 | + | |
| 2071 | + | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + | |
| 2078 | + | |
| 2079 | + | |
| 2080 | + | |
| 2081 | + | |
| 2082 | + | |
| 2083 | + | |
| 2084 | + | |
1923 | 2085 | | |
1924 | 2086 | | |
1925 | 2087 | | |
| |||
2019 | 2181 | | |
2020 | 2182 | | |
2021 | 2183 | | |
| 2184 | + | |
| 2185 | + | |
| 2186 | + | |
| 2187 | + | |
2022 | 2188 | | |
2023 | 2189 | | |
2024 | 2190 | | |
| |||
2038 | 2204 | | |
2039 | 2205 | | |
2040 | 2206 | | |
| 2207 | + | |
| 2208 | + | |
| 2209 | + | |
| 2210 | + | |
| 2211 | + | |
| 2212 | + | |
| 2213 | + | |
| 2214 | + | |
| 2215 | + | |
| 2216 | + | |
| 2217 | + | |
| 2218 | + | |
| 2219 | + | |
| 2220 | + | |
| 2221 | + | |
| 2222 | + | |
| 2223 | + | |
| 2224 | + | |
| 2225 | + | |
| 2226 | + | |
| 2227 | + | |
| 2228 | + | |
| 2229 | + | |
| 2230 | + | |
| 2231 | + | |
| 2232 | + | |
| 2233 | + | |
| 2234 | + | |
| 2235 | + | |
| 2236 | + | |
| 2237 | + | |
| 2238 | + | |
| 2239 | + | |
| 2240 | + | |
| 2241 | + | |
| 2242 | + | |
| 2243 | + | |
2041 | 2244 | | |
2042 | 2245 | | |
2043 | 2246 | | |
| |||
2221 | 2424 | | |
2222 | 2425 | | |
2223 | 2426 | | |
| 2427 | + | |
| 2428 | + | |
| 2429 | + | |
2224 | 2430 | | |
2225 | 2431 | | |
2226 | 2432 | | |
| |||
2230 | 2436 | | |
2231 | 2437 | | |
2232 | 2438 | | |
2233 | | - | |
| 2439 | + | |
2234 | 2440 | | |
2235 | 2441 | | |
2236 | | - | |
2237 | | - | |
| 2442 | + | |
| 2443 | + | |
| 2444 | + | |
| 2445 | + | |
| 2446 | + | |
| 2447 | + | |
| 2448 | + | |
| 2449 | + | |
| 2450 | + | |
| 2451 | + | |
2238 | 2452 | | |
2239 | 2453 | | |
2240 | 2454 | | |
| |||
2248 | 2462 | | |
2249 | 2463 | | |
2250 | 2464 | | |
2251 | | - | |
| 2465 | + | |
| 2466 | + | |
| 2467 | + | |
2252 | 2468 | | |
2253 | 2469 | | |
2254 | 2470 | | |
2255 | 2471 | | |
2256 | | - | |
| 2472 | + | |
| 2473 | + | |
| 2474 | + | |
| 2475 | + | |
| 2476 | + | |
2257 | 2477 | | |
2258 | 2478 | | |
2259 | 2479 | | |
| |||
2264 | 2484 | | |
2265 | 2485 | | |
2266 | 2486 | | |
2267 | | - | |
| 2487 | + | |
2268 | 2488 | | |
2269 | 2489 | | |
2270 | 2490 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
530 | 530 | | |
531 | 531 | | |
532 | 532 | | |
| 533 | + | |
533 | 534 | | |
534 | 535 | | |
535 | 536 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
167 | 172 | | |
168 | 173 | | |
169 | 174 | | |
| |||
0 commit comments