Krikri::AsyncJobs
AsyncJobs - shared job-status-file conventions for async:/poll:/ async_status:. A background job (spawned as a separate, detached OS process by TaskExecutor#execute_async, not a Fiber - so it keeps running even if it outlives the poll loop or the whole playbook run) writes its result here; async_status: (plugins/async_status.cr) reads it back. Mirrors Ansible's own ~/.ansible_async/<jid> convention, though only for local connections - see execute_async's own comment for why remote async isn't implemented.
Constants
Jids are joined into file paths under the async dir, so anything that isn't a bare, simple job-id-shaped token (generate_jid's and Ansible's own "j<digits>.<digits>" shape - Ansible builds it as j<random> in the action plugin and appends ".<pid>" in async_wrapper - printed verbatim in its ASYNC POLL/OK lines and stored as the registered ansible_job_id, so we match it for output parity; or a lookup probe like "no-such-job-...") is rejected before it can carry "/" or ".." into the join - a traversal jid would otherwise let an async_status task read (status mode) or delete (mode: cleanup) an arbitrary controller-local file.
Class methods
Deletes one job's status + config files (Ansible's own async_status mode=cleanup for a single jid). Returns true when anything was removed.
Removes every job file in the async dir - Ansible's async_status mode=cleanup with jid: ALL. ~/.ansible_async previously grew without bound for the lifetime of the account. Stray .tmp leftovers from a crashed write are swept too. Returns the number of files removed.
The controller-local async dir, resolved at call time (not require
time) so tests and concurrent processes can redirect it: env
ANSIBLE_ASYNC_DIR when set (the shell plugin's async_dir option;
Ansible's own env name and default ~/.ansible_async, confirmed
via ansible-doc -t shell sh), else the HOME default. A leading ~
in the configured value is expanded against HOME.
Ansible's async jid is "j<random digits>.<pid>" (action plugin makes j<random>, async_wrapper appends the pid), and that exact string shows up in the ASYNC POLL/OK output lines and as the registered ansible_job_id - so generate_jid follows the same shape for byte-level output parity. Random::Secure keeps it unpredictable like Ansible's secrets.randbelow.
Config counterpart to write_status: the full module params the background process will execute. Unlike the status file there's no concurrent reader, so no tmp+rename - but the same 0600-at-creation rule applies, and more so: this payload IS the params, secrets included. chmod BEFORE writing so the file never exists with the payload at umask-default perms.