ec0b7631d0
CI / lint (push) Successful in 12s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 23s
CI / typecheck (push) Successful in 36s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 46s
CI / unit_tests (push) Successful in 3m3s
CI / integration_tests (push) Successful in 3m31s
CI / docker (push) Successful in 40s
CI / coverage (push) Successful in 5m34s
CI / benchmark-publish (push) Successful in 19m15s
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 13s
CI / build (pull_request) Successful in 14s
CI / quality (pull_request) Successful in 17s
CI / security (pull_request) Successful in 34s
CI / typecheck (pull_request) Has been cancelled
CI / unit_tests (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
CI / integration_tests (pull_request) Has been cancelled
CI / docker (pull_request) Has been cancelled
Renamed src/cleveragents/acp/ to src/cleveragents/a2a/ and all 13 Acp* classes to A2a* per ADR-047 (A2A Standard Adoption). Updated all imports, structlog event names (acp.* → a2a.*), field names (acp_version → a2a_version), and test references across the entire codebase. This is a cosmetic rename only — no behavioral changes. ISSUES CLOSED: #688
120 lines
5.3 KiB
Gherkin
120 lines
5.3 KiB
Gherkin
Feature: Async Resource Cleanup and Leak Prevention
|
|
As a system operator
|
|
I want async resources to be tracked and closed reliably
|
|
So that the system does not leak connections, tasks, or subscriptions
|
|
|
|
Background:
|
|
Given I have an async resource tracker
|
|
|
|
Scenario: Registering an async resource and closing it
|
|
Given I have a mock async resource named "db-pool"
|
|
When I register the resource with the tracker
|
|
And I close all tracked resources
|
|
Then the resource "db-pool" should be closed
|
|
And the tracker should have zero open resources
|
|
|
|
Scenario: close_all awaits registered resources with timeout
|
|
Given I have 3 mock async resources with varied close times
|
|
When I close all tracked resources with a 5 second timeout
|
|
Then all 3 resources should be closed
|
|
And the tracker should have zero open resources
|
|
|
|
Scenario: Leaked resources are logged by name in finalizer
|
|
Given I have a mock async resource named "leaky-conn"
|
|
And I register the resource with the tracker
|
|
When the tracker finalizer runs without close_all
|
|
Then a warning should be logged mentioning "leaky-conn"
|
|
|
|
Scenario: Graceful cancellation awaits in-flight tasks before cleanup
|
|
Given I have an async task tracked by the bridge
|
|
When I request graceful cleanup with a 2 second timeout
|
|
Then the task should be cancelled
|
|
And the bridge should have no active tasks
|
|
|
|
Scenario: Time-bounded shutdown warns on forced termination
|
|
Given I have a mock async resource named "slow-resource" that takes 5 seconds to close
|
|
And I register the resource with the tracker
|
|
When I close all tracked resources with a 0.1 second timeout
|
|
Then a warning should be logged about forced termination
|
|
And the tracker should report the timed-out resource
|
|
|
|
Scenario: Cancelled async jobs persist cancellation reason
|
|
Given I have an async task tracked by the bridge
|
|
When I cancel the task with reason "user-requested-shutdown"
|
|
Then the cancellation reason should be "user-requested-shutdown"
|
|
|
|
Scenario: Checkpoint file handles are closed on cleanup
|
|
Given I have a state manager with a temporary checkpoint directory
|
|
When I save a checkpoint and then close the state manager
|
|
Then the checkpoint file should exist and be readable
|
|
And the state manager should be marked as closed
|
|
|
|
Scenario: Subscriptions are disposed on cleanup
|
|
Given I have an A2A event queue with 3 active subscriptions
|
|
When I close the event queue
|
|
Then all subscriptions should be removed
|
|
And the subscription count should be zero
|
|
|
|
Scenario: Tracker rejects duplicate resource names
|
|
Given I have a mock async resource named "unique-res"
|
|
And I register the resource with the tracker
|
|
When I try to register another resource named "unique-res"
|
|
Then a ValueError should be raised mentioning "unique-res"
|
|
|
|
Scenario: Tracker rejects empty resource name
|
|
When I try to register a resource with an empty name
|
|
Then a ValueError should be raised mentioning "name"
|
|
|
|
Scenario: Tracker rejects None resource
|
|
When I try to register a None resource with name "valid-name"
|
|
Then a ValueError should be raised mentioning "resource"
|
|
|
|
Scenario: Tracker context manager closes resources on exit
|
|
Given I have a mock async resource named "ctx-resource"
|
|
When I use the tracker as an async context manager and register the resource
|
|
Then the resource "ctx-resource" should be closed after exiting the context
|
|
|
|
Scenario: close_all is idempotent
|
|
Given I have a mock async resource named "once-resource"
|
|
And I register the resource with the tracker
|
|
When I close all tracked resources twice
|
|
Then the resource "once-resource" should be closed exactly once
|
|
And the tracker should have zero open resources
|
|
|
|
Scenario: Enhanced bridge cleanup awaits tasks with timeout
|
|
Given I have a bridge with 2 slow async tasks
|
|
When I run enhanced cleanup with a 2 second timeout
|
|
Then the bridge should have no active tasks
|
|
And completed tasks should be logged
|
|
|
|
Scenario: Registering a resource after close_all raises RuntimeError
|
|
Given I have a mock async resource named "late-resource"
|
|
And I register the resource with the tracker
|
|
When I close all tracked resources
|
|
And I try to register a resource named "post-close" after close_all
|
|
Then a RuntimeError should be raised mentioning "closed"
|
|
|
|
Scenario: State update after close raises RuntimeError
|
|
Given I have a state manager with a temporary checkpoint directory
|
|
When I close the state manager
|
|
And I try to update state after close
|
|
Then a RuntimeError should be raised mentioning "closed"
|
|
|
|
Scenario: State reset after close raises RuntimeError
|
|
Given I have a state manager with a temporary checkpoint directory
|
|
When I close the state manager
|
|
And I try to reset state after close
|
|
Then a RuntimeError should be raised mentioning "closed"
|
|
|
|
Scenario: Publish after close raises RuntimeError on A2aEventQueue
|
|
Given I have an A2A event queue with 1 active subscriptions
|
|
When I close the event queue
|
|
And I try to publish an event after close
|
|
Then a RuntimeError should be raised mentioning "closed"
|
|
|
|
Scenario: A2aEventQueue exposes is_closed property
|
|
Given I have an A2A event queue with 0 active subscriptions
|
|
Then the event queue is_closed should be False
|
|
When I close the event queue
|
|
Then the event queue is_closed should be True
|