Summary
Introduce a session management layer—connection pooling and keep-alive heartbeats—to reduce per-operation overhead for high-frequency automation workloads.
Motivation
Each Connection context manager currently tears down and re-establishes the SSH session on exit. When running dozens or hundreds of small commands in a loop, the repeated TCP handshake + key-exchange cost dominates wall-clock time. Additionally, long-idle sessions are silently dropped by firewalls and cloud NAT gateways, causing unexpected BrokenPipe / socket closed errors.
Proposed Design
Connection Pool
Provide a ConnectionPool (and AsyncConnectionPool) that vends pre-authenticated sessions from a fixed-size pool, re-authenticating only when a slot is empty or the underlying session has died.
from hussh import ConnectionPool
pool = ConnectionPool(
host="myserver.example.com",
username="deploy",
password="...",
max_connections=10,
)
# Each call borrows a ready session from the pool
with pool.connection() as conn:
result = conn.execute("uptime")
Session Keep-Alives
Add keepalive_interval and keepalive_count_max parameters to Connection / AsyncConnection to send periodic SSH-level heartbeat packets and keep NAT mappings alive.
conn = Connection(
"myserver.example.com",
username="user",
password="...",
keepalive_interval=30, # send a heartbeat every 30 s
keepalive_count_max=3, # give up after 3 unanswered heartbeats
)
Implementation Notes
- Pooling: Maintain an internal queue of open
Session objects. On borrow, validate liveness (e.g., send a no-op channel request); on return, reset channel state and re-enqueue. Thread-safety is required for the sync pool; asyncio-safety for the async pool.
- Keep-Alives: Map to
ssh2::Session::set_keepalive (sync) and the equivalent russh API (async). A background Tokio task can drive the async heartbeat loop.
- Connection errors during borrow should transparently create a replacement session rather than surfacing to the caller.
Acceptance Criteria
Summary
Introduce a session management layer—connection pooling and keep-alive heartbeats—to reduce per-operation overhead for high-frequency automation workloads.
Motivation
Each
Connectioncontext manager currently tears down and re-establishes the SSH session on exit. When running dozens or hundreds of small commands in a loop, the repeated TCP handshake + key-exchange cost dominates wall-clock time. Additionally, long-idle sessions are silently dropped by firewalls and cloud NAT gateways, causing unexpectedBrokenPipe/socket closederrors.Proposed Design
Connection Pool
Provide a
ConnectionPool(andAsyncConnectionPool) that vends pre-authenticated sessions from a fixed-size pool, re-authenticating only when a slot is empty or the underlying session has died.Session Keep-Alives
Add
keepalive_intervalandkeepalive_count_maxparameters toConnection/AsyncConnectionto send periodic SSH-level heartbeat packets and keep NAT mappings alive.Implementation Notes
Sessionobjects. On borrow, validate liveness (e.g., send a no-op channel request); on return, reset channel state and re-enqueue. Thread-safety is required for the sync pool; asyncio-safety for the async pool.ssh2::Session::set_keepalive(sync) and the equivalentrusshAPI (async). A background Tokio task can drive the async heartbeat loop.Acceptance Criteria
ConnectionPool/AsyncConnectionPoolclasses with configurable pool sizekeepalive_interval/keepalive_count_maxparameters onConnectionandAsyncConnection