Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
PyFund
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈涛
PyFund
Commits
cfb90ebf
Commit
cfb90ebf
authored
Mar 23, 2023
by
Confusion-ymc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化定时任务
parent
a7f47c5f
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
119 additions
and
24 deletions
+119
-24
__init__.py
api/__init__.py
+2
-1
fund.py
api/fund.py
+3
-9
scheduler.py
api/scheduler.py
+35
-0
schecular.py
exception/schecular.py
+8
-0
nav.py
service/nav.py
+1
-2
scheduler.py
service/scheduler.py
+39
-0
scheduler.py
tools/scheduler.py
+31
-12
No files found.
api/__init__.py
View file @
cfb90ebf
from
fastapi
import
APIRouter
from
fastapi
import
APIRouter
from
api
import
bill
,
nav
,
fund
,
group
,
node
from
api
import
bill
,
nav
,
fund
,
group
,
node
,
scheduler
api_router
=
APIRouter
()
api_router
=
APIRouter
()
...
@@ -8,3 +8,4 @@ api_router.include_router(nav.router, prefix="/nav", tags=["净值"])
...
@@ -8,3 +8,4 @@ api_router.include_router(nav.router, prefix="/nav", tags=["净值"])
api_router
.
include_router
(
fund
.
router
,
prefix
=
"/fund"
,
tags
=
[
"基金"
])
api_router
.
include_router
(
fund
.
router
,
prefix
=
"/fund"
,
tags
=
[
"基金"
])
api_router
.
include_router
(
node
.
router
,
prefix
=
"/node"
,
tags
=
[
"节点"
])
api_router
.
include_router
(
node
.
router
,
prefix
=
"/node"
,
tags
=
[
"节点"
])
api_router
.
include_router
(
group
.
router
,
prefix
=
"/group"
,
tags
=
[
"用户分组"
])
api_router
.
include_router
(
group
.
router
,
prefix
=
"/group"
,
tags
=
[
"用户分组"
])
api_router
.
include_router
(
scheduler
.
router
,
prefix
=
"/scheduler"
,
tags
=
[
"定时任务"
])
api/fund.py
View file @
cfb90ebf
...
@@ -2,9 +2,7 @@ import datetime
...
@@ -2,9 +2,7 @@ import datetime
from
typing
import
Union
from
typing
import
Union
from
redis
import
asyncio
as
aioredis
from
redis
import
asyncio
as
aioredis
import
pytz
from
apscheduler.schedulers.asyncio
import
AsyncIOScheduler
from
apscheduler.schedulers.asyncio
import
AsyncIOScheduler
from
apscheduler.triggers
import
interval
from
fastapi
import
APIRouter
,
Depends
from
fastapi
import
APIRouter
,
Depends
from
motor.core
import
AgnosticCollection
from
motor.core
import
AgnosticCollection
from
pymongo
import
ReturnDocument
from
pymongo
import
ReturnDocument
...
@@ -12,8 +10,8 @@ from pymongo import ReturnDocument
...
@@ -12,8 +10,8 @@ from pymongo import ReturnDocument
from
exception.db
import
NotFundError
from
exception.db
import
NotFundError
from
model
import
Response
from
model
import
Response
from
model.fund
import
FundType
,
CreateFund
,
StakingFund
,
NormalFund
,
UpdateFund
from
model.fund
import
FundType
,
CreateFund
,
StakingFund
,
NormalFund
,
UpdateFund
from
dependencies
import
get_current_user
,
get_fund_collect
,
get_scheduler
,
get_cmc_price_redis
from
dependencies
import
get_current_user
,
get_fund_collect
,
get_scheduler
from
service.
nav
import
calculate_nav
from
service.
scheduler
import
calculate_nav_task
from
tools.jwt_tools
import
User
from
tools.jwt_tools
import
User
router
=
APIRouter
()
router
=
APIRouter
()
...
@@ -27,7 +25,6 @@ async def create(
...
@@ -27,7 +25,6 @@ async def create(
create_fund
:
CreateFund
,
create_fund
:
CreateFund
,
user
:
User
=
Depends
(
get_current_user
),
user
:
User
=
Depends
(
get_current_user
),
fund_collect
:
AgnosticCollection
=
Depends
(
get_fund_collect
),
fund_collect
:
AgnosticCollection
=
Depends
(
get_fund_collect
),
redis_client
:
aioredis
.
Redis
=
Depends
(
get_cmc_price_redis
),
scheduler
:
AsyncIOScheduler
=
Depends
(
get_scheduler
)
scheduler
:
AsyncIOScheduler
=
Depends
(
get_scheduler
)
):
):
if
create_fund
.
fund_type
==
FundType
.
staking
:
if
create_fund
.
fund_type
==
FundType
.
staking
:
...
@@ -42,10 +39,7 @@ async def create(
...
@@ -42,10 +39,7 @@ async def create(
await
fund_collect
.
insert_one
(
insert_data
)
await
fund_collect
.
insert_one
(
insert_data
)
scheduler
.
add_job
(
func
=
calculate_nav
,
args
=
(
create_model
.
id
,),
await
calculate_nav_task
(
create_model
.
id
,
scheduler
,
fund_collect
,
user
.
id
)
trigger
=
interval
.
IntervalTrigger
(
seconds
=
5
,
timezone
=
pytz
.
UTC
),
misfire_grace_time
=
10
)
scheduler
.
print_jobs
()
return
response
return
response
...
...
api/scheduler.py
0 → 100644
View file @
cfb90ebf
from
apscheduler.schedulers.asyncio
import
AsyncIOScheduler
from
fastapi
import
Depends
,
APIRouter
from
motor.core
import
AgnosticCollection
from
dependencies
import
get_current_user
,
get_scheduler
,
get_fund_collect
from
model
import
BaseResponse
from
service.scheduler
import
calculate_nav_task
,
delete_task
from
tools.jwt_tools
import
User
router
=
APIRouter
()
@
router
.
post
(
'/'
,
summary
=
'创建基金净值计算任务'
,
description
=
'创建基金净值计算任务'
)
async
def
create
(
fund_id
:
str
,
user
:
User
=
Depends
(
get_current_user
),
fund_collect
:
AgnosticCollection
=
Depends
(
get_fund_collect
),
scheduler
:
AsyncIOScheduler
=
Depends
(
get_scheduler
)
):
await
calculate_nav_task
(
fund_id
,
scheduler
,
fund_collect
,
user
.
id
)
return
BaseResponse
(
message
=
'创建成功'
)
@
router
.
delete
(
'/'
,
summary
=
'停止定时任务'
,
description
=
'停止定时任务'
)
async
def
stop
(
job_id
:
str
,
user
:
User
=
Depends
(
get_current_user
),
scheduler
:
AsyncIOScheduler
=
Depends
(
get_scheduler
)
):
await
delete_task
(
job_id
,
scheduler
)
return
BaseResponse
(
message
=
'停止成功'
)
exception/schecular.py
0 → 100644
View file @
cfb90ebf
from
starlette
import
status
from
exception
import
MyException
class
TaskExistError
(
MyException
):
status
=
status
.
HTTP_500_INTERNAL_SERVER_ERROR
message
=
'任务已存在'
service/nav.py
View file @
cfb90ebf
from
loguru
import
logger
from
loguru
import
logger
from
redis
import
asyncio
as
aioredis
from
motor.core
import
AgnosticCollection
from
dependencies
import
get_fund_collect
,
get_cmc_price_redis
from
dependencies
import
get_fund_collect
,
get_cmc_price_redis
from
model.fund
import
FundStatus
from
model.fund
import
FundStatus
...
@@ -15,3 +13,4 @@ async def calculate_nav(fund_id):
...
@@ -15,3 +13,4 @@ async def calculate_nav(fund_id):
for
coin_item
in
fund_data
[
'assets'
]:
for
coin_item
in
fund_data
[
'assets'
]:
data
=
await
redis_client
.
hget
(
f
'CMC:CoinPrice:{coin_item["currency"]}'
,
'Price'
)
data
=
await
redis_client
.
hget
(
f
'CMC:CoinPrice:{coin_item["currency"]}'
,
'Price'
)
print
(
f
'获取到报价 {data}'
)
print
(
f
'获取到报价 {data}'
)
# todo 未完成具体实现
service/scheduler.py
0 → 100644
View file @
cfb90ebf
import
pytz
from
apscheduler.triggers
import
interval
from
motor.core
import
AgnosticCollection
from
exception.db
import
NotFundError
from
exception.schecular
import
TaskExistError
from
service.nav
import
calculate_nav
async
def
delete_task
(
job_id
,
schedular
):
if
schedular
.
get_job
(
job_id
):
schedular
.
remove_job
(
job_id
)
else
:
raise
NotFundError
()
schedular
.
print_jobs
()
async
def
calculate_nav_task
(
fund_id
,
schedular
,
fund_collect
:
AgnosticCollection
,
user_id
=
None
):
"""
创建净值计算任务
:param schedular:
:param fund_id:
:param fund_collect:
:param user_id:
:return:
"""
query
=
{
'id'
:
fund_id
}
if
user_id
:
query
.
update
({
'user_id'
:
user_id
})
res
=
await
fund_collect
.
find_one
()
assert
res
,
NotFundError
()
job_id
=
f
'calculate_nav_{fund_id}'
if
schedular
.
get_job
(
job_id
):
raise
TaskExistError
schedular
.
add_job
(
func
=
calculate_nav
,
id
=
job_id
,
args
=
(
fund_id
,),
trigger
=
interval
.
IntervalTrigger
(
seconds
=
5
,
timezone
=
pytz
.
UTC
),
misfire_grace_time
=
10
)
schedular
.
print_jobs
()
tools/scheduler.py
View file @
cfb90ebf
import
asyncio
import
asyncio
import
datetime
import
datetime
import
time
import
time
from
apscheduler
import
events
from
apscheduler.events
import
EVENT_JOB_ERROR
,
EVENT_JOB_MISSED
,
EVENT_JOB_EXECUTED
,
JobEvent
,
JobExecutionEvent
from
apscheduler.events
import
EVENT_JOB_ERROR
,
EVENT_JOB_MISSED
,
EVENT_JOB_EXECUTED
,
JobEvent
,
JobExecutionEvent
,
\
EVENT_JOB_ADDED
,
EVENT_JOB_SUBMITTED
,
EVENT_JOB_REMOVED
,
EVENT_JOB_MAX_INSTANCES
,
EVENT_JOB_MODIFIED
from
apscheduler.jobstores.mongodb
import
MongoDBJobStore
from
apscheduler.jobstores.mongodb
import
MongoDBJobStore
from
apscheduler.schedulers.asyncio
import
AsyncIOScheduler
from
apscheduler.schedulers.asyncio
import
AsyncIOScheduler
from
loguru
import
logger
from
loguru
import
logger
...
@@ -10,27 +11,45 @@ from pymongo import MongoClient
...
@@ -10,27 +11,45 @@ from pymongo import MongoClient
from
configs
import
settings
from
configs
import
settings
event_map
=
{
2
**
0
:
"EVENT_SCHEDULER_STARTED"
,
2
**
0
:
"EVENT_SCHEDULER_START"
,
2
**
1
:
"EVENT_SCHEDULER_SHUTDOWN"
,
2
**
2
:
"EVENT_SCHEDULER_PAUSED"
,
2
**
3
:
"EVENT_SCHEDULER_RESUMED"
,
2
**
4
:
"EVENT_EXECUTOR_ADDED"
,
2
**
5
:
"EVENT_EXECUTOR_REMOVED"
,
2
**
6
:
"EVENT_JOBSTORE_ADDED"
,
2
**
7
:
"EVENT_JOBSTORE_REMOVED"
,
2
**
8
:
"EVENT_ALL_JOBS_REMOVED"
,
2
**
9
:
"EVENT_JOB_ADDED"
,
2
**
10
:
"EVENT_JOB_REMOVED"
,
2
**
11
:
"EVENT_JOB_MODIFIED"
,
2
**
12
:
"EVENT_JOB_EXECUTED"
,
2
**
13
:
"EVENT_JOB_ERROR"
,
2
**
14
:
"EVENT_JOB_MISSED"
,
2
**
15
:
"EVENT_JOB_SUBMITTED"
,
2
**
16
:
"EVENT_JOB_MAX_INSTANCES"
}
def
create_scheduler
(
store_mongodb_url
)
->
AsyncIOScheduler
:
def
create_scheduler
(
store_mongodb_url
)
->
AsyncIOScheduler
:
def
job_listener
(
event
:
JobExecutionEvent
):
def
job_listener
(
event
:
JobExecutionEvent
):
job
=
scheduler
.
get_job
(
event
.
job_id
)
if
getattr
(
event
,
"exception"
,
None
):
if
event
.
code
==
EVENT_JOB_MISSED
:
logger
.
error
(
logger
.
error
(
f
"[Scheduler][Error][错过执行时间] {job.name}|{job.trigger}|设定执行时间:{event.scheduled_run_time}|当前时间:{datetime.datetime.utcnow()}"
)
f
"[Scheduler] [{event.job_id}] [{event_map.get(event.code, event.code)}]|{event.exception}|{event.traceback}"
)
elif
not
event
.
exception
:
print
(
event
)
logger
.
info
(
f
"[Scheduler][Success] {job.name}|{job.trigger}|设定执行时间:{event.scheduled_run_time}"
)
else
:
else
:
logger
.
error
(
logger
.
info
(
f
"[Scheduler][Error] {job.name}|{job.trigger}|设定执行时间:{event.scheduled_run_time}|{event.exception}|{event.traceback}"
)
f
'[Scheduler] [{event.job_id}] [{event_map.get(event.code, event.code)}]'
)
scheduler
:
AsyncIOScheduler
=
AsyncIOScheduler
(
scheduler
:
AsyncIOScheduler
=
AsyncIOScheduler
(
jobstores
=
{
jobstores
=
{
'default'
:
MongoDBJobStore
(
client
=
MongoClient
(
store_mongodb_url
),
database
=
'scheduler'
,
collection
=
'jobs'
)},
'default'
:
MongoDBJobStore
(
client
=
MongoClient
(
store_mongodb_url
),
database
=
'scheduler'
,
collection
=
'jobs'
)},
max_workers
=
50
max_workers
=
50
)
)
scheduler
.
add_listener
(
job_listener
,
EVENT_JOB_ERROR
|
EVENT_JOB_MISSED
|
EVENT_JOB_EXECUTED
)
scheduler
.
add_listener
(
job_listener
,
mask
=
(
EVENT_JOB_ADDED
|
EVENT_JOB_REMOVED
|
EVENT_JOB_MODIFIED
|
EVENT_JOB_EXECUTED
|
EVENT_JOB_ERROR
|
EVENT_JOB_MISSED
|
EVENT_JOB_SUBMITTED
|
EVENT_JOB_MAX_INSTANCES
))
return
scheduler
return
scheduler
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment