Skip to content

Optimize chaos test setup and add type checking#195

Merged
chrisguidry merged 2 commits intomainfrom
bump-timeout
Nov 13, 2025
Merged

Optimize chaos test setup and add type checking#195
chrisguidry merged 2 commits intomainfrom
bump-timeout

Conversation

@chrisguidry
Copy link
Copy Markdown
Owner

@chrisguidry chrisguidry commented Nov 13, 2025

The chaos tests spawn 15 processes (5 producers + 10 workers) that randomly use either the latest PyPI release or the current main branch. This helps catch data contract issues when introducing changes.

Previously, each process used `uv run --isolated --with pydocket==X.Y.Z`, creating a new isolated environment for every spawn (~0.45s each). With 15 processes, that's about 6.75 seconds of overhead just for environment setup.

Changes

Performance optimization:

  • Added `setup_environments()` function that creates two persistent venvs once at startup (one for base version, one for main)
  • Modified process spawning to use Python executables directly from pre-created environments
  • Removed `uv run --isolated` overhead, reducing setup time from ~6.75s to ~1s
  • Reduced CI timeout from 3 minutes to 2 minutes

Type checking improvements:

  • Added `chaos/` to pyright include paths in pyproject.toml
  • Added new pre-commit hook for chaos tests using the same strict mode as the test suite
  • Fixed type errors from incomplete third-party library stubs (docker, redis) with appropriate type: ignore comments

The optimization saves about 5-6 seconds per chaos test run while maintaining the same random version selection behavior for migration testing.

🤖 Generated with Claude Code

Co-authored-by: Claude noreply@anthropic.com

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Nov 13, 2025

Claude finished @chrisguidry's task —— View job


PR Review: Bump the timeout for the chaos tests

I've reviewed the changes in this PR. Here's my analysis:

Todo List

  • Review .pre-commit-config.yaml changes
  • Review chaos/driver.py changes
  • Review pyproject.toml changes
  • Analyze code quality and best practices
  • Check for potential bugs or issues
  • Consider performance implications
  • Review security concerns
  • Verify test coverage

Summary

This PR increases the GitHub Actions timeout for chaos tests from 2 to 3 minutes and refactors the chaos test setup to use pre-created virtual environments instead of on-the-fly uv run --isolated commands. Additionally, it adds pyright type checking for the chaos test directory.

Changes Review

1. Environment Setup Optimization (chaos/driver.py)

✅ Positive Changes:

  • The new setup_environments() function pre-creates virtual environments once at the start, which should significantly improve performance compared to the previous uv run --isolated approach that created isolated environments for each producer/worker spawn
  • Properly handles OpenTelemetry instrumentation compatibility
  • Clear separation of concerns with a dedicated setup function

Suggestions:

  • Consider cleaning up the temporary directories (temp_dir) after the test completes to avoid disk space issues over time. You could use tempfile.TemporaryDirectory() context manager or add cleanup in a finally block

2. Type Checking Improvements

✅ Positive Changes:

  • Added # type: ignore[reportUnknownMemberType] annotations for Redis operations where type stubs are incomplete
  • Added pyright type checking for chaos tests in both .pre-commit-config.yaml and pyproject.toml
  • This ensures chaos test code maintains the same quality standards as the main codebase

3. Timeout Adjustment

✅ Reasonable Change:

  • Increasing timeout from 2 to 3 minutes is sensible given the complexity of chaos tests
  • The optimization of environment setup should actually make tests faster, but having buffer time for chaos scenarios is prudent

Potential Issues

1. Error Handling in Environment Setup

The setup_environments() function doesn't check subprocess return codes. If uv venv or uv pip install fails, the function will continue and might produce confusing errors later:

process = await asyncio.create_subprocess_exec(...)
await process.wait()
# Should check: if process.returncode != 0: handle error

2. Resource Cleanup

The temporary virtual environments created in /tmp/docket-chaos-{uuid} are never cleaned up. Over many test runs, this could accumulate significant disk space.

Performance Considerations

✅ Improvements:

  • Pre-creating environments should be much faster than repeated uv run --isolated calls
  • The tradeoff is slightly more upfront setup time for significantly faster worker/producer spawning

Neutral:

  • Suppressing stdout/stderr (DEVNULL) improves performance but might make debugging harder if setup fails

Security Considerations

No security issues identified. The changes:

  • Don't expose any sensitive information
  • Use appropriate temporary directory paths with UUID for isolation
  • Maintain proper subprocess handling

