Skip to content

fix(context): stop() releases the singletons it destroyed (release 26.09.03) - #163

Merged
ancongui merged 1 commit into
mainfrom
fix/stop-clears-singletons
Sep 10, 2026
Merged

fix(context): stop() releases the singletons it destroyed (release 26.09.03)#163
ancongui merged 1 commit into
mainfrom
fix/stop-clears-singletons

Conversation

@ancongui

Copy link
Copy Markdown
Contributor

The companion to #162. stop() called @pre_destroy on every resolved bean and then left each
instance on its registration
, so the container went on holding objects whose pools were closed, whose
consumers were stopped and whose files were flushed.

Two consequences, both silent:

  • get_bean() after a stop returns a destroyed singleton rather than failing or rebuilding.
  • A later start() creates a fresh set beside the stale one, so anything walking the registrations
    — health reporting, metrics, a bean inventory — sees every singleton twice, one live and one dead.

stop() now clears the instance from every registration it destroyed, which is what makes it the
inverse of start() rather than half of it.

It releases only what the container built

Anything handed to the container as a ready-made object — its own self-registration, the context's,
anything an embedder registered as an instance — has no factory to rebuild it, so discarding it
would break the next start(). start() now records which instances predate its bean pipeline, and
stop() leaves exactly those alone. That distinction is what the first attempt at this fix got wrong:
clearing everything made a restart fail with NameError: name 'Container' is not defined.

Found with the same service that surfaced the double-start in #162: a start/stop/start cycle across
two test modules left two EventPublisher instances in one container, one of them dead.

Verification

Gate Result
pytest tests/ (CI's ignore set) 5001 passed, 7 skipped, 0 failed
mypy src/pyfly --strict no issues in 694 source files
ruff check / ruff format --check passed / 1274 files formatted

stop() called @pre_destroy on every resolved bean and then left each instance on
its registration, so the container went on holding objects whose pools were closed,
whose consumers were stopped and whose files were flushed.

Two consequences, both silent: get_bean() after a stop returned a DESTROYED
singleton rather than failing or rebuilding, and a later start() created a fresh
set beside the stale one, so anything walking the registrations — health
reporting, metrics, a bean inventory — saw every singleton twice, one live and one
dead.

stop() now clears the instance from every registration it destroyed, which is what
makes it the inverse of start() rather than half of it. It releases only what the
container BUILT: anything handed to it as a ready-made object — the container's own
self-registration, the context's, anything an embedder registered as an instance —
has no factory to rebuild it, so it is left alone and the next start() still works.
start() records that distinction as it begins.

Found with the same service that surfaced the double-start in 26.09.02: a
start/stop/start cycle across two test modules left two EventPublisher instances in
one container, one of them dead.

Release 26.09.03.
@ancongui
ancongui merged commit 35c295e into main Sep 10, 2026
6 checks passed
@ancongui
ancongui deleted the fix/stop-clears-singletons branch September 10, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant