module

Krikri::PluginDaemon

Perf items 1-3 (formerly SUGGESTED_PERFORMANCE_IMPROVEMENTS.md item #15, a doc since deleted) - the persistent remote executor. Today's per-task remote path forks a local ssh client, a remote bash -s, and execs a fresh plugin process for EVERY task (PluginManager.execute_remote_plugin) - real work already banked (ControlMaster reuse, task batching, the fat plugin binary) hasn't removed that per-task fork/exec cost. This module is the remote HALF of the fix: started via <fat-plugin> --daemon (see build.sh's generated dispatcher), it stays resident over ONE long-lived SSH session and serves every subsequent eligible task for that host as a plain read+write on an already-open pipe - no new process on either end. The controller half lives in ssh_manager.cr's daemon_send.

Deliberately opt-in and narrowly scoped - see this class's own design notes (perf items 1-5) for what remains out of scope (batching, remote async:, vars-context residency; become: is no longer - see item 1). Nothing here changes default behavior: this module is only ever invoked by --daemon, which nothing reaches unless --persistent-daemon was passed on the controller.

Class methods

serve

Serves requests off STDIN/STDOUT until STDIN closes (the controller closing its write end of the pipe - see SSHManager.close_all_daemons - is the clean-shutdown signal, mirroring the one-shot path's own STDIN.gets_to_end-until-EOF termination; no explicit "goodbye" message needed). Each request is {"module": "<simple plugin name>", "config": <original task config, same shape #execute_remote_plugin already builds>}; the response is the dispatch block's raw return value (the same JSON String BasePlugin#run_and_capture already produces) written back framed, unchanged - callers on the controller side get exactly the plugin's own JSON result, nothing wrapped around it.

One request in flight at a time, by construction: a single SSH session/pipe pair serves exactly one host's tasks, and this codebase's own --forks model runs a given host's own tasks sequentially on one fiber (verified directly - executor.cr's run_task_for_hosts_in_parallel spawns one fiber PER HOST, not per task) - so there is never a second request racing this one on the same daemon connection, no correlation ID needed.

Source