Skip to content

Expand documentation with comprehensive guides addressing #134#145

Merged
chrisguidry merged 6 commits intomainfrom
docs-boost
Jun 25, 2025
Merged

Expand documentation with comprehensive guides addressing #134#145
chrisguidry merged 6 commits intomainfrom
docs-boost

Conversation

@chrisguidry
Copy link
Owner

@chrisguidry chrisguidry commented Jun 25, 2025

Summary

Closes #134 by adding detailed documentation that covers all the advanced features demonstrated in the test suite.

Added four new comprehensive guides:

  • Dependencies Guide - dependency injection, retry patterns, timeouts, custom dependencies
  • Testing with Docket - pytest fixtures, testing utilities, integration testing
  • Advanced Task Patterns - perpetual tasks, striking/restoring, logging, task chains
  • Docket in Production - Redis architecture, monitoring, deployment strategies

Enhanced Getting Started with better explanations of task keys and idempotency. Updated navigation structure for better learning flow. Added FastAPI/Typer context to README.

Fixed factual errors in dependency examples and clarified task cancellation behavior. Reformatted code blocks and softened overly confident language.

🤖 Generated with Claude Code

## Summary
- Closes #132 by adding PEP 740 attestations to PyPI releases
- Switches from `uv publish` to `pypa/gh-action-pypi-publish` for
built-in attestation support
- Adds PyPI environment configuration for proper trusted publishing
setup

## Security Benefits
- Automatic generation of cryptographically signed attestations for all
releases
- Provides verifiable link between published packages and source
repository
- Uses GitHub's OIDC token for trusted publishing and attestation
signing

## Test Plan
- [ ] Create a test release to verify attestations are generated
correctly
- [ ] Confirm attestations appear on PyPI package page
- [ ] Validate workflow runs successfully with new configuration

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

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Jun 25, 2025

📚 Documentation has been built for this PR!

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

@codecov-commenter
Copy link

codecov-commenter commented Jun 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (8892251) to head (7182b98).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #145   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           28        28           
  Lines         3570      3570           
  Branches       191       191           
=========================================
  Hits          3570      3570           
Flag Coverage Δ
python-3.12 100.00% <ø> (ø)
python-3.13 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.

Comment on lines +188 to +194
Ready for more? Check out:

Docket provides _at-least-once_ delivery semantics. When a worker picks up a
task, if it crashes or fails to acknowledge within `redelivery_timeout`, the
task will be considered unacknowledged and redelivered to another available
worker. This ensures tasks are not lost but may be delivered more than once. To
achieve exactly-once processing, design your tasks to be idempotent.
- **Dependencies Guide** - Access current docket, advanced retry patterns, timeouts, and custom dependencies
- **Testing with Docket** - Ergonomic testing utilities for unit and integration tests
- **Advanced Task Patterns** - Perpetual tasks, striking/restoring, logging, and task chains
- **Docket in Production** - Redis architecture, monitoring, and deployment best practices
- **[API Reference](api-reference.md)** - Complete documentation of all classes and methods
Copy link
Owner Author

Choose a reason for hiding this comment

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

These should be links, right?

docs/testing.md Outdated

## Controlling Perpetual Tasks

Use `run_at_most()` to limit how many times specific tasks run, which is essential for testing perpetual tasks:
Copy link
Owner Author

Choose a reason for hiding this comment

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

Can we make all function references like this links to the appropriate API reference?

docs/testing.md Outdated

You can use task keys in `run_at_most()` to control specific task instances rather than all tasks of a given type.

## Testing with Built-in Utility Tasks
Copy link
Owner Author

Choose a reason for hiding this comment

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

Cut this section, it's kinda nonsense

docs/testing.md Outdated
- Debugging task execution order
- Creating synthetic failures for error handling tests

## Testing Retry Logic
Copy link
Owner Author

Choose a reason for hiding this comment

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

This section is also nonsense, cut it

