Files
ulthon_admin/app/admin/controller/system/TimerConfig.php
augushong f13384403a 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>
2026-07-25 21:57:56 +08:00

180 lines
6.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\admin\controller\system;
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="定时任务协调配置表")
*/
class TimerConfig extends AdminController
{
use \app\admin\traits\Curd;
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new \app\admin\model\SystemTimerConfig();
$this->assign('select_list_run_type', $this->model::SELECT_LIST_RUN_TYPE, true);
$this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true);
$this->assign('select_list_is_synced', $this->model::SELECT_LIST_IS_SYNCED, true);
$this->assign('select_list_manual_trigger', $this->model::SELECT_LIST_MANUAL_TRIGGER, true);
// 允许通过行内修改的字段
$this->allowModifyFields = [
'status',
'run_type',
'concurrency',
];
}
/**
* @NodeAnotation(title="添加")
*/
public function add()
{
$this->error('定时任务配置由系统同步生成,不支持手动添加');
}
/**
* @NodeAnotation(title="删除")
*/
public function delete($id)
{
$this->error('定时任务配置由系统管理,不支持删除');
}
/**
* @NodeAnotation(title="编辑")
*/
public function edit($id)
{
$row = $this->model->find($id);
empty($row) && $this->error('数据不存在');
if ($this->request->isPost()) {
$post = $this->request->post();
// 只允许修改 run_type、status、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());
}
if ($save) {
// D18DB commit 后递增脏标记,触发 timer reloadedit 改 concurrency/run_type/status与 trigger 一致)
Cache::inc('timer_config_version');
$this->success('保存成功');
}
$this->error('保存失败');
}
$this->assign('row', $row);
return $this->fetch();
}
/**
* @NodeAnotation(title="手动触发")
*/
public function trigger($id)
{
$this->checkPostRequest();
$row = $this->model->find($id);
if (!$row) {
$this->error('数据不存在');
}
$trigger_node_id = $this->request->post('trigger_node_id');
if (empty($trigger_node_id)) {
$this->error('请选择节点');
}
try {
// 手动触发跨 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;
}
}