ddeutil-workflow 0.0.8__py3-none-any.whl → 0.0.9__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 +3 -14
- ddeutil/workflow/api.py +44 -75
- ddeutil/workflow/cli.py +51 -0
- ddeutil/workflow/cron.py +713 -0
- ddeutil/workflow/loader.py +65 -13
- ddeutil/workflow/log.py +147 -49
- ddeutil/workflow/on.py +18 -15
- ddeutil/workflow/pipeline.py +389 -140
- ddeutil/workflow/repeat.py +9 -5
- ddeutil/workflow/route.py +30 -37
- ddeutil/workflow/scheduler.py +398 -659
- ddeutil/workflow/stage.py +145 -73
- ddeutil/workflow/utils.py +133 -42
- ddeutil_workflow-0.0.9.dist-info/METADATA +273 -0
- ddeutil_workflow-0.0.9.dist-info/RECORD +22 -0
- {ddeutil_workflow-0.0.8.dist-info → ddeutil_workflow-0.0.9.dist-info}/WHEEL +1 -1
- ddeutil_workflow-0.0.9.dist-info/entry_points.txt +2 -0
- ddeutil/workflow/app.py +0 -45
- ddeutil_workflow-0.0.8.dist-info/METADATA +0 -266
- ddeutil_workflow-0.0.8.dist-info/RECORD +0 -20
- {ddeutil_workflow-0.0.8.dist-info → ddeutil_workflow-0.0.9.dist-info}/LICENSE +0 -0
- {ddeutil_workflow-0.0.8.dist-info → ddeutil_workflow-0.0.9.dist-info}/top_level.txt +0 -0
ddeutil/workflow/repeat.py
CHANGED
@@ -5,19 +5,23 @@
|
|
5
5
|
# ------------------------------------------------------------------------------
|
6
6
|
import asyncio
|
7
7
|
import logging
|
8
|
+
import os
|
8
9
|
from asyncio import ensure_future
|
9
10
|
from datetime import datetime
|
10
11
|
from functools import wraps
|
12
|
+
from zoneinfo import ZoneInfo
|
11
13
|
|
12
14
|
from croniter import croniter
|
13
15
|
from starlette.concurrency import run_in_threadpool
|
14
16
|
|
15
17
|
|
16
|
-
def
|
18
|
+
def get_cron_delta(cron: str):
|
17
19
|
"""This function returns the time delta between now and the next cron
|
18
20
|
execution time.
|
19
21
|
"""
|
20
|
-
now: datetime = datetime.now(
|
22
|
+
now: datetime = datetime.now(
|
23
|
+
tz=ZoneInfo(os.getenv("WORKFLOW_CORE_TIMEZONE", "UTC"))
|
24
|
+
)
|
21
25
|
cron = croniter(cron, now)
|
22
26
|
return (cron.get_next(datetime) - now).total_seconds()
|
23
27
|
|
@@ -57,14 +61,14 @@ def repeat_at(
|
|
57
61
|
nonlocal repititions
|
58
62
|
while max_repetitions is None or repititions < max_repetitions:
|
59
63
|
try:
|
60
|
-
|
61
|
-
await asyncio.sleep(
|
64
|
+
sleep_time = get_cron_delta(cron)
|
65
|
+
await asyncio.sleep(sleep_time)
|
62
66
|
if is_coroutine:
|
63
67
|
await func(*args, **kwargs)
|
64
68
|
else:
|
65
69
|
await run_in_threadpool(func, *args, **kwargs)
|
66
70
|
except Exception as e:
|
67
|
-
if logger
|
71
|
+
if logger:
|
68
72
|
logger.exception(e)
|
69
73
|
if raise_exceptions:
|
70
74
|
raise e
|
ddeutil/workflow/route.py
CHANGED
@@ -1,62 +1,55 @@
|
|
1
|
-
from
|
1
|
+
from __future__ import annotations
|
2
2
|
|
3
|
-
from fastapi import APIRouter, Request
|
4
|
-
from
|
3
|
+
from fastapi import APIRouter, Request
|
4
|
+
from fastapi import status as st
|
5
5
|
|
6
6
|
from .log import get_logger
|
7
7
|
|
8
8
|
logger = get_logger(__name__)
|
9
|
-
|
9
|
+
workflow = APIRouter(prefix="/wf", tags=["workflow"])
|
10
10
|
|
11
11
|
|
12
|
-
@
|
13
|
-
async def
|
12
|
+
@workflow.get("/")
|
13
|
+
async def get_workflows():
|
14
|
+
return {"message": "getting all pipelines: []"}
|
15
|
+
|
16
|
+
|
17
|
+
@workflow.get("/{name}")
|
18
|
+
async def get_workflow(name: str):
|
14
19
|
return {"message": f"getting pipeline {name}"}
|
15
20
|
|
16
21
|
|
17
|
-
@
|
18
|
-
async def
|
22
|
+
@workflow.get("/{name}/logs")
|
23
|
+
async def get_workflow_logs(name: str):
|
19
24
|
return {"message": f"getting pipeline {name} logs"}
|
20
25
|
|
21
26
|
|
22
|
-
|
23
|
-
|
27
|
+
@workflow.get("/{name}/logs/{release}")
|
28
|
+
async def get_workflow_release_log(name: str, release: str):
|
29
|
+
return {"message": f"getting pipeline {name} log in release {release}"}
|
24
30
|
|
25
31
|
|
26
|
-
|
32
|
+
@workflow.delete(
|
33
|
+
"/{name}/logs/{release}",
|
34
|
+
status_code=st.HTTP_204_NO_CONTENT,
|
35
|
+
)
|
36
|
+
async def del_workflow_release_log(name: str, release: str):
|
37
|
+
return {"message": f"getting pipeline {name} log in release {release}"}
|
27
38
|
|
28
39
|
|
29
|
-
class
|
30
|
-
|
31
|
-
cron = "cron"
|
40
|
+
class JobNotFoundError(Exception):
|
41
|
+
pass
|
32
42
|
|
33
43
|
|
34
|
-
|
35
|
-
model_config = ConfigDict(
|
36
|
-
json_schema_extra={
|
37
|
-
"example": {
|
38
|
-
"func": "example.main:pytest_job",
|
39
|
-
"trigger": "interval",
|
40
|
-
"seconds": 3,
|
41
|
-
"id": "pytest_job",
|
42
|
-
},
|
43
|
-
},
|
44
|
-
)
|
45
|
-
func: str = Field()
|
46
|
-
trigger: TriggerEnum = Field(title="Trigger type")
|
47
|
-
seconds: int = Field(title="Interval in seconds")
|
48
|
-
id: str = Field(title="Job ID")
|
44
|
+
schedule = APIRouter(prefix="/schedule", tags=["schedule"])
|
49
45
|
|
50
46
|
|
51
|
-
@
|
52
|
-
|
53
|
-
|
54
|
-
async def add_job(request: Request, job: Job):
|
55
|
-
job = request.app.scheduler.add_job(**job.dict())
|
56
|
-
return {"job": f"{job.id}"}
|
47
|
+
@schedule.post("/", name="scheduler:add_job", status_code=st.HTTP_201_CREATED)
|
48
|
+
async def add_job(request: Request):
|
49
|
+
return {"job": f"{request}"}
|
57
50
|
|
58
51
|
|
59
|
-
@
|
52
|
+
@schedule.get("/", name="scheduler:get_jobs", response_model=list)
|
60
53
|
async def get_jobs(request: Request):
|
61
54
|
jobs = request.app.scheduler.get_jobs()
|
62
55
|
jobs = [
|
@@ -66,7 +59,7 @@ async def get_jobs(request: Request):
|
|
66
59
|
return jobs
|
67
60
|
|
68
61
|
|
69
|
-
@
|
62
|
+
@schedule.delete("/{job_id}", name="scheduler:remove_job")
|
70
63
|
async def remove_job(request: Request, job_id: str):
|
71
64
|
try:
|
72
65
|
deleted = request.app.scheduler.remove_job(job_id=job_id)
|