Files
ulthon_admin/extend/base/common/controller/TimerControllerBase.php
augushong a47bbb2c6a fix(timer): 自动记录执行日志并捕获结果
Add execute() wrapper in TimerControllerBase that wraps do() with logStart/logEnd, captures return value to result field. Change site URL routing from /do to /execute with task_name injection. Add result field to system_timer_log scheme.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-26 18:33:45 +08:00

110 lines
3.1 KiB
PHP
Raw Permalink 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\controller;
use app\admin\model\SystemTimerLog;
use app\common\controller\ToolsController;
use think\facade\Cache;
class TimerControllerBase extends ToolsController
{
protected $frequency = null;
protected $concurrency = 1;
protected $concurrencyId = 0;
protected $hostId = null;
public function initialize()
{
parent::initialize();
$concurrency_id = $this->request->param('concurrency_id', 0);
if ($concurrency_id > $this->concurrency) {
$this->error('concurrency id error');
}
$this->concurrencyId = $concurrency_id;
$concurrency_count = $this->request->param('concurrency_count', 1);
if ($concurrency_count > $this->concurrency) {
$this->error('concurrency count error');
}
$this->hostId = $this->request->param('host_id', '');
if (is_int($this->frequency)) {
$this->protectVisit($this->frequency);
}
}
protected function protectVisit(int $frequency)
{
$cache_tag = 'timer_protect';
$cache_key = 'timer_protect_' . md5($this->request->url());
$last_exec_time = Cache::get($cache_key, 0);
if ($last_exec_time >= time() - $frequency) {
return $this->error('请不要频繁请求');
}
Cache::tag($cache_tag)->set($cache_key, time());
}
public function logStart(string $taskName): int
{
$data = [
'task_name' => $taskName,
'node_id' => $this->hostId,
'run_type' => '',
'start_time' => time(),
'end_time' => 0,
'duration' => 0,
'status' => 'running',
'error_message' => null,
'result' => null,
'concurrency_id' => $this->concurrencyId,
'create_time' => time(),
];
$log = SystemTimerLog::create($data);
return $log->id;
}
public function logEnd(int $logId, string $status = 'success', ?string $errorMessage = null, ?string $result = null): void
{
$log = SystemTimerLog::find($logId);
if ($log) {
$endTime = time();
$log->end_time = $endTime;
$log->duration = ($endTime - $log->start_time) * 1000; // ms
$log->status = $status;
$log->error_message = $errorMessage;
$log->result = $result;
$log->save();
}
}
/**
* 日志包裹入口:自动记录 do() 的执行过程和返回值.
* 子类仍实现 do()URL 路由从 /do 改为 /execute 触发此方法.
*/
public function execute()
{
$taskName = $this->request->param('task_name', '');
$logId = $this->logStart($taskName);
try {
$result = $this->do();
$resultStr = is_string($result) ? $result : json_encode($result, JSON_UNESCAPED_UNICODE);
$this->logEnd($logId, 'success', null, $resultStr);
return $result;
} catch (\Throwable $e) {
$this->logEnd($logId, 'error', $e->getMessage());
throw $e;
}
}
}