python-pq 0.5.1__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_pq-0.5.1 → python_pq-0.5.2}/PKG-INFO +15 -1
- {python_pq-0.5.1 → python_pq-0.5.2}/README.md +14 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/pyproject.toml +1 -1
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/__init__.py +1 -1
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/client.py +5 -0
- python_pq-0.5.2/src/pq/migrations/versions/20260217T120000Z_c3d4e5f6a7b8_add_periodic_active.py +32 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/models.py +2 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/worker.py +1 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/config.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/logging.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/README +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/__init__.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/env.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/script.py.mako +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/versions/20260109T055839Z_476683af098d_initial_schema.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/versions/20260109T063747Z_2483bec70083_add_client_id.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/versions/20260205T120000Z_a1b2c3d4e5f6_add_max_concurrent.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/versions/20260205T180000Z_b7c8d9e0f1a2_add_periodic_key.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/migrations/versions/__init__.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/priority.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/registry.py +0 -0
- {python_pq-0.5.1 → python_pq-0.5.2}/src/pq/serialization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python-pq
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Postgres-backed job queue for Python
|
|
5
5
|
Author: ricwo
|
|
6
6
|
Author-email: ricwo <r@cogram.com>
|
|
@@ -166,6 +166,20 @@ pq.schedule(fast_idempotent_task, run_every=timedelta(seconds=30), max_concurren
|
|
|
166
166
|
|
|
167
167
|
The lock auto-expires after `max_runtime` seconds (or 1 hour by default) for crash safety.
|
|
168
168
|
|
|
169
|
+
### Pausing & Resuming
|
|
170
|
+
|
|
171
|
+
Disable a periodic task without removing it:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# Pause - task stays in the database but won't run
|
|
175
|
+
pq.schedule(sync_inventory, run_every=timedelta(minutes=5), active=False)
|
|
176
|
+
|
|
177
|
+
# Resume
|
|
178
|
+
pq.schedule(sync_inventory, run_every=timedelta(minutes=5), active=True)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
New schedules are active by default.
|
|
182
|
+
|
|
169
183
|
### Multiple Schedules (Key)
|
|
170
184
|
|
|
171
185
|
Use `key` to register the same function multiple times with different configurations:
|
|
@@ -145,6 +145,20 @@ pq.schedule(fast_idempotent_task, run_every=timedelta(seconds=30), max_concurren
|
|
|
145
145
|
|
|
146
146
|
The lock auto-expires after `max_runtime` seconds (or 1 hour by default) for crash safety.
|
|
147
147
|
|
|
148
|
+
### Pausing & Resuming
|
|
149
|
+
|
|
150
|
+
Disable a periodic task without removing it:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# Pause - task stays in the database but won't run
|
|
154
|
+
pq.schedule(sync_inventory, run_every=timedelta(minutes=5), active=False)
|
|
155
|
+
|
|
156
|
+
# Resume
|
|
157
|
+
pq.schedule(sync_inventory, run_every=timedelta(minutes=5), active=True)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
New schedules are active by default.
|
|
161
|
+
|
|
148
162
|
### Multiple Schedules (Key)
|
|
149
163
|
|
|
150
164
|
Use `key` to register the same function multiple times with different configurations:
|
|
@@ -237,6 +237,7 @@ class PQ:
|
|
|
237
237
|
client_id: str | None = None,
|
|
238
238
|
max_concurrent: int | None = 1,
|
|
239
239
|
key: str = "",
|
|
240
|
+
active: bool = True,
|
|
240
241
|
**kwargs: Any,
|
|
241
242
|
) -> int:
|
|
242
243
|
"""Schedule a periodic task.
|
|
@@ -256,6 +257,8 @@ class PQ:
|
|
|
256
257
|
for future use and raise ValueError.
|
|
257
258
|
key: Discriminator for multiple schedules of the same function.
|
|
258
259
|
Defaults to "" (empty string).
|
|
260
|
+
active: Whether the task is active. Inactive tasks are not executed.
|
|
261
|
+
Defaults to True.
|
|
259
262
|
**kwargs: Keyword arguments to pass to the handler.
|
|
260
263
|
|
|
261
264
|
Returns:
|
|
@@ -316,6 +319,7 @@ class PQ:
|
|
|
316
319
|
next_run=next_run,
|
|
317
320
|
client_id=client_id,
|
|
318
321
|
max_concurrent=max_concurrent,
|
|
322
|
+
active=active,
|
|
319
323
|
)
|
|
320
324
|
.on_conflict_do_update(
|
|
321
325
|
index_elements=["name", "key"],
|
|
@@ -326,6 +330,7 @@ class PQ:
|
|
|
326
330
|
"cron": cron_expr,
|
|
327
331
|
"next_run": next_run,
|
|
328
332
|
"max_concurrent": max_concurrent,
|
|
333
|
+
"active": active,
|
|
329
334
|
},
|
|
330
335
|
)
|
|
331
336
|
.returning(Periodic.id)
|
python_pq-0.5.2/src/pq/migrations/versions/20260217T120000Z_c3d4e5f6a7b8_add_periodic_active.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""add periodic active
|
|
2
|
+
|
|
3
|
+
Revision ID: c3d4e5f6a7b8
|
|
4
|
+
Revises: b7c8d9e0f1a2
|
|
5
|
+
Create Date: 2026-02-17 12:00:00 Z
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Sequence, Union
|
|
10
|
+
|
|
11
|
+
from alembic import op
|
|
12
|
+
import sqlalchemy as sa
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# revision identifiers, used by Alembic.
|
|
16
|
+
revision: str = "c3d4e5f6a7b8"
|
|
17
|
+
down_revision: Union[str, Sequence[str], None] = "b7c8d9e0f1a2"
|
|
18
|
+
branch_labels: Union[str, Sequence[str], None] = None
|
|
19
|
+
depends_on: Union[str, Sequence[str], None] = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def upgrade() -> None:
|
|
23
|
+
"""Add active column to pq_periodic."""
|
|
24
|
+
op.add_column(
|
|
25
|
+
"pq_periodic",
|
|
26
|
+
sa.Column("active", sa.Boolean(), nullable=False, server_default="true"),
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def downgrade() -> None:
|
|
31
|
+
"""Remove active column from pq_periodic."""
|
|
32
|
+
op.drop_column("pq_periodic", "active")
|
|
@@ -6,6 +6,7 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
from sqlalchemy import (
|
|
8
8
|
BigInteger,
|
|
9
|
+
Boolean,
|
|
9
10
|
DateTime,
|
|
10
11
|
Enum,
|
|
11
12
|
Identity,
|
|
@@ -92,6 +93,7 @@ class Periodic(Base):
|
|
|
92
93
|
cron: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
93
94
|
next_run: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
|
94
95
|
max_concurrent: Mapped[int | None] = mapped_column(SmallInteger, nullable=True)
|
|
96
|
+
active: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default="true")
|
|
95
97
|
last_run: Mapped[datetime | None] = mapped_column(
|
|
96
98
|
DateTime(timezone=True), nullable=True
|
|
97
99
|
)
|
|
@@ -560,6 +560,7 @@ def _process_periodic_task(
|
|
|
560
560
|
# Claim highest priority due periodic task with FOR UPDATE SKIP LOCKED
|
|
561
561
|
# Filter out tasks that are locked (max_concurrent=1 and locked_until in future)
|
|
562
562
|
stmt = select(Periodic).where(
|
|
563
|
+
Periodic.active.is_(True),
|
|
563
564
|
Periodic.next_run <= func.now(),
|
|
564
565
|
or_(
|
|
565
566
|
Periodic.max_concurrent.is_(None),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|