Skip to content

fix(cron): 分离调度器状态与数据库同步状态,修复持久化任务在提前启动场景下未加载的问题 - #9419

Open
gomico wants to merge 2 commits into
AstrBotDevs:masterfrom
gomico:fix/cron-sync-on-early-start
Open

fix(cron): 分离调度器状态与数据库同步状态,修复持久化任务在提前启动场景下未加载的问题#9419
gomico wants to merge 2 commits into
AstrBotDevs:masterfrom
gomico:fix/cron-sync-on-early-start

Conversation

@gomico

@gomico gomico commented Jul 27, 2026

Copy link
Copy Markdown

修复了插件在核心启动前通过 add_basic_job(enabled=True) 注册 BasicCronJob 时,导致 CronJobManager.start() 跳过 sync_from_db(),数据库中已启用的持久化 CronJob 未加载到 APScheduler 的问题。

根因_started 变量同时兼任两个职责——"APScheduler 是否已运行"和"sync_from_db() 是否已执行"。插件在 plugin_manager.reload() 阶段调用 add_basic_job() 时,_schedule_job() 会提前启动 scheduler 并置 _started = True;随后核心生命周期调用 start() 看到 _started 为真直接返回,sync_from_db() 被永久跳过。

关联 issue: #9418

Modifications / 改动点

  • astrbot/core/cron/manager.py:引入独立状态 _db_synced,将"APScheduler 运行状态"与"数据库同步状态"解耦。

    • start() 的提前返回条件改为 _db_synced,而非 _started
    • scheduler 启动仍受 _started 保护,避免重复调用 scheduler.start()
    • sync_from_db() 完成后才置 _db_synced = True,确保无论 scheduler 是否被提前启动,数据库中的持久化任务都能被加载。
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

修复前(上次重启):cost_control 注册 CronJob → _started=Truestart() 直接 return → sync_from_db() 未执行,所有持久化 job 的 updated_at 未被更新,原有定时任务静默错过。

修复后(本次重启验证):

日志序列:
  01:37:40  [cost_control] CronJob 注册完成          ← 插件 init 调用 add_basic_job,_started=True
  01:37:53  AstrBot started.                         ← start() 执行,_started 已为 True 但 _db_synced=False

数据库验证(updated_at 全部更新到 01:37:53,确认 sync_from_db 已执行):
  [一次性测试任务]            ✓ updated 17:37:53
  [定时提醒任务A]             ✓ updated 17:37:53  ← 之前卡住未恢复的任务
  [定时提醒任务B]             ✓ updated 17:37:53
  [定时提醒任务C]             ✓ updated 17:37:53
  [定时天气播报任务]           ✓ updated 17:37:53
  [定时提醒任务D]             ✓ updated 17:37:53
  [定时提醒任务E]             ✓ updated 17:37:53
  [定时提醒任务F]             ✓ updated 17:37:53
  [一次性提醒任务]            ✓ updated 17:37:53
  [已禁用的语音播报任务]       ✗ disabled,被跳过

(时间戳为 UTC,日志为 CST;数据库使用 sqlite3 直查确认。)


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Decouple the cron scheduler running state from the database sync state to ensure persistent jobs are always loaded, even when the scheduler is started early.

Bug Fixes:

  • Ensure database-synced persistent cron jobs are loaded into the scheduler when basic jobs start the scheduler before the core start sequence.

Tests:

  • Add a regression test verifying that early scheduler startup does not cause the cron manager to skip syncing jobs from the database.

@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend labels Jul 27, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider resetting _db_synced (e.g., in shutdown or a dedicated reset method) so that a manager reused after shutdown will correctly resync from the database rather than skipping sync_from_db() on the next start() call.
  • The introduction of _db_synced changes the state machine for CronJobManager; adding a brief comment or diagram of the expected _started/_db_synced transitions near start() would help future maintainers reason about edge cases like early starts and restarts.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider resetting `_db_synced` (e.g., in `shutdown` or a dedicated reset method) so that a manager reused after shutdown will correctly resync from the database rather than skipping `sync_from_db()` on the next `start()` call.
- The introduction of `_db_synced` changes the state machine for `CronJobManager`; adding a brief comment or diagram of the expected `_started`/`_db_synced` transitions near `start()` would help future maintainers reason about edge cases like early starts and restarts.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant