fix(events): add unsubscribe() to EventBus protocol and implementations #10887

Open
HAL9000 wants to merge 5 commits from bugfix/m3-eventbus-unsubscribe into master

5 Commits

Author SHA1 Message Date
CleverAgents Bot 11de2bddb2 ci: stop master workflow on PR updates
CI / lint (pull_request) Has been cancelled
CI / typecheck (pull_request) Has been cancelled
CI / security (pull_request) Has been cancelled
CI / quality (pull_request) Has been cancelled
CI / unit_tests (pull_request) Has been cancelled
CI / integration_tests (pull_request) Has been cancelled
CI / e2e_tests (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / docker (pull_request) Has been cancelled
CI / helm (pull_request) Has been cancelled
CI / push-validation (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
Remove the stale pull_request trigger from master.yml so PR branch commits do not launch the master workflow.

Maintenance patch for PR #10887.
2026-06-10 20:22:22 -04:00
HAL9000 20a49d92fd fix(actor): catch typer.Exit alongside click.exceptions.Exit in run handlers
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 37s
CI / build (pull_request) Successful in 48s
CI / helm (pull_request) Successful in 50s
CI / lint (pull_request) Successful in 58s
CI / quality (pull_request) Successful in 57s
CI / typecheck (pull_request) Successful in 1m0s
CI / security (pull_request) Successful in 1m12s
CI / e2e_tests (pull_request) Successful in 5m40s
CI / integration_tests (pull_request) Successful in 10m53s
CI / unit_tests (pull_request) Failing after 14m39s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Successful in 23m53s
CI / status-check (pull_request) Failing after 5s
In typer>=0.9.0 typer.Exit is a plain Exception subclass that does not
inherit from click.exceptions.Exit. The run commands in actor.py and
actor_run.py only re-raised click.exceptions.Exit, so a typer.Exit
raised by _resolve_config_files fell through to the generic Exception
handler (exit code 3 instead of 2). The BDD step files also used
click.exceptions.Exit in their except clauses, causing the affected
resolve_config_files scenarios to error out instead of capturing the
expected exit code. Remove unused import click from the two step files.

Refs: #10356
2026-06-07 01:44:20 -04:00
HAL9000 7faab43918 fix(events): add unsubscribe() to mock EventBus test doubles
CI / push-validation (pull_request) Successful in 22s
CI / helm (pull_request) Successful in 32s
CI / build (pull_request) Successful in 36s
CI / lint (pull_request) Successful in 47s
CI / quality (pull_request) Successful in 51s
CI / security (pull_request) Successful in 1m17s
CI / typecheck (pull_request) Successful in 1m25s
CI / benchmark-publish (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 3m32s
CI / integration_tests (pull_request) Failing after 4m15s
CI / unit_tests (pull_request) Failing after 8m18s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Successful in 15m39s
CI / status-check (pull_request) Failing after 2s
The EventBus protocol is @runtime_checkable and gained unsubscribe()
in this PR. Python's isinstance() check requires all protocol methods
to be present, so _MockEventBus and _FailingEventBus in the step files
failed the isinstance(event_bus, EventBus) guard in
FixThenRevalidateOrchestrator.__init__, raising ValidationError before
any scenario step ran — causing 5 errored scenarios.

Added no-op unsubscribe() to:
- _MockEventBus in fix_then_revalidate_coverage_boost_steps.py
- _FailingEventBus in fix_then_revalidate_coverage_boost_steps.py
- _FailingEventBus in fix_then_revalidate_coverage_r3_steps.py

Refs: #10356
2026-06-06 23:43:34 -04:00
HAL9000 73832cd6bb fix(events): remove type: ignore[misc] from protocol unsubscribe stub and fix formatting
CI / helm (pull_request) Successful in 58s
CI / lint (pull_request) Successful in 1m22s
CI / build (pull_request) Successful in 1m14s
CI / quality (pull_request) Successful in 1m47s
CI / typecheck (pull_request) Successful in 1m59s
CI / security (pull_request) Successful in 2m2s
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 20s
CI / integration_tests (pull_request) Successful in 4m1s
CI / e2e_tests (pull_request) Successful in 4m57s
CI / unit_tests (pull_request) Failing after 5m37s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Successful in 14m46s
CI / status-check (pull_request) Failing after 3s
2026-05-05 20:14:11 +00:00
HAL9000 1e9620223f fix(events): add unsubscribe() to EventBus protocol and implementations
CI / lint (pull_request) Failing after 46s
CI / helm (pull_request) Successful in 29s
CI / push-validation (pull_request) Successful in 31s
CI / build (pull_request) Successful in 48s
CI / typecheck (pull_request) Successful in 1m16s
CI / quality (pull_request) Successful in 1m22s
CI / security (pull_request) Successful in 1m29s
CI / coverage (pull_request) Has been skipped
CI / benchmark-publish (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 4m3s
CI / integration_tests (pull_request) Successful in 4m25s
CI / unit_tests (pull_request) Failing after 4m38s
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 5s
Add unsubscribe() method to EventBus protocol and both implementations
(ReactiveEventBus, LoggingEventBus) to prevent handler reference memory
leaks in long-running processes.

Previously, once a handler was registered via subscribe() it could never
be removed. Bound-method handlers hold strong references to their owning
objects, preventing garbage collection even after the owning component
is shut down.

The new unsubscribe() method removes the handler from _subscriptions
using contextlib.suppress(ValueError) for a clean no-op when the handler
was never registered. This releases the strong reference, allowing the
owning object to be garbage collected.

TDD regression scenarios tagged @tdd_issue @tdd_issue_10354 verify:
- Unsubscribed handlers are not called on subsequent emit() calls
- Unsubscribing a non-registered handler is a no-op (no exception)
- Owning objects are garbage collected after unsubscription

ISSUES CLOSED: #10356
2026-04-28 07:24:30 +00:00