-
Notifications
You must be signed in to change notification settings - Fork 3
Add result persistence #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add comprehensive result storage and retrieval for task executions using py-key-value-aio as the backend. Results are serialized with cloudpickle, base64-encoded for JSON compatibility, and stored with TTL matching execution_ttl. Key features: - Tasks returning non-None values store results in result_storage - Tasks annotated with -> None or returning None skip persistence - Execution.get_result() retrieves results, waiting via pub/sub if needed - Failed tasks store exceptions which are re-raised on retrieval - Result TTL matches execution_ttl for consistent expiration - Added returns_none() helper to check type annotations Implementation: - Added result field to Execution class for tracking result location - Updated mark_as_completed() and mark_as_failed() to accept result_key - Worker._execute() captures results and stores them after completion - Worker._execute() stores exceptions for failed tasks - Comprehensive test coverage for various scenarios Addresses #166 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit fixes several resource cleanup issues and adds comprehensive tests to achieve 100% code coverage. ## Fixes ### RedisStore Cleanup (docket.py) - Add proper cleanup of result_storage in Docket.__aexit__() - RedisStore maintains its own connection pool that wasn't being closed - Fixes ResourceWarning about unclosed connections ### Test Mock Cleanup (test_execution_progress.py) - Fix incomplete Redis async context manager mocks - Add __aexit__ configuration to prevent connection cleanup warnings - Applied to test_execution_sync_with_missing_state_field and test_execution_sync_with_string_state_value ### Exception Pickling (test_results.py) - Fix CustomError to properly pickle/unpickle - Pass both args to super().__init__() to preserve exception state ### Timeout Handling (execution.py) - Fix get_result() timeout to work even when no events arrive - Wrap subscribe loop with asyncio.wait_for() - Add early check for already-expired timeouts ## New Tests Added 4 tests to test_results.py for 100% coverage: - test_get_result_with_expired_timeout - test_get_result_failed_task_without_result_key - test_get_result_with_malformed_result_data - test_get_result_failed_task_with_missing_exception_data ## Results - All 395 tests passing - 100% code coverage achieved - No resource warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
9f7b479 to
5af635c
Compare
|
Claude finished @desertaxle's task —— View job Code Review: Result Persistence PR✅ Overall AssessmentThis PR successfully implements result persistence for task executions with a well-designed API and comprehensive test coverage. The implementation is clean, follows existing patterns in the codebase, and maintains 100% test coverage as required. 🎯 Code Quality & Best PracticesStrengths:
Minor Suggestions:
🔒 Security ConsiderationsPotential Concerns:
Mitigations in Place:
Recommendation: Consider documenting that this feature should only be used in trusted environments where all task results come from known sources. ⚡ Performance ConsiderationsPositives:
Potential Improvements:
🐛 Potential Issues
📚 Documentation & TestingTest Coverage Highlights:
Suggestion: The reviewer's request to copy the test to 🔄 Backwards CompatibilityThe implementation maintains backwards compatibility:
📝 SummaryThis is a well-implemented feature that adds significant value to the Docket system. The code is production-ready with only minor cosmetic suggestions. The comprehensive test suite and proper error handling demonstrate thorough engineering. Recommended Actions:
Great work on this implementation! The feature is well-designed and thoroughly tested. 🎉 |
|
📚 Documentation has been built for this PR! You can download the documentation directly here: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #184 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 36 37 +1
Lines 6100 6400 +300
Branches 295 312 +17
==========================================
+ Hits 6100 6400 +300
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
This reverts commit 01809f6.
… persistence Documents features added in PRs #181, #184, and #189: - Add comprehensive "Task State and Progress Monitoring" section to advanced-patterns.md covering execution state machine, Redis data model, pub/sub events, progress reporting, result retrieval, and CLI monitoring - Add Progress() dependency documentation to dependencies.md with usage examples and links to detailed patterns - Add "State and Result Storage" section to production.md documenting execution_ttl configuration, fire-and-forget mode (execution_ttl=0), and custom result storage backends - Add "Task Observability" section to getting-started.md introducing state tracking, progress reporting, and result retrieval with links to detailed documentation All documentation includes working code examples and follows the existing tone and style. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
… persistence (#191) ## Summary Adds comprehensive documentation for the execution state tracking, progress monitoring, and result persistence features introduced in PRs #181, #184, and #189. **Related PRs:** - #181 - Add execution state tracking and progress monitoring - #184 - Add result persistence - #189 - Add support for execution_ttl=0 and timeout/deadline parameters ## Documentation Changes ### docs/advanced-patterns.md Added a new major section **"Task State and Progress Monitoring"** covering: - **High-Level Design** - Architecture overview explaining the execution state machine, Redis data model, pub/sub event system, and result storage - **Tracking Execution State** - How to query and monitor task states - **Reporting Task Progress** - Using the `Progress()` dependency with `ExecutionProgress` API - **Monitoring Progress in Real-Time** - Subscribing to progress and state events programmatically - **Advanced Progress Patterns** - Incremental progress, batch updates, and nested tracking patterns - **Retrieving Task Results** - Using `get_result()` with timeout/deadline parameters and exception handling - **CLI Monitoring with Watch** - Using the `docket watch` command for real-time monitoring - **Fire-and-Forget Mode** - Documenting `execution_ttl=0` for high-throughput scenarios ### docs/dependencies.md Added **"Reporting Task Progress"** subsection to Built-in Context Dependencies: - Documents the `Progress()` dependency injection pattern - Explains `ExecutionProgress` methods (`set_total`, `increment`, `set_message`, `sync`) - Highlights key characteristics (atomic, real-time, observable, ephemeral) - Links to detailed documentation in advanced-patterns.md ### docs/production.md Added **"State and Result Storage"** section: - Execution state tracking configuration with `execution_ttl` - Fire-and-forget mode using `execution_ttl=0` for maximum throughput - Result storage configuration with custom backends (RedisStore, MemoryStore) - Best practices for TTL management, separate databases, and large results - Monitoring state and result storage in Redis ### docs/getting-started.md Added **"Task Observability"** section: - Introduction to execution state tracking - Basic progress reporting examples - Task result retrieval with `get_result()` - Links to detailed documentation in advanced-patterns.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <[email protected]>
Summary
Adds automatic result persistence for task executions using
py-key-value-aiostorage, plus critical bug fixes for resource cleanup and improved test coverage.✨ New Feature: Result Persistence
Tasks can now store return values and exceptions for later retrieval:
Key Features
get_result()Noneskip persistenceexecution_ttl(default: 1 hour)get_result(timeout=...)with graceful timeout handlingImplementation Details
Docket.result_storage:RedisStoreorMemoryStorebackendExecution.result_key: Tracks where result is storedExecution.get_result(): Retrieves results, waiting via pub/sub if neededStorage Backend
Uses
py-key-value-aiowith pluggable storage:RedisStorefor production (separate connection pool)MemoryStoreformemory://URLs (testing)📚 API Changes
New Public Methods
Docket Configuration
Closes #166
🤖 Generated with Claude Code