Skip to content

Lifecycle handlers run synchronously in the notification router loop (A9) #126

Description

@krukow

Generated via Copilot on behalf of @krukow

Lifecycle handlers run synchronously in the notification router loop

Found during the GA Phase 2 correctness/async review.

User-supplied lifecycle handlers (registered via on-lifecycle-event) are invoked
synchronously inside the client's notification router loop
(src/github/copilot_sdk/client.clj, the doseq over :lifecycle-handlers that calls
(handler lifecycle-event)). A slow or blocking user handler therefore stalls all
notification routing for that client until it returns.

By contrast, session-level on-event user callbacks are correctly isolated onto
async/thread with a sliding buffer (session.clj), so a blocking event handler cannot
stall the session. Lifecycle handlers should get the same isolation.

Proposed resolution

Dispatch lifecycle handler invocations off the router loop — e.g. on async/thread or a
dedicated executor. Note the ordering tension: naive per-handler threading would lose the
in-order delivery guarantee, so a serial per-client worker (single-threaded executor or a
dedicated dispatch channel/thread) is preferable to preserve ordering while keeping the
router loop responsive.

Severity: post-ga (defensive robustness; only bites callers who block inside a lifecycle
handler).

Metadata

Metadata

Assignees

No one assigned

    Labels

    post-gaDeferred to after 1.0.0 GA

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions