✨ feat(vscode): 代码阅读加 Celery 库规则,定时任务表里的任务名能跳到任务函数

This commit is contained in:
cruldra committed 2026-09-26 19:41:07 +08:00
1 parent 905d7845b5
commit 68104e2cba
22 files changed
+2228 -139

No files matched your search

+125
View File
@@ -0,0 +1,125 @@
# luffy-agent-platform 的 backend/src/luffy_agent/celery_app.py 节选:Celery 库规则的样例
"""Celery 应用实例.
使用 Redis 作为 broker 和 result backend。
通过 autodiscover_tasks 自动发现各模块的 tasks.py。
"""
from __future__ import annotations
import logging
import os
from celery import Celery
from celery.schedules import crontab
from celery.signals import task_postrun
from luffy_agent.core.setting import get_settings
logger = logging.getLogger(__name__)
_role = os.getenv("CELERY_ROLE", "worker")
settings = get_settings()
celery_app = Celery(
"luffy_agent",
broker=settings.CELERY_BROKER_URL,
backend=settings.CELERY_RESULT_BACKEND,
)
celery_app.conf.update(
task_serializer="json",
accept_content=["json"],
timezone="UTC",
task_acks_late=True,
result_expires=3600,
)
@task_postrun.connect
def _on_task_postrun(task_id: str, **kwargs: object) -> None:
logger.debug("task %s done", task_id)
celery_app.autodiscover_tasks(
[
"luffy_agent.user",
"luffy_agent.deployment",
]
)
def _ops_beat_entries(enabled: bool) -> dict[str, dict]:
"""OPS_DASHBOARD_ENABLED=false 时两条 ops 任务不进 beat_schedule."""
if not enabled:
return {}
return {
"ops.sample_realtime": {
"task": "ops.sample_realtime",
"schedule": 15,
"options": {"expires": 14},
},
"ops.sample_daily": {
"task": "ops.sample_daily",
"schedule": crontab(hour=4, minute=0),
},
}
celery_app.conf.beat_schedule = {
"commerce.cancel_timeout_pending_orders": {
"task": "commerce.cancel_timeout_pending_orders",
"schedule": 5 * 60,
},
"commerce.retry_failed_fulfillments": {
"task": "commerce.retry_failed_fulfillments",
"schedule": 10 * 60,
},
"commerce.check_pending_refunds": {
"task": "commerce.check_pending_refunds",
"schedule": 30 * 60,
},
"commerce.check_channel_pending_manual_slices": {
"task": "commerce.check_channel_pending_manual_slices",
"schedule": 10 * 60, # 手动退款切片对账: 微信回调丢失兜底
},
"deployment.reconcile_inflight": {
"task": "deployment.reconcile_inflight",
"schedule": 5 * 60, # 发布管线 in-flight 行卡死兜底: 按阶段重新派发
},
"deployment.reclaim_expired_slot_deployments": {
"task": "deployment.reclaim_expired_slot_deployments",
"schedule": 10 * 60, # 到期部署位对账: 换票或拆除 (#159)
},
"deployment.notify_expiring_deployments": {
"task": "deployment.notify_expiring_deployments",
"schedule": 24 * 60 * 60, # 每天一轮到期提醒扫描 (#274)
},
"deployment.sweep_terminal_garbage": {
"task": "deployment.sweep_terminal_garbage",
"schedule": 10
* 60, # 终态垃圾兜底: failed 行 teardown 重试 + OSS 败方补清 (#320)
},
"session.prune_langgraph_checkpoints": {
"task": "session.prune_langgraph_checkpoints",
# 高频小批量 sweep: 单轮 ≤200 thread + 批间限速 + 270s 预算, 防磁盘吃满
# 与清理 IO 风暴 (#316); 频率对齐 LangGraph Platform TTL sweeper 量级
"schedule": 5 * 60,
},
"referral.settle_due_commissions": {
"task": "referral.settle_due_commissions",
"schedule": 60 * 60, # 每小时扫一次到期佣金
},
"membership.grant_monthly_entitlements": {
"task": "membership.grant_monthly_entitlements",
"schedule": 60 * 60,
},
"storage.poll_app_data_usage": {
"task": "storage.poll_app_data_usage",
"schedule": get_settings().STORAGE_USAGE_POLL_INTERVAL_SEC,
},
**_ops_beat_entries(settings.OPS_DASHBOARD_ENABLED),
}
import luffy_agent.commerce.tasks # noqa: E402, F401