pydocket 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of pydocket might be problematic. Click here for more details.
- docket/__init__.py +2 -0
- docket/dependencies.py +28 -0
- docket/instrumentation.py +6 -0
- docket/worker.py +38 -1
- {pydocket-0.2.1.dist-info → pydocket-0.3.0.dist-info}/METADATA +1 -1
- pydocket-0.3.0.dist-info/RECORD +16 -0
- pydocket-0.2.1.dist-info/RECORD +0 -16
- {pydocket-0.2.1.dist-info → pydocket-0.3.0.dist-info}/WHEEL +0 -0
- {pydocket-0.2.1.dist-info → pydocket-0.3.0.dist-info}/entry_points.txt +0 -0
- {pydocket-0.2.1.dist-info → pydocket-0.3.0.dist-info}/licenses/LICENSE +0 -0
docket/__init__.py
CHANGED
|
@@ -14,6 +14,7 @@ from .dependencies import (
|
|
|
14
14
|
CurrentExecution,
|
|
15
15
|
CurrentWorker,
|
|
16
16
|
ExponentialRetry,
|
|
17
|
+
Perpetual,
|
|
17
18
|
Retry,
|
|
18
19
|
TaskKey,
|
|
19
20
|
TaskLogger,
|
|
@@ -34,5 +35,6 @@ __all__ = [
|
|
|
34
35
|
"Retry",
|
|
35
36
|
"ExponentialRetry",
|
|
36
37
|
"Logged",
|
|
38
|
+
"Perpetual",
|
|
37
39
|
"__version__",
|
|
38
40
|
]
|
docket/dependencies.py
CHANGED
|
@@ -126,6 +126,34 @@ class ExponentialRetry(Retry):
|
|
|
126
126
|
return retry
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
class Perpetual(Dependency):
|
|
130
|
+
single = True
|
|
131
|
+
|
|
132
|
+
every: timedelta
|
|
133
|
+
args: tuple[Any, ...]
|
|
134
|
+
kwargs: dict[str, Any]
|
|
135
|
+
cancelled: bool
|
|
136
|
+
|
|
137
|
+
def __init__(self, every: timedelta = timedelta(0)) -> None:
|
|
138
|
+
self.every = every
|
|
139
|
+
self.cancelled = False
|
|
140
|
+
|
|
141
|
+
def __call__(
|
|
142
|
+
self, docket: Docket, worker: Worker, execution: Execution
|
|
143
|
+
) -> "Perpetual":
|
|
144
|
+
perpetual = Perpetual(every=self.every)
|
|
145
|
+
perpetual.args = execution.args
|
|
146
|
+
perpetual.kwargs = execution.kwargs
|
|
147
|
+
return perpetual
|
|
148
|
+
|
|
149
|
+
def cancel(self) -> None:
|
|
150
|
+
self.cancelled = True
|
|
151
|
+
|
|
152
|
+
def perpetuate(self, *args: Any, **kwargs: Any) -> None:
|
|
153
|
+
self.args = args
|
|
154
|
+
self.kwargs = kwargs
|
|
155
|
+
|
|
156
|
+
|
|
129
157
|
def get_dependency_parameters(
|
|
130
158
|
function: Callable[..., Awaitable[Any]],
|
|
131
159
|
) -> dict[str, Dependency]:
|
docket/instrumentation.py
CHANGED
|
@@ -70,6 +70,12 @@ TASKS_RETRIED = meter.create_counter(
|
|
|
70
70
|
unit="1",
|
|
71
71
|
)
|
|
72
72
|
|
|
73
|
+
TASKS_PERPETUATED = meter.create_counter(
|
|
74
|
+
"docket_tasks_perpetuated",
|
|
75
|
+
description="How many tasks that have been self-perpetuated",
|
|
76
|
+
unit="1",
|
|
77
|
+
)
|
|
78
|
+
|
|
73
79
|
TASK_DURATION = meter.create_histogram(
|
|
74
80
|
"docket_task_duration",
|
|
75
81
|
description="How long tasks take to complete",
|
docket/worker.py
CHANGED
|
@@ -36,6 +36,7 @@ from .instrumentation import (
|
|
|
36
36
|
TASK_PUNCTUALITY,
|
|
37
37
|
TASKS_COMPLETED,
|
|
38
38
|
TASKS_FAILED,
|
|
39
|
+
TASKS_PERPETUATED,
|
|
39
40
|
TASKS_RETRIED,
|
|
40
41
|
TASKS_RUNNING,
|
|
41
42
|
TASKS_STARTED,
|
|
@@ -424,12 +425,20 @@ class Worker:
|
|
|
424
425
|
TASKS_SUCCEEDED.add(1, counter_labels)
|
|
425
426
|
duration = datetime.now(timezone.utc) - start
|
|
426
427
|
log_context["duration"] = duration.total_seconds()
|
|
427
|
-
|
|
428
|
+
rescheduled = await self._perpetuate_if_requested(
|
|
429
|
+
execution, dependencies, duration
|
|
430
|
+
)
|
|
431
|
+
arrow = "↫" if rescheduled else "↩"
|
|
432
|
+
logger.info("%s [%s] %s", arrow, duration, call, extra=log_context)
|
|
428
433
|
except Exception:
|
|
429
434
|
TASKS_FAILED.add(1, counter_labels)
|
|
430
435
|
duration = datetime.now(timezone.utc) - start
|
|
431
436
|
log_context["duration"] = duration.total_seconds()
|
|
432
437
|
retried = await self._retry_if_requested(execution, dependencies)
|
|
438
|
+
if not retried:
|
|
439
|
+
retried = await self._perpetuate_if_requested(
|
|
440
|
+
execution, dependencies, duration
|
|
441
|
+
)
|
|
433
442
|
arrow = "↫" if retried else "↩"
|
|
434
443
|
logger.exception("%s [%s] %s", arrow, duration, call, extra=log_context)
|
|
435
444
|
finally:
|
|
@@ -481,6 +490,34 @@ class Worker:
|
|
|
481
490
|
|
|
482
491
|
return False
|
|
483
492
|
|
|
493
|
+
async def _perpetuate_if_requested(
|
|
494
|
+
self, execution: Execution, dependencies: dict[str, Any], duration: timedelta
|
|
495
|
+
) -> bool:
|
|
496
|
+
from .dependencies import Perpetual
|
|
497
|
+
|
|
498
|
+
perpetuals = [
|
|
499
|
+
perpetual
|
|
500
|
+
for perpetual in dependencies.values()
|
|
501
|
+
if isinstance(perpetual, Perpetual)
|
|
502
|
+
]
|
|
503
|
+
if not perpetuals:
|
|
504
|
+
return False
|
|
505
|
+
|
|
506
|
+
perpetual = perpetuals[0]
|
|
507
|
+
|
|
508
|
+
if perpetual.cancelled:
|
|
509
|
+
return False
|
|
510
|
+
|
|
511
|
+
now = datetime.now(timezone.utc)
|
|
512
|
+
execution.when = max(now, now + perpetual.every - duration)
|
|
513
|
+
execution.args = perpetual.args
|
|
514
|
+
execution.kwargs = perpetual.kwargs
|
|
515
|
+
|
|
516
|
+
await self.docket.schedule(execution)
|
|
517
|
+
|
|
518
|
+
TASKS_PERPETUATED.add(1, {**self.labels(), **execution.specific_labels()})
|
|
519
|
+
return True
|
|
520
|
+
|
|
484
521
|
@property
|
|
485
522
|
def workers_set(self) -> str:
|
|
486
523
|
return self.docket.workers_set
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydocket
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A distributed background task system for Python functions
|
|
5
5
|
Project-URL: Homepage, https://github.com/chrisguidry/docket
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/chrisguidry/docket/issues
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
docket/__init__.py,sha256=7oruGALDoU6W_ntF-mMxxv3FFtO970DVzj3lUgoVIiM,775
|
|
2
|
+
docket/__main__.py,sha256=Vkuh7aJ-Bl7QVpVbbkUksAd_hn05FiLmWbc-8kbhZQ4,34
|
|
3
|
+
docket/annotations.py,sha256=GZwOPtPXyeIhnsLh3TQMBnXrjtTtSmF4Ratv4vjPx8U,950
|
|
4
|
+
docket/cli.py,sha256=EseF0Sj7IEgd9QDC-FSbHSffvF7DNsrmDGYGgZBdJc8,19413
|
|
5
|
+
docket/dependencies.py,sha256=S3KqXxEF0Q2t_jO3R-kI5IIA3M-tqybtiSod2xnRO4o,4991
|
|
6
|
+
docket/docket.py,sha256=zva6ofTm7i5hRwAaAnNtlgIqoMPaNLqCTs2PXGka_8s,19723
|
|
7
|
+
docket/execution.py,sha256=ShP8MoLmxEslk2pAuhKi6KEEKbHdneyQukR9oQwXdjQ,11732
|
|
8
|
+
docket/instrumentation.py,sha256=bZlGA02JoJcY0J1WGm5_qXDfY0AXKr0ZLAYu67wkeKY,4611
|
|
9
|
+
docket/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
docket/tasks.py,sha256=RIlSM2omh-YDwVnCz6M5MtmK8T_m_s1w2OlRRxDUs6A,1437
|
|
11
|
+
docket/worker.py,sha256=A0jfi6f2QZ2OA5z9rVvEcstSiIAQPrxaJmKkFBHH48g,21752
|
|
12
|
+
pydocket-0.3.0.dist-info/METADATA,sha256=O6NoNE03rUVEMokkKArLaH6_sXhnrx-kWTnVBN8h5Ak,13092
|
|
13
|
+
pydocket-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
+
pydocket-0.3.0.dist-info/entry_points.txt,sha256=4WOk1nUlBsUT5O3RyMci2ImuC5XFswuopElYcLHtD5k,47
|
|
15
|
+
pydocket-0.3.0.dist-info/licenses/LICENSE,sha256=YuVWU_ZXO0K_k2FG8xWKe5RGxV24AhJKTvQmKfqXuyk,1087
|
|
16
|
+
pydocket-0.3.0.dist-info/RECORD,,
|
pydocket-0.2.1.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
docket/__init__.py,sha256=GoJYpyuO6QFeBB8GNaxGGvMMuai55Eaw_8u-o1PM3hk,743
|
|
2
|
-
docket/__main__.py,sha256=Vkuh7aJ-Bl7QVpVbbkUksAd_hn05FiLmWbc-8kbhZQ4,34
|
|
3
|
-
docket/annotations.py,sha256=GZwOPtPXyeIhnsLh3TQMBnXrjtTtSmF4Ratv4vjPx8U,950
|
|
4
|
-
docket/cli.py,sha256=EseF0Sj7IEgd9QDC-FSbHSffvF7DNsrmDGYGgZBdJc8,19413
|
|
5
|
-
docket/dependencies.py,sha256=gIDwcBUhrLk7xGh0ZxdqpsnSeX-hZzGMNvUrVFfqbJI,4281
|
|
6
|
-
docket/docket.py,sha256=zva6ofTm7i5hRwAaAnNtlgIqoMPaNLqCTs2PXGka_8s,19723
|
|
7
|
-
docket/execution.py,sha256=ShP8MoLmxEslk2pAuhKi6KEEKbHdneyQukR9oQwXdjQ,11732
|
|
8
|
-
docket/instrumentation.py,sha256=SUVhVFf8AX2HAfmi0HPTT_QvQezlGPJEKs_1YAmrCbA,4454
|
|
9
|
-
docket/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
docket/tasks.py,sha256=RIlSM2omh-YDwVnCz6M5MtmK8T_m_s1w2OlRRxDUs6A,1437
|
|
11
|
-
docket/worker.py,sha256=DH15hW8QBGHaZdOdkpH7bjYtLEydi4sGh-Ei8lEXGOo,20556
|
|
12
|
-
pydocket-0.2.1.dist-info/METADATA,sha256=9DxwXrPzeTCOlxDGn9JUOzQN-k6OjhAJbiRPeMhcNNo,13092
|
|
13
|
-
pydocket-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
-
pydocket-0.2.1.dist-info/entry_points.txt,sha256=4WOk1nUlBsUT5O3RyMci2ImuC5XFswuopElYcLHtD5k,47
|
|
15
|
-
pydocket-0.2.1.dist-info/licenses/LICENSE,sha256=YuVWU_ZXO0K_k2FG8xWKe5RGxV24AhJKTvQmKfqXuyk,1087
|
|
16
|
-
pydocket-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|