2bbdb00a4d
包含节点账本、每日清算,以及 Ubuntu 交互式部署脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
"""多实例定时任务互斥。锁有过期时间,持有进程异常退出后其他实例仍能继续。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import socket
|
|
from datetime import timedelta
|
|
|
|
from sqlalchemy import update
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
from app.clock import utcnow
|
|
from app.database import session_scope
|
|
from app.models import SchedulerLock
|
|
|
|
OWNER = f"{socket.gethostname()}:{os.getpid()}"
|
|
|
|
|
|
def acquire_lock(name: str, ttl: timedelta) -> bool:
|
|
now = utcnow()
|
|
until = now + ttl
|
|
try:
|
|
with session_scope() as session:
|
|
lock = session.get(SchedulerLock, name)
|
|
if lock is None:
|
|
session.add(SchedulerLock(name=name, locked_until=until, owner=OWNER))
|
|
try:
|
|
session.flush()
|
|
except IntegrityError:
|
|
session.rollback()
|
|
return False
|
|
return True
|
|
updated = session.execute(
|
|
update(SchedulerLock)
|
|
.where(SchedulerLock.name == name)
|
|
.where(SchedulerLock.locked_until <= now)
|
|
.values(locked_until=until, owner=OWNER)
|
|
)
|
|
return updated.rowcount == 1
|
|
except IntegrityError:
|
|
return False
|