pub struct CommandExecutor { /* private fields */ }Expand description
Command executor for running commands in shell sessions.
Implementations§
Source§impl CommandExecutor
impl CommandExecutor
Sourcepub fn new(store: Arc<SessionStore>) -> Self
pub fn new(store: Arc<SessionStore>) -> Self
Create a new command executor.
Sourcepub fn execute_sync(&self, command: &Command) -> Result<ExecutionResult>
pub fn execute_sync(&self, command: &Command) -> Result<ExecutionResult>
Execute a command synchronously (blocking).
This runs the command and waits for completion or timeout. Prefer
CommandExecutor::execute from async contexts — this blocking variant
must never be called directly on a tokio worker thread.
Sourcepub async fn execute(&self, command: &Command) -> Result<ExecutionResult>
pub async fn execute(&self, command: &Command) -> Result<ExecutionResult>
Execute a command, keeping the async runtime responsive.
The blocking work runs on a dedicated blocking thread via
spawn_blocking, so the tokio worker pool (and therefore /health and
the accept loop) is never starved by a slow or hung command. The
underlying [run_command] enforces its own timeout, so this always
completes without leaking runtime capacity.
Sourcepub async fn execute_async(
&self,
command: &Command,
) -> Result<(Receiver<OutputChunk>, JoinHandle<Result<ExecutionResult>>)>
pub async fn execute_async( &self, command: &Command, ) -> Result<(Receiver<OutputChunk>, JoinHandle<Result<ExecutionResult>>)>
Execute a command asynchronously, streaming output chunks as they arrive.
Returns a receiver that yields OutputChunks live, plus a join handle
resolving to the final ExecutionResult. Backed by the same piped
[run_command_streaming] core as the non-streaming paths, so it inherits
real completion detection, enforceable timeout, and process-tree kill —
none of which the previous PTY implementation could provide for
non-interactive commands (see [run_command_streaming]).
A consumer that stops receiving should drop the receiver. Holding it while awaiting the join handle is a deadlock in waiting: the channel is bounded, and the producer runs inside the control loop that enforces the timeout, so a full channel stops that loop from checking anything. Both WebSocket handlers used to do exactly this when their client hung up, and the command then outlived its own timeout — verified by watching a child with a five-second timeout run to completion.
Dropping the receiver frees the producer immediately. As a backstop for the consumer that forgets, forwarding gives up once the command’s own deadline has passed — timeout enforcement is a guarantee of this crate, not something each consumer re-earns.
Sourcepub async fn execute_in_session(
&self,
session_id: &SessionId,
command: &Command,
) -> Result<ExecutionResult>
pub async fn execute_in_session( &self, session_id: &SessionId, command: &Command, ) -> Result<ExecutionResult>
Execute a command in an existing session.