ddeutil-workflow 0.0.53__py3-none-any.whl → 0.0.55__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/api/__init__.py +170 -1
- ddeutil/workflow/api/routes/job.py +23 -22
- ddeutil/workflow/api/routes/schedules.py +0 -2
- ddeutil/workflow/api/routes/workflows.py +3 -4
- ddeutil/workflow/job.py +125 -170
- ddeutil/workflow/result.py +1 -0
- ddeutil/workflow/scheduler.py +1 -3
- ddeutil/workflow/stages.py +641 -399
- ddeutil/workflow/utils.py +5 -4
- ddeutil/workflow/workflow.py +118 -258
- {ddeutil_workflow-0.0.53.dist-info → ddeutil_workflow-0.0.55.dist-info}/METADATA +5 -13
- ddeutil_workflow-0.0.55.dist-info/RECORD +30 -0
- ddeutil/workflow/api/api.py +0 -170
- ddeutil_workflow-0.0.53.dist-info/RECORD +0 -31
- /ddeutil/workflow/api/{log.py → logs.py} +0 -0
- /ddeutil/workflow/api/{repeat.py → utils.py} +0 -0
- {ddeutil_workflow-0.0.53.dist-info → ddeutil_workflow-0.0.55.dist-info}/WHEEL +0 -0
- {ddeutil_workflow-0.0.53.dist-info → ddeutil_workflow-0.0.55.dist-info}/licenses/LICENSE +0 -0
- {ddeutil_workflow-0.0.53.dist-info → ddeutil_workflow-0.0.55.dist-info}/top_level.txt +0 -0
ddeutil/workflow/api/api.py
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
# ------------------------------------------------------------------------------
|
2
|
-
# Copyright (c) 2022 Korawich Anuttra. All rights reserved.
|
3
|
-
# Licensed under the MIT License. See LICENSE in the project root for
|
4
|
-
# license information.
|
5
|
-
# ------------------------------------------------------------------------------
|
6
|
-
from __future__ import annotations
|
7
|
-
|
8
|
-
import contextlib
|
9
|
-
from collections.abc import AsyncIterator
|
10
|
-
from datetime import datetime, timedelta
|
11
|
-
from typing import TypedDict
|
12
|
-
|
13
|
-
from dotenv import load_dotenv
|
14
|
-
from fastapi import FastAPI, Request
|
15
|
-
from fastapi import status as st
|
16
|
-
from fastapi.encoders import jsonable_encoder
|
17
|
-
from fastapi.exceptions import RequestValidationError
|
18
|
-
from fastapi.middleware.cors import CORSMiddleware
|
19
|
-
from fastapi.middleware.gzip import GZipMiddleware
|
20
|
-
from fastapi.responses import UJSONResponse
|
21
|
-
|
22
|
-
from ..__about__ import __version__
|
23
|
-
from ..conf import api_config, config
|
24
|
-
from ..logs import get_logger
|
25
|
-
from ..scheduler import ReleaseThread, ReleaseThreads
|
26
|
-
from ..workflow import ReleaseQueue, WorkflowTask
|
27
|
-
from .repeat import repeat_at
|
28
|
-
from .routes import job, log
|
29
|
-
|
30
|
-
load_dotenv()
|
31
|
-
logger = get_logger("uvicorn.error")
|
32
|
-
|
33
|
-
|
34
|
-
class State(TypedDict):
|
35
|
-
"""TypeDict for State of FastAPI application."""
|
36
|
-
|
37
|
-
scheduler: list[str]
|
38
|
-
workflow_threads: ReleaseThreads
|
39
|
-
workflow_tasks: list[WorkflowTask]
|
40
|
-
workflow_queue: dict[str, ReleaseQueue]
|
41
|
-
|
42
|
-
|
43
|
-
@contextlib.asynccontextmanager
|
44
|
-
async def lifespan(a: FastAPI) -> AsyncIterator[State]:
|
45
|
-
"""Lifespan function for the FastAPI application."""
|
46
|
-
a.state.scheduler = []
|
47
|
-
a.state.workflow_threads = {}
|
48
|
-
a.state.workflow_tasks = []
|
49
|
-
a.state.workflow_queue = {}
|
50
|
-
|
51
|
-
yield {
|
52
|
-
# NOTE: Scheduler value should be contained a key of workflow and
|
53
|
-
# list of datetime of queue and running.
|
54
|
-
#
|
55
|
-
# ... {
|
56
|
-
# ... '<workflow-name>': (
|
57
|
-
# ... [<running-datetime>, ...], [<queue-datetime>, ...]
|
58
|
-
# ... )
|
59
|
-
# ... }
|
60
|
-
#
|
61
|
-
"scheduler": a.state.scheduler,
|
62
|
-
"workflow_queue": a.state.workflow_queue,
|
63
|
-
"workflow_threads": a.state.workflow_threads,
|
64
|
-
"workflow_tasks": a.state.workflow_tasks,
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
app = FastAPI(
|
69
|
-
titile="Workflow",
|
70
|
-
description=(
|
71
|
-
"This is a workflow FastAPI application that use to manage manual "
|
72
|
-
"execute, logging, and schedule workflow via RestAPI."
|
73
|
-
),
|
74
|
-
version=__version__,
|
75
|
-
lifespan=lifespan,
|
76
|
-
default_response_class=UJSONResponse,
|
77
|
-
)
|
78
|
-
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
79
|
-
origins: list[str] = [
|
80
|
-
"http://localhost",
|
81
|
-
"http://localhost:88",
|
82
|
-
"http://localhost:80",
|
83
|
-
]
|
84
|
-
app.add_middleware(
|
85
|
-
CORSMiddleware,
|
86
|
-
allow_origins=origins,
|
87
|
-
allow_credentials=True,
|
88
|
-
allow_methods=["*"],
|
89
|
-
allow_headers=["*"],
|
90
|
-
)
|
91
|
-
|
92
|
-
|
93
|
-
@app.get("/")
|
94
|
-
async def health():
|
95
|
-
"""Index view that not return any template without json status."""
|
96
|
-
return {"message": "Workflow already start up with healthy status."}
|
97
|
-
|
98
|
-
|
99
|
-
# NOTE Add the jobs and logs routes by default.
|
100
|
-
app.include_router(job, prefix=api_config.prefix_path)
|
101
|
-
app.include_router(log, prefix=api_config.prefix_path)
|
102
|
-
|
103
|
-
|
104
|
-
# NOTE: Enable the workflows route.
|
105
|
-
if api_config.enable_route_workflow:
|
106
|
-
from .routes import workflow
|
107
|
-
|
108
|
-
app.include_router(workflow, prefix=api_config.prefix_path)
|
109
|
-
|
110
|
-
|
111
|
-
# NOTE: Enable the schedules route.
|
112
|
-
if api_config.enable_route_schedule:
|
113
|
-
from ..logs import get_audit
|
114
|
-
from ..scheduler import schedule_task
|
115
|
-
from .routes import schedule
|
116
|
-
|
117
|
-
app.include_router(schedule, prefix=api_config.prefix_path)
|
118
|
-
|
119
|
-
@schedule.on_event("startup")
|
120
|
-
@repeat_at(cron="* * * * *", delay=2)
|
121
|
-
def scheduler_listener():
|
122
|
-
"""Schedule broker every minute at 02 second."""
|
123
|
-
logger.debug(
|
124
|
-
f"[SCHEDULER]: Start listening schedule from queue "
|
125
|
-
f"{app.state.scheduler}"
|
126
|
-
)
|
127
|
-
if app.state.workflow_tasks:
|
128
|
-
schedule_task(
|
129
|
-
app.state.workflow_tasks,
|
130
|
-
stop=datetime.now(config.tz) + timedelta(minutes=1),
|
131
|
-
queue=app.state.workflow_queue,
|
132
|
-
threads=app.state.workflow_threads,
|
133
|
-
audit=get_audit(),
|
134
|
-
)
|
135
|
-
|
136
|
-
@schedule.on_event("startup")
|
137
|
-
@repeat_at(cron="*/5 * * * *", delay=10)
|
138
|
-
def monitoring():
|
139
|
-
"""Monitoring workflow thread that running in the background."""
|
140
|
-
logger.debug("[MONITOR]: Start monitoring threading.")
|
141
|
-
snapshot_threads: list[str] = list(app.state.workflow_threads.keys())
|
142
|
-
for t_name in snapshot_threads:
|
143
|
-
|
144
|
-
thread_release: ReleaseThread = app.state.workflow_threads[t_name]
|
145
|
-
|
146
|
-
# NOTE: remove the thread that running success.
|
147
|
-
if not thread_release["thread"].is_alive():
|
148
|
-
app.state.workflow_threads.pop(t_name)
|
149
|
-
|
150
|
-
|
151
|
-
@app.exception_handler(RequestValidationError)
|
152
|
-
async def validation_exception_handler(
|
153
|
-
request: Request, exc: RequestValidationError
|
154
|
-
):
|
155
|
-
_ = request
|
156
|
-
return UJSONResponse(
|
157
|
-
status_code=st.HTTP_422_UNPROCESSABLE_ENTITY,
|
158
|
-
content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
|
159
|
-
)
|
160
|
-
|
161
|
-
|
162
|
-
if __name__ == "__main__":
|
163
|
-
import uvicorn
|
164
|
-
|
165
|
-
uvicorn.run(
|
166
|
-
app,
|
167
|
-
host="0.0.0.0",
|
168
|
-
port=80,
|
169
|
-
log_level="DEBUG",
|
170
|
-
)
|
@@ -1,31 +0,0 @@
|
|
1
|
-
ddeutil/workflow/__about__.py,sha256=fOQi-49Q8-qLVO7us5t2StkrubZvI2LQkyYSQi-3P88,28
|
2
|
-
ddeutil/workflow/__cron.py,sha256=h8rLeIUAAEB2SdZ4Jhch7LU1Yl3bbJ-iNNJ3tQ0eYVM,28095
|
3
|
-
ddeutil/workflow/__init__.py,sha256=noE8LNRcgq32m9OnIFcQqh0P7PXWdp-SGmvBCYIXgf4,1338
|
4
|
-
ddeutil/workflow/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
ddeutil/workflow/__types.py,sha256=8jBdbfb3aZSetjz0mvNrpGHwwxJff7mK8_4v41cLqlc,4316
|
6
|
-
ddeutil/workflow/conf.py,sha256=80rgmJKFU7BlH5xTLnghGzGhE8C6LFAQykd9mjHSjo8,12528
|
7
|
-
ddeutil/workflow/cron.py,sha256=WS2MInn0Sp5DKlZDZH5VFZ5AA0Q3_AnBnYEU4lZSv4I,9779
|
8
|
-
ddeutil/workflow/exceptions.py,sha256=r4Jrf9qtVPALU4wh4bnb_OYqC-StqSQJEmFC-_QK934,1408
|
9
|
-
ddeutil/workflow/job.py,sha256=Z1XP_9pj-RY64z3G4LYX-MppS99zQns9wtZy7zHuWbE,35262
|
10
|
-
ddeutil/workflow/logs.py,sha256=rsoBrUGQrooou18fg2yvPsB8NOaXnUA5ThQpBr_WVMg,26598
|
11
|
-
ddeutil/workflow/params.py,sha256=FKY4Oo1Ze4QZKRfAk7rqKsi44YaJQAbqAtXM6vlO2hI,11392
|
12
|
-
ddeutil/workflow/result.py,sha256=27nPQq9CETLCVczv4vvFEF9w2TllHZ_ROfyDoLFxRWM,5647
|
13
|
-
ddeutil/workflow/reusables.py,sha256=iXcS7Gg-71qVX4ln0ILTDx03cTtUnj_rNoXHTVdVrxc,17636
|
14
|
-
ddeutil/workflow/scheduler.py,sha256=4G5AogkmnsTKe7jKYSfU35qjubR82WQ8CLtEe9kqPTE,28304
|
15
|
-
ddeutil/workflow/stages.py,sha256=ZsGh8Wd-NqdAZC5cyJ6wXuF-UHqoCcFFedXvyHssSqc,72473
|
16
|
-
ddeutil/workflow/utils.py,sha256=zbVttaMFMRLuuBJdSJf7D9qtz8bOnQIBq-rHI3Eqy4M,7821
|
17
|
-
ddeutil/workflow/workflow.py,sha256=2ZBNW3-vcP8bpKrK184wSCukq3wpT6G0z25Su5bapR0,50832
|
18
|
-
ddeutil/workflow/api/__init__.py,sha256=F53NMBWtb9IKaDWkPU5KvybGGfKAcbehgn6TLBwHuuM,21
|
19
|
-
ddeutil/workflow/api/api.py,sha256=CWtPLgOv2Jus9E7nzG5mG2Z32ZEkUK3JWQ2htZyMRpA,5244
|
20
|
-
ddeutil/workflow/api/log.py,sha256=NMTnOnsBrDB5129329xF2myLdrb-z9k1MQrmrP7qXJw,1818
|
21
|
-
ddeutil/workflow/api/repeat.py,sha256=uTtUFVLpiYYahXvCVx8sueRQ03K2Xw1id_gW3IMmX1U,5295
|
22
|
-
ddeutil/workflow/api/routes/__init__.py,sha256=qoGtOMyVgQ5nTUc8J8wH27A8isaxl3IFCX8qoyibeCY,484
|
23
|
-
ddeutil/workflow/api/routes/job.py,sha256=oPwBVP0Mxwxv-bGPlfmxQQ9PcVl0ev9HoPzndpYDCCQ,1954
|
24
|
-
ddeutil/workflow/api/routes/logs.py,sha256=U6vOni3wd-ZTOwd3yVdSOpgyRmNdcgfngU5KlLM3Cww,5383
|
25
|
-
ddeutil/workflow/api/routes/schedules.py,sha256=EgUjyRGhsm6UNaMj5luh6TcY6l571sCHcla-BL1iOfY,4829
|
26
|
-
ddeutil/workflow/api/routes/workflows.py,sha256=JcDOrn1deK8ztFRcMTNATQejG6KMA7JxZLVc4QeBsP4,4527
|
27
|
-
ddeutil_workflow-0.0.53.dist-info/licenses/LICENSE,sha256=nGFZ1QEhhhWeMHf9n99_fdt4vQaXS29xWKxt-OcLywk,1085
|
28
|
-
ddeutil_workflow-0.0.53.dist-info/METADATA,sha256=xNgYIlFQvS9VsF0agSPsYbJWin_s9c_llkRFnEUxyC0,19425
|
29
|
-
ddeutil_workflow-0.0.53.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
30
|
-
ddeutil_workflow-0.0.53.dist-info/top_level.txt,sha256=m9M6XeSWDwt_yMsmH6gcOjHZVK5O0-vgtNBuncHjzW4,8
|
31
|
-
ddeutil_workflow-0.0.53.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|