Admission runner survey
Decision context
Issue #1131 asks for a local runner that holds heavy steps until the workstation has at least
12 GiB MemAvailable, 15 GiB SwapFree and a load that fits, runs each in its own memory-limited
scope, returns to the caller at once and reports when the step is admitted. This survey compares
the existing local queue tools against those needs before any code was written. It was run on
2026-10-17; versions and dates are review pins checked on that day, not evergreen
recommendations.
Outcome: no candidate both waits for memory and swap headroom and contains the step. The engine
adopts systemd-run for containment, reads the host through its existing sentinel
(internal/sentinel), and adds only the waiting loop (internal/admission). Usage is in the
admission guide.
Comparison
| Candidate | Admission Gating | Resource Limits | Notifications | Concurrency & Persistence | Platforms | Licence & Release (Latest Commit) | Arch Linux Package |
|---|---|---|---|---|---|---|---|
| Pueue | Slot count per group (parallel); no RAM/swap/load gating |
None (external shell execution) | Finish callback only (callback); no start hook; status via JSON CLI |
Multi-producer socket; persistent state across reboot; groups & integer priorities | Linux, macOS, Windows | MIT OR Apache-2.0; v4.0.4 (2026-03-02; commit 2026-09-09) |
extra/pueue |
| nq | Single-slot FIFO (flock on file); no condition gating |
None | No hooks; poll/wait via nq -w/-t; exit dirs NQDONEDIR/NQFAILDIR |
Multi-producer directory locks; volatile in-memory queues (lost on reboot); directory groups, no priorities | Linux, macOS, BSD (POSIX); no Windows | CC0-1.0; v1.0 (2024-07-03; commit 2025-10-26) |
aur/nq |
| Task Spooler | Slot count (-S slots, -N per job); no RAM/swap/load gating |
None | Finish hook (TS_ONFINISH), mail; no start hook; exit status via ts -s/-c |
Multi-producer socket; volatile queues (best-effort dump on SIGTERM via TS_SAVELIST); socket groups, urgent flag (-u) |
Linux, macOS, BSD (POSIX); no Windows | GPL-2.0-or-later; v1.0.4 (2025-06-30; tarball release 2025-06-30) |
aur/task-spooler |
| systemd-run | None (immediate execution; condition checks skip rather than queue) | Native cgroup v2 (--slice, MemoryHigh, MemoryMax, CPUWeight) |
D-Bus signals (JobNew, JobRemoved); unit hooks (ExecStartPost, ExecStopPost); status via ExecMainStatus |
Multi-producer via user D-Bus; non-persistent transient units; slice hierarchy, weight priorities | Linux only (cgroup v2) | LGPL-2.1-or-later; v262.1 (2026-10-16; commit 2026-10-17) |
core/systemd |
| GNU parallel | Condition-based: --memfree, --load, --noswap; no SwapFree byte floor |
None | Per-job log on finish (--joblog); no async admission/start hooks |
Single-producer batch stream CLI; no reboot persistence (resume via --joblog); no groups/priorities |
Linux, macOS, BSD, Windows (WSL/MSYS2) | GPL-3.0-or-later; 20260922 (2026-09-22; commit 2026-10-14) |
extra/parallel |
Pueue
Pueue schedules tasks strictly by group slot limits (pueue parallel <N>) or dependencies (--after), explicitly delegating load balancing elsewhere (Get-started: Load Balancing). It enforces zero cgroup or process resource containment. Notification is restricted to a post-execution finish hook (Configuration: callback) without any start or admission trigger, though exit status and logs are queryable via JSON CLI. It supports concurrent producers over a Unix domain socket, persists queued tasks across daemon reboots via JSON state, isolates concurrency via named groups (Groups), and respects integer priorities (spawn.rs#L93-L103). Pueue is dual-licensed under MIT OR Apache-2.0, released tag v4.0.4 on 2026-03-02 (last commit 2026-09-09), supports Linux, macOS, and Windows (README), and packages as extra/pueue on Arch Linux. Fit: Fails the requirement because it cannot gate on memory/swap/load metrics, lacks cgroup isolation, and cannot fire admission notifications.
nq
nq implements file-level mutual exclusion using flock(2) on output files in an enqueue directory (nq.1: Internals), providing strictly one job slot per queue directory without any memory, swap, or load admission logic. It provides no cgroup isolation or resource control. It lacks hooks or callbacks on job start or finish, requiring consumers to poll or block via nq -w / nq -t or rely on directory-sorting completed jobs with NQDONEDIR and NQFAILDIR (nq.1: Environment). Queues do not persist across reboots because waiting jobs exist only as sleeping processes holding locks (nq.1: Caveats); producers can submit concurrently to the same directory, groups correspond to discrete NQDIR paths, and priorities are unconfigurable FIFO. nq is dedicated to the public domain under CC0-1.0, tagged v1.0 on 2024-07-03 (last commit 2025-10-26), runs on POSIX platforms (Linux, macOS, BSD; Windows unverified/unsupported), and is available in aur/nq. Fit: Fails the requirement due to single-slot FIFO locking, zero dynamic resource awareness, lack of cgroup containment, and absence of admission hooks.
Task Spooler (ts / tsp)
Task Spooler admits jobs strictly by fixed queue slots (-S <num>) or per-command required slots (-N <num>) (ts.1: Multi-Slot), offering no conditions for RAM, swap, or load average. It has no integration with cgroups or resource limiting. It supports exit notifications via the TS_ONFINISH executable callback and mail dispatch (-m) (ts.1: Environment), with exit status inspectable via ts -s / ts -c, but provides no admission or execution start hook. It handles concurrent producers over a Unix domain socket (TS_SOCKET), isolates queues via separate socket paths, supports urgent priority promotion (-u), but queue state across reboots is non-persistent unless explicitly flushed on clean SIGTERM via TS_SAVELIST. Task Spooler is licensed under GPL-2.0-or-later, released v1.0.4 on 2025-06-30 (last release activity 2025-06-30; public git unverified), targets POSIX systems (Linux, macOS, BSD; Windows unsupported), and installs via aur/task-spooler. Fit: Fails the requirement because it cannot gate on dynamic host memory/swap thresholds, cannot enforce cgroups, and lacks admission notifications.
systemd user slices + systemd-run
systemd-run launches transient .scope or .service units immediately against systemd; it contains no queuing mechanism or deferred admission logic (unit ConditionMemory= skips execution instead of queueing, systemd.unit). However, it provides native first-class cgroup v2 containment via --slice= and properties like MemoryHigh=, MemoryMax=, and CPUWeight= (systemd.resource-control). Lifecycle notification is rich via D-Bus signals (JobNew, JobRemoved), transient service unit hooks (ExecStartPost=, ExecStopPost=), and synchronous return or property queries (ExecMainStatus). Multiple producers submit concurrently via unprivileged user D-Bus; transient units do not survive reboots, and slices define hierarchical resource partitions rather than job queues. systemd is licensed under LGPL-2.1-or-later, released v262.1 on 2026-10-16 (last commit 2026-10-17), runs exclusively on Linux, and is packaged in core/systemd. Fit: Fails as a standalone queue because it executes immediately without admission holding, but functions as the optimal cgroup execution backend when paired with an external queue.
GNU parallel
GNU parallel is a batch tool that natively evaluates resource conditions before admitting jobs: --memfree <size> delays jobs until free memory exceeds a threshold (killing the youngest job if free memory falls below 50%), --load <max-load> pauses submission on high system load, and --noswap stops starts during active swap thrashing (parallel man: --memfree), though it cannot enforce a static SwapFree byte floor. It does not provide cgroup containment or process resource limits. Completion status is recorded in --joblog, but it offers no asynchronous webhook or start callback upon admission. It operates as a single-producer batch stream CLI rather than a multi-agent daemon, maintains volatile in-memory queues without reboot persistence (resuming only via static input with --joblog), and lacks queue groups or priority reordering. GNU parallel is licensed under GPL-3.0-or-later, released tag 20260922 on 2026-09-22 (commit 2026-10-14), supports Linux, macOS, BSD, and Windows (via WSL/MSYS2), and packages as extra/parallel in Arch Linux. Fit: Fails the requirement due to batch-only execution without daemon concurrency, lack of cgroup integration, and inability to return immediately while notifying callers upon admission.