docs/testing.md Outdated
assert service.attempts == 3
```

## Testing Dependencies
Copy link
Owner Author

Choose a reason for hiding this comment

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

Unclear if this section makes sense. LEt's rewrite it with the goal of explaining simple patterns for testing custom dependencies, which won't themselves be mocks like the weird example shows here.

@@ -0,0 +1,454 @@
# Testing with Docket
Copy link
Owner Author

Choose a reason for hiding this comment

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

One thing I think we're missing here is the simple fact that you can often test your tasks without running a worker! they're simple python functions and you can pass your own test values for all the dependency parameters as kwargs! We should show more examples of doing that before we jump into complex testing examples where we're setting up dockets and workers. There is absolutely a place for using dockets in tests to verify future scheduling (great example below) and running workers, so let's keep these in as well.

Comment on lines +21 to +38
@pytest.fixture
async def test_docket() -> AsyncGenerator[Docket, None]:
"""Create a test docket with a unique name for each test."""
async with Docket(
name=f"test-{uuid4()}",
url="redis://localhost:6379/0"
) as docket:
yield docket

@pytest.fixture
async def test_worker(test_docket: Docket) -> AsyncGenerator[Worker, None]:
"""Create a test worker with fast polling for quick tests."""
async with Worker(
test_docket,
minimum_check_interval=timedelta(milliseconds=5),
scheduling_resolution=timedelta(milliseconds=5)
) as worker:
yield worker
Copy link
Owner Author

Choose a reason for hiding this comment

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

We set up these great fixtures, but then many of the examples below set up their own dockets and workers, let's just have as many examples as possible use these fixtures

docs/testing.md Outdated
Comment on lines +40 to +52
# Mock task fixture for testing
@pytest.fixture
def mock_task() -> AsyncMock:
task = AsyncMock()
task.__name__ = "mock_task"
return task

@pytest.fixture
def now() -> Callable[[], datetime]:
"""Consistent time source for tests."""
from functools import partial
from datetime import timezone
return partial(datetime.now, timezone.utc)
Copy link
Owner Author

Choose a reason for hiding this comment

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

Let's drop these

docs/testing.md Outdated
Comment on lines +60 to +62
async def test_task_execution(
test_docket: Docket, test_worker: Worker, mock_task: AsyncMock
):
Copy link
Owner Author

Choose a reason for hiding this comment

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

We shouldn't be using mock_tasks in these examples, the user would use their own real tasks!

docs/testing.md Outdated
Test that tasks are properly registered and can be called by name:

```python
async def test_task_registration_by_name(test_docket, test_worker, mock_task):
Copy link
Owner Author

Choose a reason for hiding this comment

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

Missing types

Comment on lines +5 to +18
## Redis Streams Architecture

Docket uses Redis streams and sorted sets to provide reliable task delivery with at-least-once semantics.

### Data Storage Model

Docket creates several Redis data structures for each docket:

- **Stream (`{docket}:stream`)**: Ready-to-execute tasks using Redis consumer groups
- **Sorted Set (`{docket}:queue`)**: Future tasks ordered by scheduled execution time
- **Hashes (`{docket}:{key}`)**: Serialized task data for scheduled tasks
- **Set (`{docket}:workers`)**: Active worker heartbeats with timestamps
- **Set (`{docket}:worker-tasks:{worker}`)**: Tasks each worker can execute
- **Stream (`{docket}:strikes`)**: Strike/restore commands for operational control
Copy link
Owner Author

Choose a reason for hiding this comment

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

Let's move these down lower, they are implementation details

Comment on lines +206 to +224
**Task Counters:**
- `docket_tasks_added` - Tasks scheduled
- `docket_tasks_started` - Tasks begun execution
- `docket_tasks_succeeded` - Successfully completed tasks
- `docket_tasks_failed` - Failed tasks
- `docket_tasks_retried` - Retry attempts
- `docket_tasks_stricken` - Tasks blocked by strikes

**Task Timing:**
- `docket_task_duration` - Histogram of task execution times
- `docket_task_punctuality` - How close tasks run to their scheduled time

**System Health:**
- `docket_queue_depth` - Tasks ready for immediate execution
- `docket_schedule_depth` - Tasks scheduled for future execution
- `docket_tasks_running` - Currently executing tasks
- `docket_redis_disruptions` - Redis connection failures
- `docket_strikes_in_effect` - Active strike rules

Copy link
Owner Author

Choose a reason for hiding this comment

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

these got formatted oddly in the resulting page:

image

Comment on lines +246 to +262
Configure your OpenTelemetry exporter to send traces to your observability platform:

```python
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# Configure tracing before creating workers
trace.set_tracer_provider(TracerProvider())
jaeger_exporter = JaegerExporter(
agent_host_name="jaeger",
agent_port=6831,
)
span_processor = BatchSpanProcessor(jaeger_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
```
Copy link
Owner Author

Choose a reason for hiding this comment

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

Rather than showing them in our docs, let's just link them out to https://opentelemetry.io/docs/languages/python/ and such

Comment on lines +319 to +336
### Deployment Strategies

**Blue-green deployments:**
```bash
# Deploy new workers with different name
docket worker --name orders-worker-v2 --tasks myapp.tasks:v2_tasks

# Gradually strike old task versions
docket strike old_task_function

# Scale down old workers after tasks drain
```

**Rolling updates:**
```bash
# Update worker configuration gradually
# Workers automatically reconnect and pick up new tasks
```
Copy link
Owner Author

Choose a reason for hiding this comment

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

I think we can skip this stuff

- Move Redis data structures section lower as implementation details
- Fix metrics formatting from bold to proper headings
- Replace OpenTelemetry code example with documentation link
- Remove rolling updates section
- Fix testing.md to use fixtures consistently and add missing type annotations
- Replace all instances of 'best practices' with better terminology
- Simplify Redis connection pool example by removing socket options
- Correct Redis requirements - remove cluster/sentinel support claims
- Remove confusing Testing Dependencies section
@chrisguidry chrisguidry merged commit 977b99e into main Jun 25, 2025
16 checks passed
@chrisguidry chrisguidry deleted the docs-boost branch June 25, 2025 01:27
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.

The documentation for Docket barely describes all the cool stuff you can do with dependencies

2 participants