ddeutil-workflow 0.0.53__tar.gz → 0.0.55__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.
- {ddeutil_workflow-0.0.53/src/ddeutil_workflow.egg-info → ddeutil_workflow-0.0.55}/PKG-INFO +5 -13
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/README.md +4 -12
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/pyproject.toml +0 -2
- ddeutil_workflow-0.0.55/src/ddeutil/workflow/__about__.py +1 -0
- ddeutil_workflow-0.0.53/src/ddeutil/workflow/api/api.py → ddeutil_workflow-0.0.55/src/ddeutil/workflow/api/__init__.py +2 -2
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/job.py +23 -22
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/schedules.py +0 -2
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/workflows.py +3 -4
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/job.py +125 -170
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/result.py +1 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/scheduler.py +1 -3
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/stages.py +641 -399
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/utils.py +5 -4
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/workflow.py +118 -258
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55/src/ddeutil_workflow.egg-info}/PKG-INFO +5 -13
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil_workflow.egg-info/SOURCES.txt +3 -4
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_job_exec.py +119 -45
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_job_exec_strategy.py +65 -37
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_release_queue.py +6 -2
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_reusables_template.py +5 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_stage.py +1 -1
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_stage_handler_exec.py +58 -2
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_utils.py +1 -1
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow.py +3 -4
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow_exec.py +91 -82
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow_exec_job.py +27 -4
- ddeutil_workflow-0.0.53/src/ddeutil/workflow/__about__.py +0 -1
- ddeutil_workflow-0.0.53/src/ddeutil/workflow/api/__init__.py +0 -1
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/LICENSE +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/setup.cfg +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/__cron.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/__init__.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/__main__.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/__types.py +0 -0
- /ddeutil_workflow-0.0.53/src/ddeutil/workflow/api/log.py → /ddeutil_workflow-0.0.55/src/ddeutil/workflow/api/logs.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/__init__.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/logs.py +0 -0
- /ddeutil_workflow-0.0.53/src/ddeutil/workflow/api/repeat.py → /ddeutil_workflow-0.0.55/src/ddeutil/workflow/api/utils.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/conf.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/cron.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/exceptions.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/logs.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/params.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/reusables.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil_workflow.egg-info/requires.txt +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test__cron.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test__regex.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_conf.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_cron_on.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_job.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_logs_audit.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_logs_trace.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_params.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_release.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_result.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_reusables_call_tag.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_reusables_template_filter.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_schedule.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_schedule_pending.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_schedule_tasks.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_schedule_workflow.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_scheduler_control.py +0 -0
- /ddeutil_workflow-0.0.53/tests/test_job_strategy.py → /ddeutil_workflow-0.0.55/tests/test_strategy.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow_exec_poke.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow_exec_release.py +0 -0
- {ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/tests/test_workflow_task.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ddeutil-workflow
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.55
|
4
4
|
Summary: Lightweight workflow orchestration
|
5
5
|
Author-email: ddeutils <korawich.anu@gmail.com>
|
6
6
|
License: MIT
|
@@ -62,12 +62,6 @@ by a `.yaml` template.
|
|
62
62
|
> use the workflow stage to process any large volume data which use a lot of compute
|
63
63
|
> resource :cold_sweat:.
|
64
64
|
|
65
|
-
In my opinion, I think it should not create duplicate workflow codes if I can
|
66
|
-
write with dynamic input parameters on the one template workflow that just change
|
67
|
-
the input parameters per use-case instead.
|
68
|
-
This way I can handle a lot of logical workflows in our orgs with only metadata
|
69
|
-
configuration. It called **Metadata Driven Data Workflow**.
|
70
|
-
|
71
65
|
---
|
72
66
|
|
73
67
|
**:pushpin: <u>Rules of This Workflow engine</u>**:
|
@@ -127,12 +121,10 @@ flowchart LR
|
|
127
121
|
|
128
122
|
> [!WARNING]
|
129
123
|
> _**Disclaimer**_: I inspire the dynamic YAML statement from the [**GitHub Action**](https://github.com/features/actions),
|
130
|
-
> and
|
131
|
-
>
|
132
|
-
|
133
|
-
>
|
134
|
-
> Other workflow orchestration tools that I interest and pick them to be inspiration
|
135
|
-
> some for this package:
|
124
|
+
> and my experience of data framework configs pattern. :grimacing:
|
125
|
+
>
|
126
|
+
> Other workflow orchestration services that I interest and pick them to be
|
127
|
+
> this project inspiration:
|
136
128
|
>
|
137
129
|
> - [Google **Workflows**](https://cloud.google.com/workflows)
|
138
130
|
> - [AWS **Step Functions**](https://aws.amazon.com/step-functions/)
|
@@ -17,12 +17,6 @@ by a `.yaml` template.
|
|
17
17
|
> use the workflow stage to process any large volume data which use a lot of compute
|
18
18
|
> resource :cold_sweat:.
|
19
19
|
|
20
|
-
In my opinion, I think it should not create duplicate workflow codes if I can
|
21
|
-
write with dynamic input parameters on the one template workflow that just change
|
22
|
-
the input parameters per use-case instead.
|
23
|
-
This way I can handle a lot of logical workflows in our orgs with only metadata
|
24
|
-
configuration. It called **Metadata Driven Data Workflow**.
|
25
|
-
|
26
20
|
---
|
27
21
|
|
28
22
|
**:pushpin: <u>Rules of This Workflow engine</u>**:
|
@@ -82,12 +76,10 @@ flowchart LR
|
|
82
76
|
|
83
77
|
> [!WARNING]
|
84
78
|
> _**Disclaimer**_: I inspire the dynamic YAML statement from the [**GitHub Action**](https://github.com/features/actions),
|
85
|
-
> and
|
86
|
-
>
|
87
|
-
|
88
|
-
>
|
89
|
-
> Other workflow orchestration tools that I interest and pick them to be inspiration
|
90
|
-
> some for this package:
|
79
|
+
> and my experience of data framework configs pattern. :grimacing:
|
80
|
+
>
|
81
|
+
> Other workflow orchestration services that I interest and pick them to be
|
82
|
+
> this project inspiration:
|
91
83
|
>
|
92
84
|
> - [Google **Workflows**](https://cloud.google.com/workflows)
|
93
85
|
> - [AWS **Step Functions**](https://aws.amazon.com/step-functions/)
|
@@ -79,9 +79,7 @@ source = ["src.ddeutil.workflow"]
|
|
79
79
|
omit = [
|
80
80
|
"src/ddeutil/workflow/__about__.py",
|
81
81
|
"src/ddeutil/workflow/__cron.py",
|
82
|
-
"src/ddeutil/workflow/context.py",
|
83
82
|
"src/ddeutil/workflow/api/__init__.py",
|
84
|
-
"src/ddeutil/workflow/api/api.py",
|
85
83
|
"src/ddeutil/workflow/api/log.py",
|
86
84
|
"src/ddeutil/workflow/api/repeat.py",
|
87
85
|
"src/ddeutil/workflow/api/routes/__init__.py",
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__: str = "0.0.55"
|
@@ -24,8 +24,8 @@ from ..conf import api_config, config
|
|
24
24
|
from ..logs import get_logger
|
25
25
|
from ..scheduler import ReleaseThread, ReleaseThreads
|
26
26
|
from ..workflow import ReleaseQueue, WorkflowTask
|
27
|
-
from .repeat import repeat_at
|
28
27
|
from .routes import job, log
|
28
|
+
from .utils import repeat_at
|
29
29
|
|
30
30
|
load_dotenv()
|
31
31
|
logger = get_logger("uvicorn.error")
|
@@ -90,7 +90,7 @@ app.add_middleware(
|
|
90
90
|
)
|
91
91
|
|
92
92
|
|
93
|
-
@app.get("/")
|
93
|
+
@app.get(path="/", response_class=UJSONResponse)
|
94
94
|
async def health():
|
95
95
|
"""Index view that not return any template without json status."""
|
96
96
|
return {"message": "Workflow already start up with healthy status."}
|
@@ -9,7 +9,7 @@ from typing import Any, Optional
|
|
9
9
|
|
10
10
|
from fastapi import APIRouter
|
11
11
|
from fastapi.responses import UJSONResponse
|
12
|
-
from pydantic import BaseModel
|
12
|
+
from pydantic import BaseModel, Field
|
13
13
|
|
14
14
|
from ...__types import DictData
|
15
15
|
from ...exceptions import JobException
|
@@ -18,33 +18,37 @@ from ...logs import get_logger
|
|
18
18
|
from ...result import Result
|
19
19
|
|
20
20
|
logger = get_logger("uvicorn.error")
|
21
|
+
job_route = APIRouter(prefix="/job", tags=["job"])
|
21
22
|
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
)
|
24
|
+
class ResultCreate(BaseModel):
|
25
|
+
"""Create Result model for receive running IDs to create the Result
|
26
|
+
dataclass.
|
27
|
+
"""
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
parent_run_id: Optional[str] = None
|
29
|
+
run_id: str = Field(description="A running ID.")
|
30
|
+
parent_run_id: Optional[str] = Field(
|
31
|
+
default=None, description="A parent running ID."
|
32
|
+
)
|
34
33
|
|
35
34
|
|
36
|
-
@job_route.post(path="/execute/")
|
35
|
+
@job_route.post(path="/execute/", response_class=UJSONResponse)
|
37
36
|
async def job_execute(
|
38
|
-
result:
|
37
|
+
result: ResultCreate,
|
39
38
|
job: Job,
|
40
39
|
params: dict[str, Any],
|
40
|
+
extras: Optional[dict[str, Any]] = None,
|
41
41
|
):
|
42
|
-
"""Execute job via
|
42
|
+
"""Execute job via RestAPI with execute route path."""
|
43
43
|
rs: Result = Result(
|
44
|
-
context=result.context,
|
45
44
|
run_id=result.run_id,
|
46
45
|
parent_run_id=result.parent_run_id,
|
46
|
+
extras=extras or {},
|
47
47
|
)
|
48
|
+
|
49
|
+
if extras:
|
50
|
+
job.extras = extras
|
51
|
+
|
48
52
|
context: DictData = {}
|
49
53
|
try:
|
50
54
|
job.set_outputs(
|
@@ -56,17 +60,14 @@ async def job_execute(
|
|
56
60
|
to=context,
|
57
61
|
)
|
58
62
|
except JobException as err:
|
59
|
-
rs.trace.error(f"[
|
63
|
+
rs.trace.error(f"[JOB]: {err.__class__.__name__}: {err}")
|
60
64
|
|
61
65
|
return {
|
62
|
-
"message": "
|
63
|
-
"result": {
|
64
|
-
"run_id": rs.run_id,
|
65
|
-
"parent_run_id": rs.parent_run_id,
|
66
|
-
},
|
66
|
+
"message": "Execute job via RestAPI.",
|
67
|
+
"result": {"run_id": rs.run_id, "parent_run_id": rs.parent_run_id},
|
67
68
|
"job": job.model_dump(
|
68
69
|
by_alias=True,
|
69
|
-
exclude_none=
|
70
|
+
exclude_none=False,
|
70
71
|
exclude_unset=True,
|
71
72
|
exclude_defaults=True,
|
72
73
|
),
|
{ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/schedules.py
RENAMED
@@ -17,7 +17,6 @@ from ...logs import get_logger
|
|
17
17
|
from ...scheduler import Schedule
|
18
18
|
|
19
19
|
logger = get_logger("uvicorn.error")
|
20
|
-
|
21
20
|
schedule_route = APIRouter(
|
22
21
|
prefix="/schedules",
|
23
22
|
tags=["schedules"],
|
@@ -108,7 +107,6 @@ async def add_deploy_scheduler(request: Request, name: str):
|
|
108
107
|
schedule.tasks(
|
109
108
|
start_date_waiting,
|
110
109
|
queue=request.state.workflow_queue,
|
111
|
-
extras={},
|
112
110
|
),
|
113
111
|
)
|
114
112
|
return {
|
{ddeutil_workflow-0.0.53 → ddeutil_workflow-0.0.55}/src/ddeutil/workflow/api/routes/workflows.py
RENAMED
@@ -21,7 +21,6 @@ from ...result import Result
|
|
21
21
|
from ...workflow import Workflow
|
22
22
|
|
23
23
|
logger = get_logger("uvicorn.error")
|
24
|
-
|
25
24
|
workflow_route = APIRouter(
|
26
25
|
prefix="/workflows",
|
27
26
|
tags=["workflows"],
|
@@ -55,7 +54,7 @@ async def get_workflow_by_name(name: str) -> DictData:
|
|
55
54
|
) from None
|
56
55
|
return workflow.model_dump(
|
57
56
|
by_alias=True,
|
58
|
-
exclude_none=
|
57
|
+
exclude_none=False,
|
59
58
|
exclude_unset=True,
|
60
59
|
exclude_defaults=True,
|
61
60
|
)
|
@@ -98,7 +97,7 @@ async def get_workflow_audits(name: str):
|
|
98
97
|
"audits": [
|
99
98
|
audit.model_dump(
|
100
99
|
by_alias=True,
|
101
|
-
exclude_none=
|
100
|
+
exclude_none=False,
|
102
101
|
exclude_unset=True,
|
103
102
|
exclude_defaults=True,
|
104
103
|
)
|
@@ -132,7 +131,7 @@ async def get_workflow_release_audit(name: str, release: str):
|
|
132
131
|
"message": f"Getting workflow {name!r} audit in release {release}",
|
133
132
|
"audit": audit.model_dump(
|
134
133
|
by_alias=True,
|
135
|
-
exclude_none=
|
134
|
+
exclude_none=False,
|
136
135
|
exclude_unset=True,
|
137
136
|
exclude_defaults=True,
|
138
137
|
),
|