Skip to content

Python dispose() is sync while Node dispose() is async — parity gap #21

@AndresL230

Description

@AndresL230

Python dispose() is sync; Node dispose() is async — shutdown semantics differ

Severity: Medium
Affected repos: middleware-python, middleware-node
Component boundary: middleware lifecycle parity

Symptom

  • Node: await handle.dispose() waits for the final flush to complete (bounded by shutdownFlushTimeoutMs).
  • Python: handle.dispose() returns synchronously after spawning a background flush thread, joining it with a 2-second timeout. The final flush may or may not complete.

A user porting a shutdown path from one SDK to the other will get inconsistent behavior. In Python, fast process exit (os._exit() or short-lived scripts) may drop the last window of data.

Evidence

  • middleware-node/src/init.tsdispose() is async, awaits flush.
  • middleware-python/recost/_init.pydispose() is sync, spawns a thread with a short join timeout.

Impact

  • Cross-language users see surprising differences.
  • Pythonists doing graceful shutdown via atexit or signal handler may lose the trailing telemetry window if the runtime tears down before the thread joins.

Fix recommendation

Two options:

  1. Document the difference clearly in both READMEs and CLAUDE.md. Python users should call dispose() and then time.sleep(3) before os._exit() if they want flush guarantees. Cheap.

  2. Add a sync flush call that blocks the calling thread: handle.flush_blocking(timeout_s=3). Then dispose() continues to be best-effort but a deliberate user has an explicit handle.

Recommended: do both. Option 2 is the practical fix; option 1 is the rest of the safety net.

Verification

  • Python test: run a script that emits an event, calls dispose(), exits. Assert (via a mock cloud server) that the event arrived.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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