diff --git a/README.md b/README.md index b7cb2152e46973066d305bc5adb7c8fb92aef929..4bd2a86cc12b42039d2a3b85106450702d703212 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@
-
+
diff --git a/dash-fastapi-backend/.env.dev b/dash-fastapi-backend/.env.dev
index f79f19e370f30a93e5e1137469f609604d662909..8b2d308a7479ed16953aedf26c8b0130c39fad49 100644
--- a/dash-fastapi-backend/.env.dev
+++ b/dash-fastapi-backend/.env.dev
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
-APP_VERSION= '2.1.0'
+APP_VERSION= '2.1.1'
# 应用是否开启热重载
APP_RELOAD = true
# 应用是否开启IP归属区域查询
diff --git a/dash-fastapi-backend/.env.prod b/dash-fastapi-backend/.env.prod
index 55c011df164cc6b376d746166e84070daab9d991..fb893609b8077f939237cdb604dbc877243e9a45 100644
--- a/dash-fastapi-backend/.env.prod
+++ b/dash-fastapi-backend/.env.prod
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
-APP_VERSION= '2.1.0'
+APP_VERSION= '2.1.1'
# 应用是否开启热重载
APP_RELOAD = false
# 应用是否开启IP归属区域查询
diff --git a/dash-fastapi-backend/config/get_scheduler.py b/dash-fastapi-backend/config/get_scheduler.py
index bf7547d0fdcb76de121ddca693ad67ca37f697c9..3fb66c41027ef468e6b08065e3ef98ddff76d5ca 100644
--- a/dash-fastapi-backend/config/get_scheduler.py
+++ b/dash-fastapi-backend/config/get_scheduler.py
@@ -1,11 +1,13 @@
import json
from apscheduler.events import EVENT_ALL
-from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
-from apscheduler.schedulers.background import BackgroundScheduler
+from apscheduler.executors.asyncio import AsyncIOExecutor
+from apscheduler.executors.pool import ProcessPoolExecutor
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.jobstores.redis import RedisJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
+from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
+from asyncio import iscoroutinefunction
from datetime import datetime, timedelta
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import sessionmaker
@@ -109,9 +111,9 @@ job_stores = {
)
),
}
-executors = {'default': ThreadPoolExecutor(20), 'processpool': ProcessPoolExecutor(5)}
+executors = {'default': AsyncIOExecutor(), 'processpool': ProcessPoolExecutor(5)}
job_defaults = {'coalesce': False, 'max_instance': 1}
-scheduler = BackgroundScheduler()
+scheduler = AsyncIOScheduler()
scheduler.configure(jobstores=job_stores, executors=executors, job_defaults=job_defaults)
@@ -132,9 +134,7 @@ class SchedulerUtil:
async with AsyncSessionLocal() as session:
job_list = await JobDao.get_job_list_for_scheduler(session)
for item in job_list:
- query_job = cls.get_scheduler_job(job_id=str(item.job_id))
- if query_job:
- cls.remove_scheduler_job(job_id=str(item.job_id))
+ cls.remove_scheduler_job(job_id=str(item.job_id))
cls.add_scheduler_job(item)
scheduler.add_listener(cls.scheduler_event_listener, EVENT_ALL)
logger.info('系统初始定时任务加载成功')
@@ -169,6 +169,10 @@ class SchedulerUtil:
:param job_info: 任务对象信息
:return:
"""
+ job_func = eval(job_info.invoke_target)
+ job_executor = job_info.job_executor
+ if iscoroutinefunction(job_func):
+ job_executor = 'default'
scheduler.add_job(
func=eval(job_info.invoke_target),
trigger=MyCronTrigger.from_crontab(job_info.cron_expression),
@@ -180,7 +184,7 @@ class SchedulerUtil:
coalesce=True if job_info.misfire_policy == '2' else False,
max_instances=3 if job_info.concurrent == '0' else 1,
jobstore=job_info.job_group,
- executor=job_info.job_executor,
+ executor=job_executor,
)
@classmethod
@@ -191,6 +195,10 @@ class SchedulerUtil:
:param job_info: 任务对象信息
:return:
"""
+ job_func = eval(job_info.invoke_target)
+ job_executor = job_info.job_executor
+ if iscoroutinefunction(job_func):
+ job_executor = 'default'
scheduler.add_job(
func=eval(job_info.invoke_target),
trigger='date',
@@ -203,7 +211,7 @@ class SchedulerUtil:
coalesce=True if job_info.misfire_policy == '2' else False,
max_instances=3 if job_info.concurrent == '0' else 1,
jobstore=job_info.job_group,
- executor=job_info.job_executor,
+ executor=job_executor,
)
@classmethod
@@ -214,7 +222,9 @@ class SchedulerUtil:
:param job_id: 任务id
:return:
"""
- scheduler.remove_job(job_id=str(job_id))
+ query_job = cls.get_scheduler_job(job_id=job_id)
+ if query_job:
+ scheduler.remove_job(job_id=str(job_id))
@classmethod
def scheduler_event_listener(cls, event):
diff --git a/dash-fastapi-backend/module_admin/service/job_service.py b/dash-fastapi-backend/module_admin/service/job_service.py
index 5a8c3bd163f7c669bb08f52e661a040f6cb8d9ec..91f784f901f59b8e94e6a9dd9dd4d2a267001f14 100644
--- a/dash-fastapi-backend/module_admin/service/job_service.py
+++ b/dash-fastapi-backend/module_admin/service/job_service.py
@@ -129,9 +129,7 @@ class JobService:
raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,定时任务已存在')
try:
await JobDao.edit_job_dao(query_db, edit_job)
- query_job = SchedulerUtil.get_scheduler_job(job_id=edit_job.get('job_id'))
- if query_job:
- SchedulerUtil.remove_scheduler_job(job_id=edit_job.get('job_id'))
+ SchedulerUtil.remove_scheduler_job(job_id=edit_job.get('job_id'))
if edit_job.get('status') == '0':
job_info = await cls.job_detail_services(query_db, edit_job.get('job_id'))
SchedulerUtil.add_scheduler_job(job_info=job_info)
@@ -152,9 +150,7 @@ class JobService:
:param page_object: 定时任务对象
:return: 执行一次定时任务结果
"""
- query_job = SchedulerUtil.get_scheduler_job(job_id=page_object.job_id)
- if query_job:
- SchedulerUtil.remove_scheduler_job(job_id=page_object.job_id)
+ SchedulerUtil.remove_scheduler_job(job_id=page_object.job_id)
job_info = await cls.job_detail_services(query_db, page_object.job_id)
if job_info:
SchedulerUtil.execute_scheduler_job_once(job_info=job_info)
@@ -176,9 +172,7 @@ class JobService:
try:
for job_id in job_id_list:
await JobDao.delete_job_dao(query_db, JobModel(job_id=job_id))
- query_job = SchedulerUtil.get_scheduler_job(job_id=job_id)
- if query_job:
- SchedulerUtil.remove_scheduler_job(job_id=job_id)
+ SchedulerUtil.remove_scheduler_job(job_id=job_id)
await query_db.commit()
return CrudResponseModel(is_success=True, message='删除成功')
except Exception as e:
diff --git a/dash-fastapi-backend/module_admin/service/menu_service.py b/dash-fastapi-backend/module_admin/service/menu_service.py
index 2cf7639b38ebb71be15d8a60828654007c6b4feb..af636f7a04704946132fc102ae930947cfc1b524 100644
--- a/dash-fastapi-backend/module_admin/service/menu_service.py
+++ b/dash-fastapi-backend/module_admin/service/menu_service.py
@@ -99,9 +99,9 @@ class MenuService:
:return: 新增菜单校验结果
"""
if not await cls.check_menu_name_unique_services(query_db, page_object):
- raise ServiceException(message=f'新增菜单{page_object.post_name}失败,菜单名称已存在')
+ raise ServiceException(message=f'新增菜单{page_object.menu_name}失败,菜单名称已存在')
elif page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path):
- raise ServiceException(message=f'新增菜单{page_object.post_name}失败,地址必须以http(s)://开头')
+ raise ServiceException(message=f'新增菜单{page_object.menu_name}失败,地址必须以http(s)://开头')
else:
try:
await MenuDao.add_menu_dao(query_db, page_object)
@@ -124,11 +124,11 @@ class MenuService:
menu_info = await cls.menu_detail_services(query_db, page_object.menu_id)
if menu_info.menu_id:
if not await cls.check_menu_name_unique_services(query_db, page_object):
- raise ServiceException(message=f'修改菜单{page_object.post_name}失败,菜单名称已存在')
+ raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,菜单名称已存在')
elif page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path):
- raise ServiceException(message=f'修改菜单{page_object.post_name}失败,地址必须以http(s)://开头')
+ raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,地址必须以http(s)://开头')
elif page_object.menu_id == page_object.parent_id:
- raise ServiceException(message=f'修改菜单{page_object.post_name}失败,上级菜单不能选择自己')
+ raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,上级菜单不能选择自己')
else:
try:
await MenuDao.edit_menu_dao(query_db, edit_menu)
diff --git a/dash-fastapi-backend/module_task/scheduler_test.py b/dash-fastapi-backend/module_task/scheduler_test.py
index 1c8441f9d6ccad2742d4b7c67d81a4220a5bdf29..b282732db1cee848b8c23ee782c2f3b5709ca131 100644
--- a/dash-fastapi-backend/module_task/scheduler_test.py
+++ b/dash-fastapi-backend/module_task/scheduler_test.py
@@ -2,6 +2,18 @@ from datetime import datetime
def job(*args, **kwargs):
+ """
+ 定时任务执行同步函数示例
+ """
print(args)
print(kwargs)
- print(f'{datetime.now()}执行了')
+ print(f'{datetime.now()}同步函数执行了')
+
+
+async def async_job(*args, **kwargs):
+ """
+ 定时任务执行异步函数示例
+ """
+ print(args)
+ print(kwargs)
+ print(f'{datetime.now()}异步函数执行了')
diff --git a/dash-fastapi-frontend/.env.dev b/dash-fastapi-frontend/.env.dev
index 1c39a5161f51d4f62b247e381fe3ae453223e726..b2cb98fb59e470240e2fc2d2d0fd6f4689cee325 100644
--- a/dash-fastapi-frontend/.env.dev
+++ b/dash-fastapi-frontend/.env.dev
@@ -16,7 +16,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 8088
# 应用版本
-APP_VERSION= '2.1.0'
+APP_VERSION= '2.1.1'
# 应用是否开启debug模式
APP_DEBUG = true
# flask-compress压缩配置
diff --git a/dash-fastapi-frontend/.env.prod b/dash-fastapi-frontend/.env.prod
index 8d9b01e633b943a75bd7bd340cdef68e8edf0f5a..71e3dc37081fba9d2f480497f6d63f256ff718ae 100644
--- a/dash-fastapi-frontend/.env.prod
+++ b/dash-fastapi-frontend/.env.prod
@@ -16,7 +16,7 @@ APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 8088
# 应用版本
-APP_VERSION= '2.1.0'
+APP_VERSION= '2.1.1'
# 应用是否开启debug模式
APP_DEBUG = false
# flask-compress压缩配置
diff --git a/requirements-pg.txt b/requirements-pg.txt
index 24b2c643e5b48f7970db9423deb4c487a34a344e..26e3ff02b50e941f11dfbe2a4bef4351411ad0c6 100644
--- a/requirements-pg.txt
+++ b/requirements-pg.txt
@@ -1,11 +1,11 @@
APScheduler==3.10.4
asyncpg==0.30.0
-cachebox==4.1.2
-dash==2.18.1
+cachebox==4.2.3
+dash==2.18.2
DateTime==5.5
fastapi[all]==0.115.0
feffery-antd-charts==0.1.0rc5
-feffery-antd-components==0.3.8
+feffery-antd-components==0.3.10
feffery-markdown-components==0.2.10
feffery-utils-components==0.2.0rc24
Flask-Compress==1.15
@@ -16,11 +16,11 @@ pandas==2.2.2
passlib[bcrypt]==1.7.4
Pillow==10.4.0
psutil==6.0.0
-pydantic-validation-decorator==0.1.2
+pydantic-validation-decorator==0.1.4
PyJWT[crypto]==2.8.0
psycopg2==2.9.10
redis==5.0.7
requests==2.32.3
SQLAlchemy[asyncio]==2.0.31
user-agents==2.2.0
-waitress==3.0.0
+waitress==3.0.1
diff --git a/requirements.txt b/requirements.txt
index 790b650f853e6db7df6501505c153ba4e610cef8..d88aec780ef5629e87b5aaca76fe5992fc8b6110 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,11 @@
APScheduler==3.10.4
asyncmy==0.2.9
-cachebox==4.1.2
-dash==2.18.1
+cachebox==4.2.3
+dash==2.18.2
DateTime==5.5
fastapi[all]==0.115.0
feffery-antd-charts==0.1.0rc5
-feffery-antd-components==0.3.8
+feffery-antd-components==0.3.10
feffery-markdown-components==0.2.10
feffery-utils-components==0.2.0rc24
Flask-Compress==1.15
@@ -16,11 +16,11 @@ pandas==2.2.2
passlib[bcrypt]==1.7.4
Pillow==10.4.0
psutil==6.0.0
-pydantic-validation-decorator==0.1.2
+pydantic-validation-decorator==0.1.4
PyJWT[crypto]==2.8.0
PyMySQL==1.1.1
redis==5.0.7
requests==2.32.3
SQLAlchemy[asyncio]==2.0.31
user-agents==2.2.0
-waitress==3.0.0
+waitress==3.0.1