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.
@@ -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