Files
shanxia2.0/backend/app/services/wechat_notice_events.py
T

56 lines
2.2 KiB
Python

"""独立业务事件入队;调用方持有事务,唯一键阻止多实例重复事件。"""
import hashlib
import json
from sqlalchemy.exc import IntegrityError
from app.core.config import settings
from app.core.utils import generate_uuid
from app.models.models import SysUser
from app.models.wechat_notice import WechatNotice
def event_key(*, tenant_no, appid, business_type, business_id, event_id, kind, recipient_id):
return hashlib.sha256(json.dumps([
tenant_no, appid, business_type, business_id, event_id, kind, recipient_id,
], ensure_ascii=False).encode()).hexdigest()
def enqueue_event(db, *, tenant_no, business_type, business_id, event_id, kind,
recipient_id, template_id, payload, page='', actor_id='system',
invalid_error=None):
if not settings.WECHAT_OA_ENABLED:
return None
db.flush()
user = db.query(SysUser).filter_by(
id=recipient_id, tenant_no=tenant_no, status='1', del_flag=0,
).first()
if not user:
return None
key = event_key(
tenant_no=tenant_no, appid=settings.WECHAT_OA_APPID,
business_type=business_type, business_id=business_id, event_id=event_id,
kind=kind, recipient_id=recipient_id,
)
if db.query(WechatNotice.id).filter_by(event_key=key).first():
return None
error = invalid_error or ('通知模板未配置' if not template_id else None)
row = WechatNotice(
id=generate_uuid(), tenant_no=tenant_no, appid=settings.WECHAT_OA_APPID,
business_type=business_type, business_id=business_id, cycle_id=event_id,
event_key=key, kind=kind, recipient_id=recipient_id, template_id=template_id,
payload=json.dumps(payload, ensure_ascii=False), page=page or '',
status='failed' if error else 'pending', last_error=error,
create_by=actor_id, create_dept_id=user.dept_id or '',
)
try:
with db.begin_nested():
db.add(row)
db.flush()
except IntegrityError:
# MySQL REPEATABLE READ 用当前读确认竞争者已提交的相同事件。
if db.query(WechatNotice.id).filter_by(event_key=key).with_for_update().first():
return None
raise
return row