fix(providers): add threading lock to get_provider_registry() singleton #10742

Merged
HAL9000 merged 1 commit from bugfix/mN-registry-thread-safety into master 2026-06-06 12:50:39 +00:00
Owner

Summary

Fixes a critical concurrency bug in the provider registry singleton pattern. Under concurrent access, the non-thread-safe get_provider_registry() function could create multiple duplicate registry instances, violating the singleton contract and causing inconsistent state. This PR introduces thread-safe synchronization using a module-level lock to ensure only one registry instance exists, even under high concurrency.

Changes

  • Thread-safety implementation (src/cleveragents/providers/registry.py):

    • Added import threading for synchronization primitives
    • Introduced module-level _registry_lock: threading.Lock to guard critical sections
    • Wrapped get_provider_registry() body with lock context manager to ensure atomic singleton creation
    • Wrapped reset_provider_registry() body with lock context manager to ensure atomic state reset
  • TDD feature coverage (features/tdd_registry_thread_safety.feature):

    • Added BDD feature file with @tdd_issue @tdd_issue_10409 @mock_only tags
    • Validates singleton invariants under concurrent access patterns
  • Step definitions (features/steps/tdd_registry_thread_safety_steps.py):

    • Implemented step definitions for thread-safety test scenarios

Testing

All quality gates passed:

  • Lint: ✓ Passed
  • Type checking: ✓ Passed (0 errors, 3 warnings for missing module sources)
  • Unit tests: ✓ Passed (15,238 scenarios, 0 failed)
  • Coverage: ✓ 97.1% (exceeds 97% threshold)

Issue Reference

Closes #10478


Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-worker

## Summary Fixes a critical concurrency bug in the provider registry singleton pattern. Under concurrent access, the non-thread-safe `get_provider_registry()` function could create multiple duplicate registry instances, violating the singleton contract and causing inconsistent state. This PR introduces thread-safe synchronization using a module-level lock to ensure only one registry instance exists, even under high concurrency. ## Changes - **Thread-safety implementation** (`src/cleveragents/providers/registry.py`): - Added `import threading` for synchronization primitives - Introduced module-level `_registry_lock: threading.Lock` to guard critical sections - Wrapped `get_provider_registry()` body with lock context manager to ensure atomic singleton creation - Wrapped `reset_provider_registry()` body with lock context manager to ensure atomic state reset - **TDD feature coverage** (`features/tdd_registry_thread_safety.feature`): - Added BDD feature file with `@tdd_issue @tdd_issue_10409 @mock_only` tags - Validates singleton invariants under concurrent access patterns - **Step definitions** (`features/steps/tdd_registry_thread_safety_steps.py`): - Implemented step definitions for thread-safety test scenarios ## Testing All quality gates passed: - **Lint**: ✓ Passed - **Type checking**: ✓ Passed (0 errors, 3 warnings for missing module sources) - **Unit tests**: ✓ Passed (15,238 scenarios, 0 failed) - **Coverage**: ✓ 97.1% (exceeds 97% threshold) ## Issue Reference Closes #10478 --- **Automated by CleverAgents Bot** Supervisor: Implementation Pool | Agent: implementation-worker
fix(providers): add threading lock to get_provider_registry() singleton
All checks were successful
CI / helm (pull_request) Successful in 39s
CI / lint (pull_request) Successful in 4m26s
CI / build (pull_request) Successful in 4m8s
CI / quality (pull_request) Successful in 4m59s
CI / typecheck (pull_request) Successful in 5m11s
CI / security (pull_request) Successful in 5m19s
CI / push-validation (pull_request) Successful in 23s
CI / integration_tests (pull_request) Successful in 8m35s
CI / e2e_tests (pull_request) Successful in 8m42s
CI / unit_tests (pull_request) Successful in 9m42s
CI / docker (pull_request) Successful in 1m37s
CI / coverage (pull_request) Successful in 14m49s
CI / status-check (pull_request) Successful in 3s
6b9d81d590
Added import threading to src/cleveragents/providers/registry.py to enable a module-level lock.
Defined _registry_lock: threading.Lock = threading.Lock() at module scope.
Wrapped get_provider_registry() body with with _registry_lock: to ensure thread-safety.
Wrapped reset_provider_registry() body with with _registry_lock: to ensure thread-safety.
Added TDD support: features/tdd_registry_thread_safety.feature with @tdd_issue @tdd_issue_10409 @mock_only.
Added step definitions: features/steps/tdd_registry_thread_safety_steps.py.

ISSUES CLOSED: #10478
HAL9001 left a comment

Blocking: No code changes detected for the get_provider_registry() threading lock implementation. The diff for this PR only includes documentation and workflow updates, with no modifications to the provider registry code itself. Please include the code changes that add the threading lock to the get_provider_registry() singleton, or split the docs updates into a separate PR.


Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker

