Skip to content

Commit 394b4e0

Browse files
committed
Initial commit
Multiple scheduler instances executed the same scheduled task multiple times instead of once. Tests confirmed task executed 20+ times with just 2 instances. Missing `heartbeat = NOW()` in build_fetch_schedule_query() UPDATE clause. This broke multi-instance safety - other instances saw old heartbeat, thought the task was stale (crashed instance), and re-picked it. Add `heartbeat = NOW()` to UPDATE SET clause, matching the pattern already correctly implemented in build_dequeue_query(). - fix: Add heartbeat = NOW() to scheduler query (qb.py:720) - test: Add 12 critical tests - test_issue_536_minimal.py (3 tests - no DB needed) - test_issue_536_critical.py (8 tests - comprehensive) - test_scheduler.py (3 integration tests added) All tests pass: 12/12 ✅ Fixes #536 fix(#536): Fix croniter time mocking and consolidate redundant tests Changes: 1. Fix croniter to use mocked time in schedulers - croniter(expr) was using real system time while helpers.utc_now() was mocked - This caused negative next_in() values, making tasks always appear due - Solution: Pass start_time=helpers.utc_now() to croniter - File: pgqueuer/core/executors.py:285 2. Tighten test_multi_instance_single_task_execution assertion - Changed from <= 3 to <= 2 executions (more precise) - Added detailed diagnostic messages - File: test/test_scheduler.py:360-374 3. Consolidate redundant Issue #536 tests - Deleted test_issue_536_critical.py (326 lines) - Had duplicate tests of heartbeat_in_query and consistency checks - Had 4 documentation-only tests that didn't verify functionality - Removed test_query_structure_has_heartbeat_update from test_scheduler.py - Duplicate of test_issue_536_minimal.py::test_issue_536_heartbeat_in_query - Result: 14 tests → 5 tests, 839 lines → 481 lines Final test suite: ✓ test_issue_536_minimal.py (3 SQL validation tests, no DB needed)
0 parents  commit 394b4e0

37 files changed

+5928
-0
lines changed

.github/workflows/ci.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Lint & type-check
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v5
18+
with:
19+
enable-cache: true
20+
21+
- name: Set up Python 3.12
22+
run: uv python install 3.12
23+
24+
- name: Install dependencies
25+
run: uv sync --extra dev
26+
27+
- name: ruff check
28+
run: uv run ruff check .
29+
30+
- name: mypy
31+
run: uv run mypy .
32+
33+
test:
34+
name: Test (Python 3.12)
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
39+
- name: Install uv
40+
uses: astral-sh/setup-uv@v5
41+
with:
42+
enable-cache: true
43+
44+
- name: Set up Python 3.12
45+
run: uv python install 3.12
46+
47+
- name: Install dependencies
48+
run: uv sync --extra s3 --extra gcs --extra dev
49+
50+
- name: pytest
51+
run: uv run pytest tests/ -v

.github/workflows/release.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Release
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
lint:
9+
name: Lint & type-check
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- name: Install uv
15+
uses: astral-sh/setup-uv@v5
16+
with:
17+
enable-cache: true
18+
19+
- name: Set up Python 3.12
20+
run: uv python install 3.12
21+
22+
- name: Install dependencies
23+
run: uv sync --extra dev
24+
25+
- name: ruff check
26+
run: uv run ruff check .
27+
28+
- name: mypy
29+
run: uv run mypy .
30+
31+
test:
32+
name: Test (Python 3.12)
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
37+
- name: Install uv
38+
uses: astral-sh/setup-uv@v5
39+
with:
40+
enable-cache: true
41+
42+
- name: Set up Python 3.12
43+
run: uv python install 3.12
44+
45+
- name: Install dependencies
46+
run: uv sync --extra s3 --extra gcs --extra dev
47+
48+
- name: pytest
49+
run: uv run pytest tests/ -v
50+
51+
publish:
52+
name: Build & publish to PyPI
53+
runs-on: ubuntu-latest
54+
needs: [lint, test]
55+
environment: pypi
56+
permissions:
57+
id-token: write # required for OIDC trusted publishing
58+
steps:
59+
- uses: actions/checkout@v4
60+
61+
- name: Install uv
62+
uses: astral-sh/setup-uv@v5
63+
with:
64+
enable-cache: true
65+
66+
- name: Set up Python 3.12
67+
run: uv python install 3.12
68+
69+
- name: Build package
70+
run: uv build
71+
72+
- name: Publish to PyPI
73+
uses: pypa/gh-action-pypi-publish@release/v1

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.pyo
5+
*.pyd
6+
*.so
7+
8+
# Virtual environments
9+
.venv/
10+
venv/
11+
env/
12+
13+
# Distribution / packaging
14+
dist/
15+
build/
16+
*.egg-info/
17+
*.egg
18+
19+
# uv
20+
.uv/
21+
22+
# pytest
23+
.pytest_cache/
24+
.coverage
25+
htmlcov/
26+
27+
# mypy
28+
.mypy_cache/
29+
30+
# ruff
31+
.ruff_cache/
32+
33+
# macOS
34+
.DS_Store
35+
36+
# Editors
37+
.idea/
38+
.vscode/
39+
*.swp
40+
*.swo

0 commit comments

Comments
 (0)