JS PR getlago/lago-agent-sdk-js#47 fixed two shutdown behaviors the Python port is missing:
-
Buffered events are lost on SIGTERM and SIGHUP. The queue's only exit hook is atexit.register (queue.py:136), and CPython does not run atexit handlers on SIGTERM's default action — the route every Kubernetes pod, docker stop and systemd unit takes. JS drains on natural exit, SIGINT, SIGTERM and SIGHUP; Python only on the first two. Install SIGTERM/SIGHUP handlers that drain then re-raise (JS's pattern: drain, then re-raise only if the caller has no handler of their own), taking care not to clobber user-installed handlers.
-
atexit is never unregistered. After an explicit shutdown(), the registered _atexit_shutdown keeps the dead queue — and its whole buffer — reachable for the life of the process, one entry per queue (the per-request-SDK shape), and runs a redundant second shutdown at exit. JS now removes its beforeExit/signal listeners at the end of shutdown(); Python should atexit.unregister(self._atexit_shutdown) at the same point.
Mirror JS's tests where they translate: listener/hook release after shutdown, idempotence across a second shutdown, no leak across N queues.
JS PR getlago/lago-agent-sdk-js#47 fixed two shutdown behaviors the Python port is missing:
Buffered events are lost on SIGTERM and SIGHUP. The queue's only exit hook is
atexit.register(queue.py:136), and CPython does not run atexit handlers on SIGTERM's default action — the route every Kubernetes pod,docker stopand systemd unit takes. JS drains on natural exit, SIGINT, SIGTERM and SIGHUP; Python only on the first two. Install SIGTERM/SIGHUP handlers that drain then re-raise (JS's pattern: drain, then re-raise only if the caller has no handler of their own), taking care not to clobber user-installed handlers.atexitis never unregistered. After an explicitshutdown(), the registered_atexit_shutdownkeeps the dead queue — and its whole buffer — reachable for the life of the process, one entry per queue (the per-request-SDK shape), and runs a redundant second shutdown at exit. JS now removes itsbeforeExit/signal listeners at the end ofshutdown(); Python shouldatexit.unregister(self._atexit_shutdown)at the same point.Mirror JS's tests where they translate: listener/hook release after shutdown, idempotence across a second shutdown, no leak across N queues.