[开发]SoSite 1.0 — 异步任务队列调度模式后台开关 改造执行计划

👑Lv.11 元老 🌞 骨干会员
2026-10-24 00:14:00

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:暂存20260913/docs/队列调度模式改造执行计划 (2).md。

SoSite 1.0 — 异步任务队列调度模式后台开关 改造执行计划

文档状态:待确认(2026-08-13)

目标版本:SoSite 1.0(SplitDB 纯 SQLite 分片引擎)

背景:已有完整任务队列(Queue / QueueConsumer / cli/worker.php),但业务侧(发帖/回帖)无条件入队,不适应"虚拟主机无 SSH"环境。本计划新增可配置的「队列任务处理模式」开关,覆盖三种部署形态。


一、需求评估结论

1.1 现状盘点(已读代码确认)

位置现状结论
app/Models/Thread.php::insert() (L95-96)无条件 Queue::push('rebuild_search', ['topic_id'=>$id])需按模式分支
app/Models/Post.php::insert() (L85-86)无条件 Queue::push('stats', [...])需按模式分支
app/SplitDB/Queue.php::push()随机分发 3 队列文件,返回任务 ID无需改动,复用
app/Helpers/Search.php::indexThread($id)同步重建单帖倒排索引(读分片 extern)可直接同步调用(sync 模式)
app/Helpers/Settings.php::runtimeBuild()重建 4 项统计并写 settings 表 _runtime_*可直接同步调用(sync 模式)
app/Helpers/Settings.php::get($key,$default)三层缓存读 KV(内存→文件→DB)读取 queue_mode 用
cli/worker.php常驻/--once 消费,handler 已挂接 rebuild_search/stats模式 C 依赖,无需改动
cron_trigger.php不存在需新建(模式 B 入口)
后台设置页 SettingsController::basic + admin/settings_basic.php基本信息表单,setValue 逐键保存在此页新增下拉框

1.2 关键设计确认

  1. 存储:settings 表键 queue_mode,值 sync / cron / cli,默认 sync。
  • 新装:Schema::seedDefaults() 补默认值(幂等)。
  • 老库:Settings::get('queue_mode', 'sync') 兜底,无需迁移脚本。
  1. 同步直写语义(模式 A):
  • 发帖:Search::indexThread($id)(实时索引)+ Settings::runtimeBuild()(实时统计)——与 worker handler 完全同构,数据 100% 实时。
  • 回帖:Settings::runtimeBuild()(实时统计)。
  1. 入队语义(模式 B/C):保持现状 Queue::push,立即返回。
  2. cron_trigger.php 安全设计:
  • 仅当 queue_mode === 'cron' 时执行(防止 cli 模式下误触发双消费);
  • lock/ 目录文件锁防并发重复消费;
  • 有界消费全部 3 个队列(复用 worker handler 逻辑,drain 后退出)。

二、改造执行计划表(严格串行,每步自测)

#任务交付物验证方式
S1app/Models/Thread.php::insert() 按 queue_mode 分支:sync → Search::indexThread($id) + Settings::runtimeBuild();cron/cli → 保留 Queue::push代码修改CLI 冒烟:三种模式发帖后搜索/统计即时性或队列任务数符合预期
S2app/Models/Post.php::insert() 按 queue_mode 分支:sync → Settings::runtimeBuild();cron/cli → 保留 Queue::push('stats')代码修改CLI 冒烟:sync 回帖后 total_posts 实时 +1
S3app/SplitDB/Schema.php::seedDefaults() 增加默认 queue_mode=sync(幂等)代码修改空库 bootstrap 后 settings 表含 queue_mode=sync
S4后台设置页:SettingsController::basic 增加 queue_mode 保存键;admin/settings_basic.php 新增「队列任务调度模式」区块(下拉框 + 三种模式说明 + 模式 B/C 配置指引,Alpine 联动显隐)视图 + 控制器后台保存后 settings 表值更新,刷新页面回显正确
S5新建 cron_trigger.php(web 入口:cron 模式守卫 + 文件锁 + 三队列有界消费)新文件置 cron 模式→访问 URL→队列任务被消费置 done;非 cron 模式拒绝
S6同步 update/ 镜像(S1-S5 全部改动文件)+ 更新 CHANGELOG.md交付与根目录 diff 一致;php -l 全过

说明:cli/worker.php、Queue.php、QueueConsumer.php 无需改动(模式 B/C 复用现有消费链路)。


三、详细设计

3.1 业务接入(S1 / S2)

在 Thread::insert() 步骤 5、Post::insert() 步骤 6 处,读取模式并分支:

// Thread::insert 步骤 5(原为无条件入队)
$mode = \app\Helpers\Settings::get('queue_mode', 'sync');
if ($mode === 'sync') {
    // 模式 A:同步直写(实时索引 + 实时统计)
    \app\Helpers\Search::indexThread($id);
    \app\Helpers\Settings::runtimeBuild();
} else {
    // 模式 B/C:入队,立即返回
    Queue::push('rebuild_search', ['topic_id' => $id]);
}

