Dify -- 定时任务系统

1 定时任务系统(api/schedule)--- 模块概述

1.1 模块定位

api/schedule/ 是 Dify 的定时任务中枢 ,基于 Celery Beat 调度器定义所有周期性后台任务。

每个文件对应一个独立的 Celery 任务,通过 api/extensions/ext_celery.py 中的 beat_schedule 注册触发频率,并由功能开关(dify_config.ENABLE_*)控制是否激活。

代码路径:api/schedule/

调度注册:api/extensions/ext_celery.pyinit_app()


1.2 架构概览

复制代码
Celery Beat (定时触发)
    │
    ├─ crontab / timedelta 表达式
    │
    ▼
beat_schedule (ext_celery.py)
    │ 按配置开关动态注册
    ▼
schedule/*.py  (各任务定义)
    │
    ├─ 直接操作 DB / Redis
    └─ 或 .delay() → Celery Worker Queue (异步子任务)

所有任务均以 @app.celery.task(queue="<queue_name>") 装饰,队列名与 Worker 配置对应,保证资源隔离。


1.3 任务全景

任务函数 文件 队列 默认调度周期 分类
clean_embedding_cache_task clean_embedding_cache_task.py dataset 每 N 天 02:00 数据清理
clean_unused_datasets_task clean_unused_datasets_task.py dataset 每 N 天 03:00 数据清理
clean_messages clean_messages.py retention 每 N 天 04:00 数据清理
clean_workflow_runs_task clean_workflow_runs_task.py retention 每天 00:00 数据清理
clean_workflow_runlogs_precise clean_workflow_runlogs_precise.py retention 每天 02:00 数据清理
mail_clean_document_notify_task mail_clean_document_notify_task.py dataset 每周一 10:00 通知
queue_monitor_task queue_monitor_task.py monitor 每 30 分钟 运维监控
check_upgradable_plugin_task check_upgradable_plugin_task.py plugin 每 15 分钟 插件管理
poll_workflow_schedules workflow_schedule_task.py schedule_poller 可配置(分钟级) Workflow 触发
trigger_provider_refresh trigger_provider_refresh_task.py trigger_refresh_publisher 可配置(分钟级) 触发器管理
create_tidb_serverless_task create_tidb_serverless_task.py dataset 每小时整点 TiDB 资源管理
update_tidb_serverless_status_task update_tidb_serverless_status_task.py dataset 每 10 分钟 TiDB 资源管理
batch_update_api_token_last_used update_api_token_last_used_task.py api_token 每 30 分钟 Token 管理

1.4 任务分类说明

1.4.1 数据清理类(Retention)

定期删除过期数据,防止数据库无限膨胀。包含嵌入缓存、知识库索引、消息记录、Workflow 运行日志等。部分任务通过 Redis 分布式锁防止并发执行。

1.4.2 通知类(Notification)

在数据清理后向租户发送邮件通知(如知识库文档被自动禁用)。

1.4.3 运维监控类(Monitoring)

监控 Celery 队列积压情况,超阈值时发送告警邮件。

1.4.4 插件管理类(Plugin)

定期检查哪些插件有可用更新,并按租户策略自动触发升级检查任务。

1.4.5 Workflow 定时触发类(Scheduling)

轮询 WorkflowSchedulePlan 表中到期的调度计划,分批派发给 Celery Worker 执行。

1.4.6 触发器凭证刷新类(Trigger)

扫描即将过期的触发器订阅(Webhook/外部事件),在到期前批量刷新凭证。

1.4.7 TiDB Serverless 资源池管理(Cloud)

维护 TiDB Serverless 集群的空闲资源池(按需创建和状态同步)。

1.4.8 API Token 使用记录类(Token)

将 Redis 中的 API Token 最近使用时间批量刷新到数据库,避免每次请求写 DB 的热点问题。


1.5 关键设计模式

1.5.1 功能开关 + 动态注册
python 复制代码
# ext_celery.py
if dify_config.ENABLE_CLEAN_EMBEDDING_CACHE_TASK:
    imports.append("schedule.clean_embedding_cache_task")
    beat_schedule["clean_embedding_cache_task"] = {...}

所有任务均受配置开关保护,生产环境可按需启禁,不影响其他服务。

1.5.2 Redis 分布式锁防并发
python 复制代码
with redis_client.lock("retention:clean_messages", timeout=..., blocking=False):
    ...

clean_messagesclean_workflow_runs_task 使用非阻塞锁:若已有实例在运行,当前调用直接跳过,避免重叠执行。

1.5.3 批次分页 + 增量游标

数据量大的清理任务(如 clean_workflow_runlogs_precise)使用 last_seen 游标分批处理,单批失败不影响已处理批次,支持重试。

1.5.4 子任务 Fanout(异步派发)

check_upgradable_plugin_taskpoll_workflow_schedules 将实际工作通过 .delay() / group() 派发给独立 Worker,自身只做调度协调,快速返回。


1.6 依赖关系

1.6.1 被以下模块依赖
  • api/extensions/ext_celery.py:注册并启动所有定时任务
1.6.2 依赖以下模块
依赖模块 用途
extensions/ext_database 数据库操作(增删查改)
extensions/ext_redis 分布式锁、Redis 缓存读写
extensions/ext_mail 发送告警/通知邮件
services/retention/ 数据保留策略与清理服务
tasks/process_tenant_plugin_autoupgrade_check_task 子任务:租户插件升级检查
tasks/workflow_schedule_tasks 子任务:运行 Schedule Trigger
tasks/trigger_subscription_refresh_tasks 子任务:刷新触发器订阅
core/rag/index_processor/ 清理向量索引(知识库)
core/helper/marketplace 获取全局插件 Manifest
models/ DB 模型(Dataset、Embedding、WorkflowRun 等)

2 数据清理定时任务详解

2.1 概述

数据清理任务负责定期删除 Dify 中的过期数据,防止数据库无限膨胀。涉及五类数据:

任务 目标数据 触发时间
clean_embedding_cache_task 过期 Embedding 缓存(embeddings 表) 每 N 天 02:00
clean_unused_datasets_task 长期未访问的知识库向量索引 每 N 天 03:00
clean_messages 过期对话消息记录 每 N 天 04:00
clean_workflow_runs_task Sandbox 租户过期 Workflow 运行记录 每天 00:00
clean_workflow_runlogs_precise 精确清理过期 Workflow 运行日志(全量) 每天 02:00

NCELERY_BEAT_SCHEDULER_TIME 配置;消息/Workflow 保留天数由各自 *_RETENTION_DAYS 配置控制。


2.2 clean_embedding_cache_task

文件api/schedule/clean_embedding_cache_task.py

队列dataset

2.2.1 逻辑
  1. 读取 PLAN_SANDBOX_CLEAN_DAY_SETTING 确定保留天数,计算截止时间 thirty_days_ago
  2. 循环:每批查询 100 条早于截止时间的 Embedding 记录 ID
  3. 逐条 DELETE FROM embeddings WHERE id = :id
  4. commit(),无记录时退出循环
2.2.2 特点
  • 纯数据库逐条删除,简单直接
  • 无分布式锁(任务幂等,重复执行无害)

2.3 clean_unused_datasets_task

文件api/schedule/clean_unused_datasets_task.py

队列dataset

2.3.1 逻辑

执行两组清理配置(Sandbox 和 Pro 计划各一份):

复制代码
for config in [sandbox_config, pro_config]:
    分页查询满足以下条件的 Dataset:
      - 创建时间 < 截止日期
      - 无新文档(截止日期后无更新的已启用文档)
      - 有旧文档(截止日期前有已启用文档)
    for dataset in page:
        if 截止日期后无查询记录(DatasetQuery):
            if 满足 plan_filter:
                删除向量索引(IndexProcessorFactory.clean)
                批量 UPDATE documents SET enabled=False
                可选:记录 DatasetAutoDisableLog
2.3.2 特点
  • 双重条件判断:时间维度(文档更新时间)+ 使用维度(DatasetQuery 查询记录)
  • 通过 FeatureService + Redis 缓存(600s TTL)查询租户计划,避免频繁调用
  • 分页处理(每页 50 条),防止大查询超时

2.4 clean_messages

文件api/schedule/clean_messages.py

队列retention

2.4.1 逻辑
复制代码
创建 MessagesCleanPolicy(根据 BILLING_ENABLED)
with redis_client.lock("retention:clean_messages", blocking=False):
    MessagesCleanService.from_days(policy, days, batch_size).run()
2.4.2 计费区分逻辑
  • BILLING_ENABLED=True:仅删除 Sandbox 租户的消息(含白名单/宽限期)
  • BILLING_ENABLED=False:删除所有超期消息
2.4.3 特点
  • 非阻塞分布式锁:获取失败直接跳过,不阻塞后续调度
  • 实际删除逻辑封装在 services/retention/conversation/ 中,职责分离

2.5 clean_workflow_runs_task

文件api/schedule/clean_workflow_runs_task.py

队列retention

2.5.1 逻辑
复制代码
with redis_client.lock("retention:clean_workflow_runs_task", blocking=False):
    WorkflowRunCleanup(days, batch_size).run()
  • 仅清理 Sandbox 租户的过期 Workflow 运行记录(SaaS 专用)
  • 实际级联删除逻辑封装在 services/retention/workflow_run/
2.5.2 特点
  • 同样使用非阻塞分布式锁防并发
  • clean_workflow_runlogs_precise 的区别:前者针对 Sandbox 计划租户,后者精确模式支持全量清理并可指定特定 Workflow

2.6 clean_workflow_runlogs_precise

文件api/schedule/clean_workflow_runlogs_precise.py

队列retention

2.6.1 逻辑(精确级联删除)
复制代码
while True:
    batch = workflow_run_repo.get_runs_batch_by_time_range(
        end_before=cutoff_date,
        last_seen=last_seen,       # 增量游标
        batch_size=BATCH_SIZE,
        workflow_ids=filter        # 可选:仅清理指定 Workflow
    )
    if not batch: break
    with session.begin():
        _delete_batch(session, batch)  # 嵌套事务
    last_seen = (batch[-1].created_at, batch[-1].id)

_delete_batch 的级联删除顺序:

  1. 查出 Message.idConversation.id(关联 WorkflowRun)
  2. 删除 Message 附属表(MessageAgentThoughtMessageFileMessageAnnotation 等 8 张表)
  3. 删除 Message
  4. 删除 ConversationVariableConversation
  5. 删除 WorkflowNodeExecution(通过 Repository)
  6. 删除 WorkflowTriggerLog(通过 Repository)
  7. 删除 WorkflowRun 本体
2.6.2 特点
  • 增量游标last_seen=(created_at, id) 保证分批不重不漏
  • 嵌套事务session.begin_nested() 保证单批原子性
  • 重试机制:失败后 5/10/15 分钟递增等待,最多重试 3 次
  • 可指定 WorkflowWORKFLOW_LOG_CLEANUP_SPECIFIC_WORKFLOW_IDS 支持针对特定 Workflow 清理

2.7 时序图

3 Workflow 定时调度轮询任务详解

3.1 概述

poll_workflow_schedulesapi/schedule/workflow_schedule_task.py)是 Dify Workflow Schedule Trigger 功能的核心调度器。

它以可配置的分钟间隔运行,从 WorkflowSchedulePlan 表中批量取出到期的调度计划,更新下次执行时间,并通过 Celery group() 并行派发执行任务。

文件api/schedule/workflow_schedule_task.py

队列schedule_poller

调度周期timedelta(minutes=WORKFLOW_SCHEDULE_POLLER_INTERVAL)(默认可配置)

功能开关ENABLE_WORKFLOW_SCHEDULE_POLLER_TASK


3.2 核心数据模型

模型 作用
WorkflowSchedulePlan workflow_schedule_plans 每个 Schedule 节点的执行计划(下次运行时间、cron 表达式、时区)
AppTrigger app_triggers 应用触发器注册(关联 AppId + NodeId,含状态 ENABLED/DISABLED)

3.3 执行流程

复制代码
poll_workflow_schedules()
  │
  ├─ 创建 Session
  │
  └─ loop:
       ├─ _fetch_due_schedules(session)
       │    SELECT WorkflowSchedulePlan
       │    JOIN AppTrigger ON (app_id, node_id, type=SCHEDULE)
       │    WHERE next_run_at <= now
       │      AND AppTrigger.status = ENABLED
       │    ORDER BY next_run_at ASC          ← 最久未执行优先
       │    FOR UPDATE SKIP LOCKED            ← 多实例安全
       │    LIMIT WORKFLOW_SCHEDULE_POLLER_BATCH_SIZE
       │
       ├─ if no due_schedules: break
       │
       ├─ _process_schedules(session, due_schedules, producer)
       │    for each schedule:
       │        next_run_at = calculate_next_run_at(cron, timezone)
       │        schedule.next_run_at = next_run_at  ← 立即更新,防止重入
       │    group([run_schedule_trigger.s(id) for id in ids]).apply_async()
       │    session.commit()
       │
       └─ 检查熔断器:total_dispatched >= MAX_DISPATCH_PER_TICK → break

3.4 关键设计

3.4.1 SELECT FOR UPDATE SKIP LOCKED

多个 Beat 实例并发时,FOR UPDATE SKIP LOCKED 保证同一条 WorkflowSchedulePlan 只被一个实例处理,无需额外分布式锁。

3.4.2 先更新 next_run_at 再派发

在派发 Celery 任务之前commit 更新 next_run_at,即使 Worker 执行失败,下次轮询也不会重复触发同一计划(时间窗口内最多一次语义)。

3.4.3 熔断器(Circuit Breaker)
python 复制代码
if 0 < dify_config.WORKFLOW_SCHEDULE_MAX_DISPATCH_PER_TICK <= total_dispatched:
    break  # 本轮停止,下轮继续

防止单轮派发任务数爆炸(如系统积压大量到期任务时)。

3.4.4 Celery group() 并行派发

同一批次的调度任务通过 group() 以单次 broker 事务发送,降低多次 round-trip 的延迟。


3.5 时序图


3.6 配置参数

参数 说明
ENABLE_WORKFLOW_SCHEDULE_POLLER_TASK 任务开关
WORKFLOW_SCHEDULE_POLLER_INTERVAL 轮询间隔(分钟)
WORKFLOW_SCHEDULE_POLLER_BATCH_SIZE 每批取出的最大调度计划数
WORKFLOW_SCHEDULE_MAX_DISPATCH_PER_TICK 单轮最大派发数(熔断阈值,0=不限)

4 插件自动升级检查任务详解

4.1 概述

check_upgradable_plugin_taskapi/schedule/check_upgradable_plugin_task.py)负责定期检查各租户的插件是否有可用更新,并根据租户的自动升级策略触发升级操作。

文件api/schedule/check_upgradable_plugin_task.py

队列plugin

调度周期 :每 15 分钟(crontab(minute="*/15")

功能开关ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK + MARKETPLACE_ENABLED


4.2 核心数据模型

模型 作用
TenantPluginAutoUpgradeStrategy 租户插件自动升级配置(升级时间段、策略、排除/包含列表)

4.3 执行流程

复制代码
check_upgradable_plugin_task()
  │
  ├─ 计算 now_seconds_of_day(当天已过秒数)
  │
  ├─ 查询 TenantPluginAutoUpgradeStrategy
  │    WHERE upgrade_time_of_day IN [now, now+15min)
  │      AND strategy_setting != DISABLED
  │
  ├─ if 无策略: return(跳过 Marketplace 请求,节省流量)
  │
  ├─ fetch_global_plugin_manifest(cache_prefix, cache_ttl)
  │    ← 一次性获取所有插件的最新版本信息并缓存到 Redis
  │    ← 从 30万次请求 → 每轮 1 次请求
  │
  └─ 分批派发(每批最多 MAX_CONCURRENT_CHECK_TASKS=20):
       for i in range(0, total, 20):
           for strategy in batch:
               process_tenant_plugin_autoupgrade_check_task.delay(
                   tenant_id, strategy_setting,
                   upgrade_time_of_day, upgrade_mode,
                   exclude_plugins, include_plugins
               )
           sleep(batch_interval_time)  ← 批次间匀速派发

4.4 关键设计

4.4.1 时间窗口筛选(15 分钟粒度)

租户可以配置"每天几点进行升级检查"(upgrade_time_of_day)。调度器每 15 分钟运行一次,每次只处理"升级时间恰好落在当前 15 分钟窗口内"的租户,避免所有租户同时处理。

4.4.2 全局 Manifest 缓存
python 复制代码
fetch_global_plugin_manifest(CACHE_REDIS_KEY_PREFIX, CACHE_REDIS_TTL)

在处理租户前,先将整个 Marketplace 的插件 Manifest 一次性拉取并缓存到 Redis。每个租户的子任务直接读 Redis 缓存,将 Marketplace API 的请求压力从 O(租户数) 降低到 O(1)。

4.4.3 匀速批次派发(流量整形)
python 复制代码
batch_interval_time = AUTO_UPGRADE_MINIMAL_CHECKING_INTERVAL / batch_chunk_count
time.sleep(batch_interval_time)  # 仅在非最后一批时 sleep

将所有策略在 15 分钟内匀速分批派发,避免瞬间涌入大量子任务挤压 plugin 队列。


4.5 时序图


4.6 配置参数

参数 说明
ENABLE_CHECK_UPGRADABLE_PLUGIN_TASK 任务开关
MARKETPLACE_ENABLED 市场功能开关(双重保障)
AUTO_UPGRADE_MINIMAL_CHECKING_INTERVAL 检查窗口大小(硬编码 900s/15min)
MAX_CONCURRENT_CHECK_TASKS 每批最大并发子任务数(硬编码 20)

5 API Token 使用时间批量刷新任务详解

5.1 概述

batch_update_api_token_last_usedapi/schedule/update_api_token_last_used_task.py)将 Redis 中暂存的 API Token 最近使用时间批量写回数据库,实现写延迟聚合,避免每次 API 请求都触发数据库写操作。

文件api/schedule/update_api_token_last_used_task.py

队列api_token

调度周期timedelta(minutes=API_TOKEN_LAST_USED_UPDATE_INTERVAL)(默认 30 分钟)

功能开关ENABLE_API_TOKEN_LAST_USED_UPDATE_TASK


5.2 设计背景

每次 API 请求时,若直接 UPDATE api_tokens SET last_used_at=now,在高频调用场景下会产生大量数据库写热点。

解决方案:

  • 请求时 :仅在 Redis 记录一个 api_token_active:{scope}:{token} 键,值为 ISO 格式时间戳,TTL 覆盖至下次刷新
  • 定时任务:批量扫描 Redis 键,写回数据库后删除 Redis 键

5.3 Redis Key 格式

复制代码
api_token_active:{scope}:{token_value}
  • scope:Token 类型(如 appdataset,或 None
  • token_value:实际 Token 字符串
  • value:最近使用时间(ISO 8601 格式)

5.4 执行流程

复制代码
batch_update_api_token_last_used()
  │
  ├─ redis_client.scan_iter("api_token_active:*", count=200)
  │    ← 增量扫描,不阻塞 Redis
  │
  ├─ for each key:
  │    ├─ GET value(ISO 时间戳)
  │    ├─ 解析 scope 和 token
  │    └─ 加入 token_entries[]
  │
  ├─ if token_entries 为空: 清理无效键后 return
  │
  ├─ for each (token, scope, usage_time):
  │    UPDATE api_tokens
  │    SET last_used_at = usage_time
  │    WHERE token = token
  │      AND type = scope
  │      AND (last_used_at IS NULL OR last_used_at < usage_time)
  │    ← 条件更新:只在新时间更晚时才写
  │
  └─ redis_client.delete(*keys_to_delete)  ← 清理已处理的 Redis 键

5.5 关键设计

5.5.1 scan_iter 非阻塞扫描

使用 SCAN 而非 KEYS 命令,每次返回部分结果,不阻塞 Redis 服务。

5.5.2 条件更新防回退
python 复制代码
WHERE last_used_at IS NULL OR last_used_at < usage_time

若同一 Token 在扫描期间再次被使用(新键已写入),旧的 usage_time 不会覆盖更新的时间。

5.5.3 短事务设计

每个 Token 单独开一个短 Session + BEGIN/COMMIT,避免长事务持有锁:

python 复制代码
with Session(db.engine) as session, session.begin():
    session.execute(update(ApiToken).where(...).values(...))
5.5.4 先写 DB,后删 Redis

保证在 Redis 键被删除前数据已落库,避免数据丢失。


5.6 配置参数

参数 说明
ENABLE_API_TOKEN_LAST_USED_UPDATE_TASK 任务开关
API_TOKEN_LAST_USED_UPDATE_INTERVAL 刷新间隔(分钟)
ACTIVE_TOKEN_KEY_PREFIX Redis key 前缀(定义于 services/api_token_service.py

6 其他定时任务详解

6.1 触发器订阅凭证刷新(trigger_provider_refresh

文件api/schedule/trigger_provider_refresh_task.py

队列trigger_refresh_publisher

功能开关ENABLE_TRIGGER_PROVIDER_REFRESH_TASK

调度周期timedelta(minutes=TRIGGER_PROVIDER_REFRESH_INTERVAL)

6.1.1 功能

扫描 TriggerSubscription 表,找出凭证(credential)订阅(subscription) 即将到期的记录,批量刷新以维持 Webhook/外部事件触发器的持续可用性。

6.1.2 流程
复制代码
trigger_provider_refresh()
  │
  ├─ filter = (credential_expires_at <= now + CREDENTIAL_THRESHOLD) OR
  │            (expires_at <= now + SUBSCRIPTION_THRESHOLD)
  │
  ├─ count = SELECT COUNT WHERE filter
  ├─ if count == 0: return
  │
  └─ 分页处理:
       for page in pages:
           rows = SELECT (tenant_id, subscription_id) WHERE filter
                  ORDER BY updated_at ASC LIMIT batch_size
           lock_keys = build_trigger_refresh_lock_keys(rows)
           acquired = Redis PIPELINE SETNX(lock_keys, ttl=lock_ttl)  ← 原子批量加锁
           jobs = [refresh.s(t, s) for (t,s), locked in zip if locked]
           group(jobs).apply_async()
6.1.3 关键设计
  • 原子批量加锁 :通过 Redis Pipeline SETNX 一次性获取多个锁,避免同一订阅被重复刷新
  • TTL 与阈值挂钩 :锁的 TTL = max(300, SUBSCRIPTION_THRESHOLD_SECONDS),确保刷新完成前锁不过期
  • 排序策略ORDER BY updated_at ASC 优先处理最长时间未刷新的订阅

6.2 队列积压监控(queue_monitor_task

文件api/schedule/queue_monitor_task.py

队列monitor

功能开关ENABLE_DATASETS_QUEUE_MONITOR

调度周期timedelta(minutes=QUEUE_MONITOR_INTERVAL)(默认 30 分钟)

6.2.1 功能

监控 dataset Celery 队列的积压长度,超过阈值时向配置的邮件列表发送告警。

6.2.2 流程
复制代码
queue_monitor_task()
  │
  ├─ if QUEUE_MONITOR_THRESHOLD is None: 跳过
  │
  ├─ celery_redis.llen("dataset")  ← 直接读 Celery Broker Redis
  │
  ├─ if queue_length >= threshold:
  │    for email in QUEUE_MONITOR_ALERT_EMAILS:
  │        send_email(QUEUE_MONITOR_ALERT, to=email, {queue_name, length, threshold, time})
  │
  └─ finally: close db.session
6.2.3 特点
  • 直连 Celery Broker 的 Redis(使用独立 Redis 连接,非业务 Redis)
  • 仅监控 dataset 队列(知识库相关任务最容易积压)
  • 5s socket 超时 + 健康检查,防止长连接僵死

6.3 TiDB Serverless 资源池管理

6.3.1 3a. 集群创建(create_tidb_serverless_task

文件api/schedule/create_tidb_serverless_task.py

队列dataset

调度周期 :每小时整点(crontab(minute="0", hour="*")

功能开关ENABLE_CREATE_TIDB_SERVERLESS_TASK

功能:维持指定数量的空闲 TiDB Serverless 集群,供租户按需分配。

复制代码
create_tidb_serverless_task()
  │
  ├─ if not CREATE_TIDB_SERVICE_JOB_ENABLED: return
  │
  └─ while True:
       idle_count = SELECT COUNT WHERE active=False
       if idle_count >= TIDB_SERVERLESS_NUMBER: break
       TidbService.batch_create_tidb_serverless_cluster(batch_size=20)
       INSERT TidbAuthBinding(status=CREATING, active=False)
       commit()
6.3.2 3b. 状态更新(update_tidb_serverless_status_task

文件api/schedule/update_tidb_serverless_status_task.py

队列dataset

调度周期 :每 10 分钟(timedelta(minutes=10)

功能开关ENABLE_UPDATE_TIDB_SERVERLESS_STATUS_TASK

功能 :轮询处于 CREATING 状态的集群,通过 TiDB API 更新其最新状态(变为 ACTIVE 后可被租户使用)。

复制代码
update_tidb_serverless_status_task()
  │
  ├─ SELECT TidbAuthBinding WHERE active=False AND status=CREATING
  ├─ if 无记录: return
  └─ 每批 20 个: TidbService.batch_update_tidb_serverless_cluster_status(items)
6.3.3 TiDB 资源池生命周期
复制代码
[创建任务] → CREATING → [状态更新任务] → ACTIVE (active=False, 空闲)
                                              ↓ 租户分配
                                         ACTIVE (active=True, 已使用)

6.4 文档清理邮件通知(mail_clean_document_notify_task

文件api/schedule/mail_clean_document_notify_task.py

队列dataset

调度周期 :每周一 10:00(crontab(minute="0", hour="10", day_of_week="1")

功能开关ENABLE_MAIL_CLEAN_DOCUMENT_NOTIFY_TASK

6.4.1 功能

clean_unused_datasets_task 清理知识库时会写入 DatasetAutoDisableLog。本任务读取未通知的日志,按租户聚合后向知识库 Owner 发送邮件告知哪些文档被自动禁用。

复制代码
mail_clean_document_notify_task()
  │
  ├─ if not mail.is_inited(): return
  │
  ├─ SELECT DatasetAutoDisableLog WHERE notified=False
  ├─ 按 tenant_id 分组
  │
  └─ for tenant_id, logs in groups:
       if plan == SANDBOX: skip(只通知付费用户)
       找 owner 账号
       聚合: {dataset_name: document_count}
       send_email(DOCUMENT_CLEAN_NOTIFY, to=owner.email)
       UPDATE notified=True
  commit()
6.4.2 特点
  • 只通知非 Sandbox 付费租户(Sandbox 用户无需通知)
  • 每条日志只通知一次(notified 字段幂等保护)
  • 使用 EmailType.DOCUMENT_CLEAN_NOTIFY 国际化邮件模板
相关推荐
嘉立创FPC苗工1 小时前
软硬共生:FPC与机器人的双向赋能,解锁智能装备进化新势能
人工智能·机器人·制造·fpc·电路板
MicrosoftReactor1 小时前
技术速递|解码 AI 新术语:Loops、Harnesses、Squads、Hill Climbing……到底都是什么?
人工智能·agent·harness
shxjnpl1 小时前
2026年AI会议助手横向对比:6款产品在转写、多人识别与部署上的差异
人工智能·功能测试·语音识别·智能硬件
shxjnpl1 小时前
实时转写只是第一步:一套会议AI系统背后还有哪些技术链路?
人工智能·语音识别·智能硬件
Apache IoTDB1 小时前
天谋科技 CTO 乔嘉林:多模态时序数智化软件栈
人工智能·科技·iotdb·技术大会
咖啡星人k1 小时前
2026 多智能体协作实战:把角色契约写进SPEC,MonkeyCode 云端跑通
人工智能·机器学习
正在走向自律1 小时前
爆火全网的2026机器人运动会:从赛场竞速到具身智能产业化的技术全解析
人工智能·机器人·具身智能·人形机器人·机器人运动会·百米竞速
生活皆是风景1 小时前
GEO玩明白,流量自动上门
大数据·人工智能·产品运营
B站计算机毕业设计超人1 小时前
计算机毕业设计知识图谱(Neo4j)+大语言模型LLM+GraphRAG图检索增强技术的考研院校推荐、分数线预测与智能问答系统(源码+文档+PPT+讲解)
大数据·人工智能·语言模型·毕业设计·知识图谱·课程设计·推荐算法