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 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
- logger.info("%s [%s] %s", "↩", duration, call, extra=log_context)
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.2.1
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,,
@@ -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,,