Skip to main content
ACP connections have a well-defined lifecycle from establishment to closure. Understanding this lifecycle is essential for proper resource management and error handling.

Connection Phases

An ACP connection goes through these phases:
  1. Creation - Connection object is instantiated with a stream
  2. Active - Messages can be sent and received
  3. Closing - Stream is ending (readable stream closed)
  4. Closed - Connection is terminated, no more messages possible

Creating a Connection

Connections are created by passing a stream and handler function:
The handler function (toAgent or toClient) receives the connection object and should return the Agent or Client implementation.

Monitoring Connection State

The SDK provides two mechanisms for monitoring connection state:

Using signal (AbortSignal)

The signal property provides an AbortSignal that aborts when the connection closes:
AbortSignal advantages:
  • Synchronous status check with .aborted
  • Can be passed to other APIs (fetch, setTimeout)
  • Standard Web API for cancellation

Using closed (Promise)

The closed property provides a Promise that resolves when the connection closes:
Promise advantages:
  • Natural async/await syntax
  • Can be combined with Promise.race() for timeouts

Connection Closure

Connections close when the underlying readable stream ends. This can happen:
  1. Normally - The other side closes their output stream
  2. Due to error - A stream error or write failure occurs
  3. Process termination - The subprocess exits

Detecting Closure

Both sides should monitor for connection closure:

Resource Management

Proper resource management is critical for long-running connections.

Cleaning Up on Close

Always clean up resources when the connection closes:

Using Signals for Cancellation

Pass the connection’s signal to operations that should be cancelled on disconnect:

Graceful Shutdown

For clean shutdown, ensure all pending operations complete:

Handling Stream Errors

Stream errors trigger connection closure:

Example: Complete Lifecycle Management

Here’s a complete example showing proper lifecycle management:

Best Practices

Do:
  • Monitor connection.closed or connection.signal for disconnection
  • Clean up resources (timers, file handles) when connection closes
  • Pass connection.signal to operations that should be cancelled
  • Handle both normal and error-based closure
  • Wait for pending operations during shutdown
Don’t:
  • Attempt to send messages after connection closes
  • Leak resources by not cleaning up on close
  • Ignore connection closure errors
  • Block shutdown waiting indefinitely for operations