// Post::insert 步骤 6(原为无条件入队)
$mode = \app\Helpers\Settings::get('queue_mode', 'sync');
if ($mode === 'sync') {
    // 模式 A:同步刷新全站统计
    \app\Helpers\Settings::runtimeBuild();
} else {
    \app\SplitDB\Queue::push('stats', ['type' => 'reply', 'thread_id' => $threadId, 'user_id' => ...]);
}

语义对齐:sync 直写执行的函数与 cli/worker.php 中同名 handler 完全一致,保证三种模式下最终数据一致。

3.2 配置存储(S3)

Schema::seedDefaults() 的默认 settings 数组追加:

'queue_mode' => 'sync',   // sync=同步直写 / cron=Cron 定时触发 / cli=CLI 常驻消费

(setValue 走 ON CONFLICT DO UPDATE,幂等;老库靠 get(..., 'sync') 兜底,无需迁移。)

3.3 后台 UI(S4)——布局预览

在 admin/settings_basic.php 新增「队列任务调度」区块(置于"功能开关"之后):

┌─ 队列任务调度模式 ─────────────────────────────────────────┐
│  队列任务处理模式  [ 同步直写 (默认)        ▾ ]              │
│                                                           │
│  ● 同步直写:无需额外配置,数据实时,适合小型社区            │
│  ○ Cron 定时触发:适合虚拟主机(无 SSH)                    │
│  ○ CLI 常驻消费:适合 Linux VPS(Supervisor)               │
│                                                           │
│  [模式 B 选中时显示] 请在虚拟主机控制面板添加 Cron 任务:    │
│  ┌─────────────────────────────────────────────────────┐ │
│  │ wget -q -O /dev/null http://你的域名/cron_trigger.php │ │
│  └─────────────────────────────────────────────────────┘ │
│  [模式 C 选中时显示] 请确保服务器已安装 Supervisor 并       │
│  配置运行 cli/worker.php                                   │
└───────────────────────────────────────────────────────────┘

  • 表单:<select name="queue_mode"> 三项(sync/cron/cli);
  • 联动提示:利用后台已加载的 Alpine(sostate.js),x-data="{qm:'...'}" + x-show 按选中项显示对应指引;
  • 保存:SettingsController::basic 的 $keys 数组加入 'queue_mode';保存后 Settings::buildCache() 已存在,自动生效。

3.4 cron_trigger.php(S5)设计

1) 加载框架(Autoloader)
2) 守卫:Settings::get('queue_mode') !== 'cron' → 输出提示并退出(防 cli 模式双消费)
3) 文件锁:lock/cron_trigger.lock(LOCK_EX|LOCK_NB),拿不到锁说明上次未结束,直接退出
4) 复用 worker 的 handler(rebuild_search / stats),对 3 个队列各 drain() 一次(有界)
5) 释放锁,输出处理统计,退出

安全说明:cron 模式是"公开可触发但只做队列消费",无写权限放大风险;锁防并发重入;模式守卫防误配。


四、交付清单

文件操作
app/Models/Thread.php✏️ 改(insert 步骤 5 分支)
app/Models/Post.php✏️ 改(insert 步骤 6 分支)
app/SplitDB/Schema.php✏️ 改(seedDefaults 加 queue_mode 默认值)
app/Controllers/Admin/SettingsController.php✏️ 改(basic 保存键加 queue_mode)
app/Views/admin/settings_basic.php✏️ 改(新增调度模式下拉区块)
cron_trigger.php🆕 新建(web 触发入口)
update/ 全量同步 + CHANGELOG.md 追加📦 交付

五、验收流程(用户侧)

  1. 后台 → 基本信息 → 选择「同步直写」保存 → 发帖 → 立即搜索可见、统计即时变化;
  2. 改选「Cron 定时触发」保存 → 页面显示 wget 指引 → 发帖 → 搜索暂无新帖 → 浏览器访问 cron_trigger.php → 搜索命中、队列清空;
  3. 改选「CLI 常驻消费」保存 → 显示 Supervisor 指引 → php cli/worker.php 消费验证;
  4. 重复执行 cron_trigger.php 不产生重复消费(锁生效)。

六、备注

  • 博客/分类等其余业务(BlogController 等)已是同步写入(Search::indexBlog 直调),不涉及队列,无需改动。
  • cli/worker.php 的 --once 模式已可被 cron 直接调用,本计划新增 cron_trigger.php 仅为 Web 入口(虚拟主机无法执行 PHP CLI 时使用)。
  • 全部改动文件 UTF-8 without BOM + LF,php -l 校验。
轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 瀏覽 5 次 | 回覆 0 次

全部回覆 (0)

暫無回覆

請 登入