feat(timer): 后台触发/编辑/节点列表控制器改造

trigger 定向 trigger_node_id 必填穿透 status;edit/modify 改 concurrency 后 Cache::inc 递增脏标记触发立即 reload(D18);hostList 返回在线节点;normalizeConcurrency 归一化入库值。

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
augushong
2026-07-25 21:57:56 +08:00
parent 3db3f7de78
commit f13384403a

View File

@@ -6,6 +6,7 @@ use app\common\controller\AdminController;
use app\admin\service\annotation\ControllerAnnotation;
use app\admin\service\annotation\NodeAnotation;
use think\App;
use think\facade\Cache;
/**
* @ControllerAnnotation(title="定时任务协调配置表")
@@ -29,6 +30,7 @@ class TimerConfig extends AdminController
$this->allowModifyFields = [
'status',
'run_type',
'concurrency',
];
}
@@ -57,14 +59,23 @@ class TimerConfig extends AdminController
empty($row) && $this->error('数据不存在');
if ($this->request->isPost()) {
$post = $this->request->post();
// 只允许修改 run_typestatus
$post = array_intersect_key($post, array_flip(['run_type', 'status']));
// 只允许修改 run_typestatus、concurrency
$post = array_intersect_key($post, array_flip(['run_type', 'status', 'concurrency']));
if (array_key_exists('concurrency', $post)) {
// 空/null=继承代码默认写 NULL正整数=覆盖0或负数=拒绝M5 防静默吞任务)
$post['concurrency'] = $this->normalizeConcurrency($post['concurrency']);
}
try {
$save = $row->save($post);
} catch (\Exception $e) {
$this->error('保存失败:' . $e->getMessage());
}
$save ? $this->success('保存成功') : $this->error('保存失败');
if ($save) {
// D18DB commit 后递增脏标记,触发 timer reloadedit 改 concurrency/run_type/status与 trigger 一致)
Cache::inc('timer_config_version');
$this->success('保存成功');
}
$this->error('保存失败');
}
$this->assign('row', $row);
@@ -81,17 +92,88 @@ class TimerConfig extends AdminController
if (!$row) {
$this->error('数据不存在');
}
if ($row->getAttr('run_type') !== 'manual') {
$this->error('只有manual类型的任务支持手动触发');
}
if ($row->getAttr('status') != 1) {
$this->error('任务已停用,请先启用');
$trigger_node_id = $this->request->post('trigger_node_id');
if (empty($trigger_node_id)) {
$this->error('请选择节点');
}
try {
$row->save(['manual_trigger' => 1]);
// 手动触发跨 run_type、穿透 statusD19调试工作流关闭+手动触发+打开)
$row->save([
'manual_trigger' => 1,
'trigger_node_id' => $trigger_node_id,
'last_trigger_time' => time(),
]);
// D18DB commit 成功后才递增 version防脏读commit 前递增→节点 reload 读旧值→永不 reload
Cache::inc('timer_config_version');
} catch (\Exception $e) {
$this->error('触发失败:' . $e->getMessage());
}
$this->success('触发成功,等待定时器执行');
}
/**
* @NodeAnotation(title="节点列表")
*/
public function hostList()
{
$list = \app\admin\model\SystemHost::where('status', 1)
->field('node_id,is_master,ip_address,last_heartbeat_at')
->order('is_master desc, node_id asc')
->select();
$this->success('', $list);
}
/**
* @NodeAnotation(title="属性修改")
*/
public function modify()
{
$this->checkPostRequest();
$post = $this->request->post();
$rule = [
'id|ID' => 'require',
'field|字段' => 'require',
'value|值' => 'require',
];
$this->validate($post, $rule);
if (!in_array($post['field'], $this->allowModifyFields)) {
$this->error('该字段不允许修改:' . $post['field']);
}
// concurrency 行内修改必须为正整数M5 防静默吞任务;继承默认请走 edit 表单传空值)
if ($post['field'] === 'concurrency' && (!is_numeric($post['value']) || (int) $post['value'] < 1)) {
$this->error('concurrency 必须是正整数');
}
$row = $this->model->find($post['id']);
empty($row) && $this->error('数据不存在');
$value = $post['field'] === 'concurrency' ? (int) $post['value'] : $post['value'];
try {
$save = $row->save([$post['field'] => $value]);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if ($save) {
// D18DB commit 后递增脏标记,触发 timer reload行内改 concurrency/status/run_type同 edit
Cache::inc('timer_config_version');
}
$this->success('保存成功');
}
/**
* 归一化 concurrency 入库值.
* 空字符串/null → null继承代码默认正整数 → int0或负数/非数字 → 拒绝.
*
* @param mixed $value 提交值
* @return int|null
*/
private function normalizeConcurrency($value)
{
if ($value === '' || $value === null) {
return null;
}
if (!is_numeric($value) || (int) $value < 1) {
$this->error('concurrency 必须是正整数或空(继承默认)');
}
return (int) $value;
}
}