ddeutil-workflow 0.0.62__py3-none-any.whl → 0.0.64__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.
- ddeutil/workflow/__about__.py +1 -1
- ddeutil/workflow/__init__.py +2 -31
- ddeutil/workflow/api/__init__.py +5 -84
- ddeutil/workflow/api/routes/__init__.py +0 -1
- ddeutil/workflow/api/routes/job.py +0 -1
- ddeutil/workflow/api/routes/logs.py +0 -2
- ddeutil/workflow/api/routes/workflows.py +0 -3
- ddeutil/workflow/conf.py +40 -36
- ddeutil/workflow/event.py +2 -1
- ddeutil/workflow/exceptions.py +0 -3
- ddeutil/workflow/reusables.py +104 -14
- ddeutil/workflow/stages.py +60 -52
- ddeutil/workflow/utils.py +4 -2
- {ddeutil_workflow-0.0.62.dist-info → ddeutil_workflow-0.0.64.dist-info}/METADATA +11 -57
- ddeutil_workflow-0.0.64.dist-info/RECORD +28 -0
- ddeutil/workflow/api/routes/schedules.py +0 -141
- ddeutil/workflow/api/utils.py +0 -174
- ddeutil/workflow/scheduler.py +0 -813
- ddeutil_workflow-0.0.62.dist-info/RECORD +0 -31
- {ddeutil_workflow-0.0.62.dist-info → ddeutil_workflow-0.0.64.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.62.dist-info → ddeutil_workflow-0.0.64.dist-info}/entry_points.txt +0 -0
- {ddeutil_workflow-0.0.62.dist-info → ddeutil_workflow-0.0.64.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.62.dist-info → ddeutil_workflow-0.0.64.dist-info}/top_level.txt +0 -0
ddeutil/workflow/api/utils.py
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
# ------------------------------------------------------------------------------
|
2
|
-
# Copyright (c) 2023 Priyanshu Panwar. All rights reserved.
|
3
|
-
# Licensed under the MIT License.
|
4
|
-
# This code refs from: https://github.com/priyanshu-panwar/fastapi-utilities
|
5
|
-
# ------------------------------------------------------------------------------
|
6
|
-
from __future__ import annotations
|
7
|
-
|
8
|
-
import asyncio
|
9
|
-
from asyncio import ensure_future
|
10
|
-
from datetime import datetime
|
11
|
-
from functools import wraps
|
12
|
-
|
13
|
-
from starlette.concurrency import run_in_threadpool
|
14
|
-
|
15
|
-
from ..__cron import CronJob
|
16
|
-
from ..conf import config
|
17
|
-
from ..logs import get_logger
|
18
|
-
|
19
|
-
logger = get_logger("uvicorn.error")
|
20
|
-
|
21
|
-
|
22
|
-
def get_cronjob_delta(cron: str) -> float:
|
23
|
-
"""This function returns the time delta between now and the next cron
|
24
|
-
execution time.
|
25
|
-
|
26
|
-
:rtype: float
|
27
|
-
"""
|
28
|
-
now: datetime = datetime.now(tz=config.tz)
|
29
|
-
cron = CronJob(cron)
|
30
|
-
return (cron.schedule(now).next - now).total_seconds()
|
31
|
-
|
32
|
-
|
33
|
-
def cron_valid(cron: str, raise_error: bool = True) -> bool:
|
34
|
-
"""Check this crontab string value is valid with its cron syntax.
|
35
|
-
|
36
|
-
:rtype: bool
|
37
|
-
"""
|
38
|
-
try:
|
39
|
-
CronJob(cron)
|
40
|
-
return True
|
41
|
-
except Exception as err:
|
42
|
-
if raise_error:
|
43
|
-
raise ValueError(f"Crontab value does not valid, {cron}") from err
|
44
|
-
return False
|
45
|
-
|
46
|
-
|
47
|
-
async def run_func(
|
48
|
-
is_coroutine,
|
49
|
-
func,
|
50
|
-
*args,
|
51
|
-
raise_exceptions: bool = False,
|
52
|
-
**kwargs,
|
53
|
-
):
|
54
|
-
"""Run function inside the repeat decorator functions."""
|
55
|
-
try:
|
56
|
-
if is_coroutine:
|
57
|
-
await func(*args, **kwargs)
|
58
|
-
else:
|
59
|
-
await run_in_threadpool(func, *args, **kwargs)
|
60
|
-
except Exception as e:
|
61
|
-
logger.exception(e)
|
62
|
-
if raise_exceptions:
|
63
|
-
raise e
|
64
|
-
|
65
|
-
|
66
|
-
def repeat_at(
|
67
|
-
*,
|
68
|
-
cron: str,
|
69
|
-
delay: float = 0,
|
70
|
-
raise_exceptions: bool = False,
|
71
|
-
max_repetitions: int = None,
|
72
|
-
):
|
73
|
-
"""This function returns a decorator that makes a function execute
|
74
|
-
periodically as per the cron expression provided.
|
75
|
-
|
76
|
-
:param cron: (str) A Cron-style string for periodic execution, e.g.
|
77
|
-
'0 0 * * *' every midnight
|
78
|
-
:param delay: (float) A delay seconds value.
|
79
|
-
:param raise_exceptions: (bool) A raise exception flag. Whether to raise
|
80
|
-
exceptions or log them if raise was set be false.
|
81
|
-
:param max_repetitions: int (default None)
|
82
|
-
Maximum number of times to repeat the function. If None, repeat
|
83
|
-
indefinitely.
|
84
|
-
"""
|
85
|
-
if max_repetitions and max_repetitions <= 0:
|
86
|
-
raise ValueError(
|
87
|
-
"max_repetitions should more than zero if it want to set"
|
88
|
-
)
|
89
|
-
|
90
|
-
def decorator(func):
|
91
|
-
is_coroutine: bool = asyncio.iscoroutinefunction(func)
|
92
|
-
|
93
|
-
@wraps(func)
|
94
|
-
def wrapper(*_args, **_kwargs):
|
95
|
-
repetitions: int = 0
|
96
|
-
cron_valid(cron)
|
97
|
-
|
98
|
-
async def loop(*args, **kwargs):
|
99
|
-
nonlocal repetitions
|
100
|
-
while max_repetitions is None or repetitions < max_repetitions:
|
101
|
-
sleep_time = get_cronjob_delta(cron) + delay
|
102
|
-
await asyncio.sleep(sleep_time)
|
103
|
-
await run_func(
|
104
|
-
is_coroutine,
|
105
|
-
func,
|
106
|
-
*args,
|
107
|
-
raise_exceptions=raise_exceptions,
|
108
|
-
**kwargs,
|
109
|
-
)
|
110
|
-
repetitions += 1
|
111
|
-
|
112
|
-
ensure_future(loop(*_args, **_kwargs))
|
113
|
-
|
114
|
-
return wrapper
|
115
|
-
|
116
|
-
return decorator
|
117
|
-
|
118
|
-
|
119
|
-
def repeat_every(
|
120
|
-
*,
|
121
|
-
seconds: float,
|
122
|
-
wait_first: bool = False,
|
123
|
-
raise_exceptions: bool = False,
|
124
|
-
max_repetitions: int = None,
|
125
|
-
):
|
126
|
-
"""This function returns a decorator that schedules a function to execute
|
127
|
-
periodically after every `seconds` seconds.
|
128
|
-
|
129
|
-
:param seconds: float
|
130
|
-
The number of seconds to wait before executing the function again.
|
131
|
-
:param wait_first: bool (default False)
|
132
|
-
Whether to wait `seconds` seconds before executing the function for the
|
133
|
-
first time.
|
134
|
-
:param raise_exceptions: bool (default False)
|
135
|
-
Whether to raise exceptions instead of logging them.
|
136
|
-
:param max_repetitions: int (default None)
|
137
|
-
The maximum number of times to repeat the function. If None, the
|
138
|
-
function will repeat indefinitely.
|
139
|
-
"""
|
140
|
-
if max_repetitions and max_repetitions <= 0:
|
141
|
-
raise ValueError(
|
142
|
-
"max_repetitions should more than zero if it want to set"
|
143
|
-
)
|
144
|
-
|
145
|
-
def decorator(func):
|
146
|
-
is_coroutine: bool = asyncio.iscoroutinefunction(func)
|
147
|
-
|
148
|
-
@wraps(func)
|
149
|
-
async def wrapper(*_args, **_kwargs):
|
150
|
-
repetitions = 0
|
151
|
-
|
152
|
-
async def loop(*args, **kwargs):
|
153
|
-
nonlocal repetitions
|
154
|
-
|
155
|
-
if wait_first:
|
156
|
-
await asyncio.sleep(seconds)
|
157
|
-
|
158
|
-
while max_repetitions is None or repetitions < max_repetitions:
|
159
|
-
await run_func(
|
160
|
-
is_coroutine,
|
161
|
-
func,
|
162
|
-
*args,
|
163
|
-
raise_exceptions=raise_exceptions,
|
164
|
-
**kwargs,
|
165
|
-
)
|
166
|
-
|
167
|
-
repetitions += 1
|
168
|
-
await asyncio.sleep(seconds)
|
169
|
-
|
170
|
-
ensure_future(loop(*_args, **_kwargs))
|
171
|
-
|
172
|
-
return wrapper
|
173
|
-
|
174
|
-
return decorator
|