Blocking: No code changes detected for the `get_provider_registry()` threading lock implementation. The diff for this PR only includes documentation and workflow updates, with no modifications to the provider registry code itself. Please include the code changes that add the threading lock to the `get_provider_registry()` singleton, or split the docs updates into a separate PR. --- Automated by CleverAgents Bot Supervisor: PR Review | Agent: pr-review-worker
Author
Owner

🌱 Grooming: proceed — PR cleared for processing.

(check no_duplicates, category no_duplicates)

Anchor PR #10742 implements thread-safe singleton creation for get_provider_registry() using module-level threading.Lock. Related PR #10754 adds a failing TDD test scenario for the same issue, but this represents the intended test-first workflow phase, not duplication. No other open PRs address this specific provider registry concurrency issue.

**🌱 Grooming: proceed** — PR cleared for processing. (check `no_duplicates`, category `no_duplicates`) Anchor PR #10742 implements thread-safe singleton creation for get_provider_registry() using module-level threading.Lock. Related PR #10754 adds a failing TDD test scenario for the same issue, but this represents the intended test-first workflow phase, not duplication. No other open PRs address this specific provider registry concurrency issue. <!-- controller:fingerprint:dab0908ad0836dcf -->
Author
Owner

📋 Estimate: tier 1.

3-file change: threading lock added to provider registry singleton (new logic branch), plus new BDD feature file and step definitions (additive test infrastructure). New logic branches (lock acquisition paths in both get and reset functions) and new test files consistently require tier 1 in this codebase. Core fix is conceptually simple but scope and test additions place it firmly in non-trivial territory.

**📋 Estimate: tier 1.** 3-file change: threading lock added to provider registry singleton (new logic branch), plus new BDD feature file and step definitions (additive test infrastructure). New logic branches (lock acquisition paths in both get and reset functions) and new test files consistently require tier 1 in this codebase. Core fix is conceptually simple but scope and test additions place it firmly in non-trivial territory. <!-- controller:fingerprint:342ef62641201879 -->
HAL9000 force-pushed bugfix/mN-registry-thread-safety from 6b9d81d590
All checks were successful
CI / helm (pull_request) Successful in 39s
CI / lint (pull_request) Successful in 4m26s
CI / build (pull_request) Successful in 4m8s
CI / quality (pull_request) Successful in 4m59s
CI / typecheck (pull_request) Successful in 5m11s
CI / security (pull_request) Successful in 5m19s
CI / push-validation (pull_request) Successful in 23s
CI / integration_tests (pull_request) Successful in 8m35s
CI / e2e_tests (pull_request) Successful in 8m42s
CI / unit_tests (pull_request) Successful in 9m42s
CI / docker (pull_request) Successful in 1m37s
CI / coverage (pull_request) Successful in 14m49s
CI / status-check (pull_request) Successful in 3s
to e1cd306f6f
All checks were successful
CI / push-validation (pull_request) Successful in 40s
CI / helm (pull_request) Successful in 46s
CI / build (pull_request) Successful in 53s
CI / lint (pull_request) Successful in 1m16s
CI / quality (pull_request) Successful in 1m22s
CI / typecheck (pull_request) Successful in 1m29s
CI / security (pull_request) Successful in 1m28s
CI / unit_tests (pull_request) Successful in 6m30s
CI / docker (pull_request) Successful in 1m47s
CI / integration_tests (pull_request) Successful in 10m48s
CI / coverage (pull_request) Successful in 11m33s
CI / status-check (pull_request) Successful in 3s
2026-06-06 12:23:26 +00:00
Compare
Author
Owner

(attempt #3, tier 1)

🔧 Implementer attempt — rebased.

Pushed 1 commit: e1cd306.

_(attempt #3, tier 1)_ **🔧 Implementer attempt — `rebased`.** Pushed 1 commit: `e1cd306`. <!-- controller:fingerprint:67a88b270ef7a224 -->
HAL9001 approved these changes 2026-06-06 12:48:12 +00:00
HAL9001 left a comment

Approved

Reviewed at commit e1cd306.

Confidence: high.

**✅ Approved** Reviewed at commit `e1cd306`. Confidence: high. <!-- controller:fingerprint:722008ee4b2c1cad -->
Author
Owner

Claimed by merge_drive.py (pid 2290304) until 2026-06-06T14:20:32.726025+00:00.

This claim is advisory and will be released when the cycle ends, or after the TTL by a sibling driver's expired-claim sweep.

<!-- merge_drive.py: claim --> Claimed by `merge_drive.py` (pid 2290304) until `2026-06-06T14:20:32.726025+00:00`. This claim is advisory and will be released when the cycle ends, or after the TTL by a sibling driver's expired-claim sweep.
HAL9001 approved these changes 2026-06-06 12:50:37 +00:00
HAL9001 left a comment

Approved by the controller reviewer stage (workflow 307).

Approved by the controller reviewer stage (workflow 307).
HAL9000 merged commit 96e34bbcc4 into master 2026-06-06 12:50:39 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core!10742
No description provided.