Test Coverage

Coverage maintained at 100% as confirmed by the codecov report. The chaos tests themselves are integration tests that help ensure system reliability under adverse conditions.

Recommendations

  1. Add error handling for subprocess failures in setup_environments()
  2. Consider cleanup of temporary directories after test completion
  3. Optional: Add a comment explaining why the timeout was increased (e.g., "Increased to accommodate environment setup time" or specific failure scenarios)

Overall Assessment

This is a well-thought-out optimization that should improve chaos test reliability and performance. The main suggestions are around error handling and resource cleanup, but the core changes are solid and maintain code quality standards.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 13, 2025

📚 Documentation has been built for this PR!

You can download the documentation directly here:
https://github.com/chrisguidry/docket/actions/runs/19318228324/artifacts/4550954779

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Nov 13, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (52effb4) to head (dbe4f33).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #195   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           43        43           
  Lines         7197      7197           
  Branches       369       369           
=========================================
  Hits          7197      7197           
Flag Coverage Δ
python-3.10 100.00% <ø> (ø)
python-3.11 99.08% <ø> (ø)
python-3.12 100.00% <ø> (ø)
python-3.13 100.00% <ø> (ø)
python-3.14 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

## Performance optimization

The chaos tests spawn 15 processes (5 producers + 10 workers), each randomly using either the base version or main version of pydocket. Previously, each process used `uv run --isolated --with pydocket==X.Y.Z`, which created a new isolated environment for every spawn (~0.45s each = ~6.75s total overhead).

Now we create two persistent virtual environments upfront (one for base version, one for main) and use the Python executables directly from those environments. This reduces the setup time from ~6.75s to ~1s, saving about 5-6 seconds per chaos test run.

## Type checking improvements

Added pyright type checking for the chaos test suite:
- Added chaos/ to pyright include paths in pyproject.toml
- Added new pre-commit hook for pyright (chaos tests)
- Fixed type errors from incomplete third-party library stubs (docker, redis) with type: ignore comments

All pre-commit hooks now pass including the new chaos type checking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
@chrisguidry chrisguidry changed the title Bump the timeout for the chaos tests Optimize chaos test setup and add type checking Nov 13, 2025
@chrisguidry chrisguidry merged commit 80c1357 into main Nov 13, 2025
25 checks passed
@chrisguidry chrisguidry deleted the bump-timeout branch November 13, 2025 02:14
chrisguidry added a commit that referenced this pull request Mar 10, 2026
croniter 6.0.0 has two unbounded memory leaks
([#182](pallets-eco/croniter#182),
[#195](pallets-eco/croniter#195)) that are
fixed in main but unreleased — and the project was declared unmaintained
by Pallets Community Ecosystem in March 2025, so no release is coming.
It also drags in pytz and python-dateutil as transitive deps.

cronsim is actively maintained (~280 lines, zero deps, Python 3.10+),
used in production by Healthchecks.io, and handles DST via zoneinfo
natively. One gap: cronsim doesn't support Vixie keywords (@daily,
@hourly, etc.), so we add a small mapping dict that expands them before
passing to CronSim.

Also extracted `Cron.next_time()` so tests mock at docket's abstraction
level rather than the library's internals, and added contract tests that
exercise the real cronsim integration (sequential times, timezone
handling, keyword validity).

Companion conda-forge PR: conda-forge/pydocket-feedstock#34

Closes #362

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chrisguidry added a commit that referenced this pull request Mar 10, 2026
croniter 6.0.0 has two unbounded memory leaks
([#182](pallets-eco/croniter#182),
[#195](pallets-eco/croniter#195)) that are
fixed in main but unreleased — and the project was declared unmaintained
by Pallets Community Ecosystem in March 2025, so no release is coming.
It also drags in pytz and python-dateutil as transitive deps.

cronsim is actively maintained (~280 lines, zero deps, Python 3.10+),
used in production by Healthchecks.io, and handles DST via zoneinfo
natively. One gap: cronsim doesn't support Vixie keywords (@daily,
@hourly, etc.), so we add a small mapping dict that expands them before
passing to CronSim.

Also extracted `Cron.next_time()` so tests mock at docket's abstraction
level rather than the library's internals, and added contract tests that
exercise the real cronsim integration (sequential times, timezone
handling, keyword validity).

Companion conda-forge PR:
conda-forge/pydocket-feedstock#34

Closes #362

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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.

2 participants