Skip to content

test(state): sweep async time.sleep → asyncio.sleep (followup to #73)#76

Merged
patrick-chinchill merged 2 commits into
mainfrom
test/async-sleep-sweep
Apr 24, 2026
Merged

test(state): sweep async time.sleep → asyncio.sleep (followup to #73)#76
patrick-chinchill merged 2 commits into
mainfrom
test/async-sleep-sweep

Conversation

@patrick-chinchill
Copy link
Copy Markdown
Collaborator

@patrick-chinchill patrick-chinchill commented Apr 24, 2026

Summary

  • Followup to PR feat(state): IoRedisStateAdapter for cross-runtime interop (#71) #73, which fixes this hazard in tests/test_state_redis.py. Identical sync time.sleep calls remained in the MemoryState and PostgresState test suites — sweeping them here.
  • 16 sites swept total: 7 in tests/test_memory_state.py, 9 in tests/test_state_postgres.py. Each was inside a @pytest.mark.asyncio async def test_* method, so time.sleep(X)await asyncio.sleep(X) is a direct, semantics-preserving swap.
  • import asyncio added (alphabetized) to both files. import time kept — both files still use time.time() for millisecond timestamps.

Why it matters

Sync time.sleep blocks the event loop in an async test, which can flake adjacent tests and mask ordering bugs. Same rationale as #73; no test-level behavior change is intended.

Test plan

  • uv run ruff check src/ tests/ scripts/
  • uv run ruff format --check src/ tests/ scripts/
  • uv run pyrefly check (0 errors)
  • uv run python scripts/audit_test_quality.py (0 hard failures; pre-existing duplicate-test warnings only)
  • uv run python scripts/verify_test_fidelity.py (no regression; 40 pre-existing missing)
  • uv run pytest tests/test_memory_state.py tests/test_state_postgres.py --tb=short -q — 105 passed
  • uv run pytest tests/ --tb=short -q — 3545 passed, 2 skipped

Notes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Improved test reliability and execution by replacing blocking waits with non-blocking asynchronous waits.
    • Enhanced stability for expiration, lock timing, and other time-dependent behaviors, reducing flakiness in async tests.
  • Documentation

    • Changelog updated to document the test hygiene improvements.

Same hazard as PR #73: sync time.sleep blocks the event loop in async
tests, which can flake adjacent tests and mask ordering bugs.

- tests/test_memory_state.py: 7 sites
- tests/test_state_postgres.py: 9 sites

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 62083d9d-b100-46d0-96fa-b23fba0b0b16

📥 Commits

Reviewing files that changed from the base of the PR and between 8879b56 and 7883a73.

📒 Files selected for processing (1)
  • tests/test_state_postgres.py

📝 Walkthrough

Walkthrough

This PR replaces blocking time.sleep() calls with non-blocking await asyncio.sleep() in async test files and adds a changelog "Unreleased" entry documenting the test hygiene change tied to a prior Redis flaky-test fix.

Changes

Cohort / File(s) Summary
Documentation
CHANGELOG.md
Adds an "Unreleased" changelog entry under "Test hygiene" describing replacement of blocking sleeps with async sleeps and referencing the prior Redis flaky-test fix.
Test Suite Updates
tests/test_memory_state.py, tests/test_state_postgres.py
Adds import asyncio and replaces time.sleep(...) with await asyncio.sleep(...) in TTL/expiry, lock timing, and list-expiry tests; removes one now-unnecessary short explicit sleep in a lock upsert test.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I swapped my naps for gentle waits,
Awaiting ticks through async gates.
No blocking snores to stall the run,
The event loop hums — hoppity fun! 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing blocking time.sleep with non-blocking asyncio.sleep in async tests, following up on PR #73.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/async-sleep-sweep

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces synchronous time.sleep calls with await asyncio.sleep in asynchronous tests for the memory and Postgres state adapters to improve test hygiene and mitigate flaky-test hazards. Feedback was provided to remove a redundant asyncio.sleep call in tests/test_state_postgres.py where the lock is manually expired, rendering the sleep unnecessary.

Comment thread tests/test_state_postgres.py Outdated
# Third acquire after expiry: should succeed in single query
mock_pool.executed_queries.clear()
time.sleep(0.005)
await asyncio.sleep(0.005)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This asyncio.sleep call is redundant in this specific test case. The lock is acquired with a 30-second TTL at line 739, and then it is manually force-expired by directly modifying the mock pool's state at line 759. The 5ms sleep does not contribute to the expiration logic and can be safely removed to improve test efficiency.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 7883a73 — the sleep was mechanical leftover from the time.sleep sweep; force-expiry on the next line makes it redundant. Thanks.

…gres test

The lock is force-expired on the next line by directly setting expires_at
into the past — the 5ms sleep contributed nothing. Flagged by gemini on
PR #76.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@patrick-chinchill patrick-chinchill merged commit ad37249 into main Apr 24, 2026
10 checks passed
patrick-chinchill added a commit that referenced this pull request Apr 24, 2026
Parity catch-up release for upstream chat@4.26.0. Bundles 8 PRs (#64 #65 #66 #67 #73 #74 #75 #76) + small followup cleanups. See CHANGELOG.md for details.
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