fix: report max recovery exhaustion events#1645
Conversation
📝 WalkthroughWalkthroughThe PR extends the consensus health system to surface detailed "max recovery exhausted" transaction information. A new configurable event limit controls a refactored SQL query that returns both exhaustion counts and limited, recent exhausted transaction records. This detail flows through cached health responses and enriches system health metrics with structured event objects containing transaction hash, contract address, recovery count, and exhausted timestamp. ChangesMax Recovery Exhaustion Detail Surface
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
0434dbd to
28d80ac
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
backend/services/usage_metrics_service.py (1)
106-119: ⚡ Quick winPlease pin this new payload mapping with a unit test.
This block is a cross-layer contract. A focused test around
instanceHealthEventswould catch future field drift betweenbackend/protocol_rpc/health.pyand this service before Pulse silently starts receiving partial events.As per coding guidelines,
tests/**/*.py: Use pytest with fixtures from tests/common/ for backend testing.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/services/usage_metrics_service.py` around lines 106 - 119, Add a focused pytest that pins the instanceHealthEvents payload mapping: create a test that injects a sample health_cache.services["consensus"]["max_recovery_exhausted_transactions"] entry and asserts that usage_metrics_service builds system_health["instanceHealthEvents"] with exactly the fields "type" (value "max_recovery_cycles_exhausted"), "transactionHash" from event["hash"], "contractAddress" from event["contract_address"], "recoveryCount" from event["recovery_count"], and "occurredAt" from event["exhausted_at"]; use the backend test fixtures from tests/common/ and mirror the canonical source in protocol_rpc.health to prevent field drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@backend/services/usage_metrics_service.py`:
- Around line 106-119: Add a focused pytest that pins the instanceHealthEvents
payload mapping: create a test that injects a sample
health_cache.services["consensus"]["max_recovery_exhausted_transactions"] entry
and asserts that usage_metrics_service builds
system_health["instanceHealthEvents"] with exactly the fields "type" (value
"max_recovery_cycles_exhausted"), "transactionHash" from event["hash"],
"contractAddress" from event["contract_address"], "recoveryCount" from
event["recovery_count"], and "occurredAt" from event["exhausted_at"]; use the
backend test fixtures from tests/common/ and mirror the canonical source in
protocol_rpc.health to prevent field drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 38de70ce-0005-4eb5-9227-6f86ff6d944c
📒 Files selected for processing (3)
backend/protocol_rpc/health.pybackend/services/usage_metrics_service.pytests/db-sqlalchemy/test_health_orphan_detection.py
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/unit/test_usage_metrics_service.py (1)
10-10: ⚡ Quick winAdd a return type hint to the async test function.
Use
-> Noneon the test coroutine to satisfy the project typing rule.Proposed patch
`@pytest.mark.asyncio` -async def test_system_health_metrics_include_max_recovery_events(): +async def test_system_health_metrics_include_max_recovery_events() -> None:As per coding guidelines,
**/*.py: Include type hints in all Python code.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/test_usage_metrics_service.py` at line 10, The async test coroutine test_system_health_metrics_include_max_recovery_events is missing a return type hint; update its signature to include "-> None" (e.g., async def test_system_health_metrics_include_max_recovery_events() -> None:) to satisfy the project typing rule and ensure the test function is properly typed.tests/unit/test_rpc_health_genvm_tracking.py (1)
283-338: ⚡ Quick winAdd type hints to the new async test and local fake classes.
These new definitions are untyped, which violates the repository Python typing rule.
Proposed patch
@@ `@pytest.mark.asyncio` async def test_consensus_health_includes_max_recovery_exhaustion_events( - self, monkeypatch - ): + self, monkeypatch: pytest.MonkeyPatch + ) -> None: @@ class FakeResult: - def __init__(self, row=None, rows=None): + def __init__( + self, + row: SimpleNamespace | None = None, + rows: list[SimpleNamespace] | None = None, + ) -> None: self.row = row self.rows = rows or [] - def fetchone(self): + def fetchone(self) -> SimpleNamespace | None: return self.row - def fetchall(self): + def fetchall(self) -> list[SimpleNamespace]: return self.rows class FakeConnection: - def __enter__(self): + def __enter__(self) -> "FakeConnection": return self - def __exit__(self, exc_type, exc, tb): + def __exit__(self, exc_type: object, exc: object, tb: object) -> bool: return False - def execute(self, statement, params=None): + def execute(self, statement: object, params: object | None = None) -> FakeResult: query = str(statement) @@ class FakeEngine: - def connect(self): + def connect(self) -> FakeConnection: return FakeConnection()As per coding guidelines,
**/*.py: Include type hints in all Python code.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/test_rpc_health_genvm_tracking.py` around lines 283 - 338, The test function test_consensus_health_includes_max_recovery_exhaustion_events and its local helper classes (FakeResult, FakeConnection, FakeEngine) lack type annotations; update the async test signature to include return type "-> None" and add appropriate type hints for class attributes and methods (e.g., FakeResult.__init__(self, row: Optional[Any]=None, rows: Optional[List[Any]]=None), fetchone(self) -> Optional[Any], fetchall(self) -> List[Any]; FakeConnection.__enter__(self) -> "FakeConnection", __exit__(self, exc_type: Optional[Type[BaseException]], exc: Optional[BaseException], tb: Optional[TracebackType]) -> bool, execute(self, statement: Any, params: Optional[Mapping[str, Any]] = None) -> FakeResult; FakeEngine.connect(self) -> FakeConnection) and annotate exhausted_tx with a concrete type (e.g., SimpleNamespace or a TypedDict/NamedTuple) to satisfy repository typing rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/unit/test_rpc_health_genvm_tracking.py`:
- Around line 283-338: The test function
test_consensus_health_includes_max_recovery_exhaustion_events and its local
helper classes (FakeResult, FakeConnection, FakeEngine) lack type annotations;
update the async test signature to include return type "-> None" and add
appropriate type hints for class attributes and methods (e.g.,
FakeResult.__init__(self, row: Optional[Any]=None, rows:
Optional[List[Any]]=None), fetchone(self) -> Optional[Any], fetchall(self) ->
List[Any]; FakeConnection.__enter__(self) -> "FakeConnection", __exit__(self,
exc_type: Optional[Type[BaseException]], exc: Optional[BaseException], tb:
Optional[TracebackType]) -> bool, execute(self, statement: Any, params:
Optional[Mapping[str, Any]] = None) -> FakeResult; FakeEngine.connect(self) ->
FakeConnection) and annotate exhausted_tx with a concrete type (e.g.,
SimpleNamespace or a TypedDict/NamedTuple) to satisfy repository typing rules.
In `@tests/unit/test_usage_metrics_service.py`:
- Line 10: The async test coroutine
test_system_health_metrics_include_max_recovery_events is missing a return type
hint; update its signature to include "-> None" (e.g., async def
test_system_health_metrics_include_max_recovery_events() -> None:) to satisfy
the project typing rule and ensure the test function is properly typed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2ae8af47-5251-477e-b7f8-000e91cd07dd
📒 Files selected for processing (5)
backend/protocol_rpc/health.pybackend/services/usage_metrics_service.pytests/db-sqlalchemy/test_health_orphan_detection.pytests/unit/test_rpc_health_genvm_tracking.pytests/unit/test_usage_metrics_service.py
🚧 Files skipped from review as they are similar to previous changes (3)
- tests/db-sqlalchemy/test_health_orphan_detection.py
- backend/protocol_rpc/health.py
- backend/services/usage_metrics_service.py
|
🎉 This PR is included in version 0.120.17 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary:
Verification:
Summary by CodeRabbit
New Features
Tests