Files
ulthon_admin/extend/base/common/service/TimerServiceBase.php
augushong abeac2c3cb feat(timer): 新增配置同步到数据库及主节点选举
T5: TimerServiceBase.syncConfigToDatabase() - syncs task config to DB
T6: HostServiceBase - auto master election, stale node detection,
    getMasterNode/setMasterNode methods
2026-05-26 18:33:41 +08:00

166 lines
5.1 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 base\common\service;
use app\admin\model\SystemTimerConfig;
use app\common\model\VirtualModel;
class TimerServiceBase
{
protected $taskList = null;
/**
* 将配置文件中的定时任务同步到数据库.
* 仅新增不存在的记录,标记孤立记录,不覆盖 run_type/status.
*/
public static function syncConfigToDatabase(): void
{
$config_list = include app_file_path('common/command/timer/config.php');
// 提取唯一的任务名称(并发扩展会产生同名配置,需去重)
$config_names = [];
foreach ($config_list as $config_item) {
$item = static::initConfigItem($config_item);
$name = (string) $item['name'];
if ($name !== '' && !in_array($name, $config_names, true)) {
$config_names[] = $name;
}
}
// 查询已有记录
$existing = SystemTimerConfig::column('task_name');
$now = time();
// 新增:配置中有但数据库中没有的
$new_names = array_diff($config_names, $existing);
foreach ($new_names as $name) {
SystemTimerConfig::create([
'task_name' => $name,
'run_type' => 'auto',
'status' => 1,
'is_synced' => 1,
'create_time' => $now,
'update_time' => $now,
]);
}
// 已存在且仍在配置中:仅更新 is_synced=1不动 run_type/status
$still_exists = array_intersect($existing, $config_names);
foreach ($still_exists as $name) {
SystemTimerConfig::where('task_name', $name)
->update([
'is_synced' => 1,
'update_time' => $now,
]);
}
// 已存在但不在配置中:标记为孤立
$orphaned = array_diff($existing, $config_names);
foreach ($orphaned as $name) {
SystemTimerConfig::where('task_name', $name)
->update([
'is_synced' => 0,
'update_time' => $now,
]);
}
}
public static function generateAllTaskInstanceList()
{
$config_list = include app_file_path('common/command/timer/config.php');
$task_list = [];
foreach ($config_list as $config_item) {
if ($config_item['name'] == 'http_demo' && !env('adminsystem.is_demo', false)) {
continue;
}
$task_list = array_merge($task_list, static::generateTaskInstanceFromConfig($config_item));
}
return $task_list;
}
public function generateAllRequestList()
{
if ($this->taskList === null) {
$this->taskList = static::generateAllTaskInstanceList();
}
$request_list = array_filter($this->taskList, function ($item) {
return $item['type'] == 'site';
});
return $request_list;
}
public function generateAllCallList()
{
if ($this->taskList === null) {
$this->taskList = static::generateAllTaskInstanceList();
}
$request_list = array_filter($this->taskList, function ($item) {
return $item['type'] == 'call';
});
return $request_list;
}
public static function generateTaskInstanceFromConfig($config_item)
{
$config_item = static::initConfigItem($config_item);
$request_list = [];
$concurrency = $config_item['concurrency'];
for ($i = 0; $i < $concurrency; $i++) {
$target = $config_item['target'];
$params = [
'concurrency_id' => $i,
'concurrency_count' => $concurrency,
];
// 处理target
if ($config_item['type'] == 'site') {
$target_info = parse_url($target);
$query_params = [];
if (isset($target_info['query'])) {
parse_str($target_info['query'], $query_params);
}
$query_params = array_merge($query_params, $params);
$target_info['query'] = http_build_query($query_params);
$target = unparse_url($target_info);
} elseif ($config_item['type'] == 'call') {
$target = $config_item['target'];
}
$new_config_item = clone $config_item;
$new_config_item['target'] = $target;
$new_config_item['concurrency_id'] = $i;
$request_list[] = $new_config_item;
}
return $request_list;
}
public static function initConfigItem($config)
{
$default = [
'name' => 'http_demo',
'type' => 'site',
'target' => '',
'frequency' => 600,
'concurrency' => 1,
'run_type' => 'auto',
];
$data = array_merge($default, $config);
if ($data['frequency'] < 0) {
$data['frequency'] = 0;
}
$model_timer = new VirtualModel($data);
return $model_timer;
}
}