智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

210 lines
5.4 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace core\base;
use think\facade\Log;
/**
* 定时任务基类,提供执行锁机制和统一日志
*/
abstract class BaseScheduleJob extends BaseJob
{
/**
* 任务名称(用于锁文件命名)
* @var string
*/
protected $jobName = 'schedule_job';
/**
* 锁定时间(秒),默认5分钟
* @var int
*/
protected $lockTimeout = 300;
/**
* 是否启用每日执行标记
* @var bool
*/
protected $enableDailyFlag = false;
/**
* 最终执行的方法,子类需要实现
* @return mixed
*/
abstract protected function executeJob();
/**
* 主执行方法,添加锁机制
* @return mixed
*/
public function doJob()
{
$lockFile = $this->getLockFilePath();
// 检查执行锁
if ($this->isLocked($lockFile)) {
Log::write($this->jobName . '任务正在执行中,跳过');
return $this->getSkippedResult('locked');
}
// 检查每日执行标记
if ($this->enableDailyFlag && $this->isExecutedToday()) {
Log::write($this->jobName . '今天已经执行过,跳过');
return $this->getSkippedResult('already_executed_today');
}
// 创建锁文件
$this->createLock($lockFile);
try {
Log::write('开始执行' . $this->jobName . '任务');
// 执行具体任务
$result = $this->executeJob();
// 创建每日执行标记
if ($this->enableDailyFlag) {
$this->createDailyFlag();
}
Log::write($this->jobName . '任务执行完成');
return $result;
} catch (\Exception $e) {
Log::write($this->jobName . '任务执行失败:' . $e->getMessage());
return $this->getFailedResult($e->getMessage());
} finally {
// 删除锁文件
$this->removeLock($lockFile);
}
}
/**
* 获取锁文件路径
* @return string
*/
protected function getLockFilePath()
{
return runtime_path() . $this->jobName . '.lock';
}
/**
* 检查是否被锁定
* @param string $lockFile
* @return bool
*/
protected function isLocked($lockFile)
{
return file_exists($lockFile) && (time() - filemtime($lockFile)) < $this->lockTimeout;
}
/**
* 创建锁文件
* @param string $lockFile
*/
protected function createLock($lockFile)
{
file_put_contents($lockFile, time());
}
/**
* 删除锁文件
* @param string $lockFile
*/
protected function removeLock($lockFile)
{
if (file_exists($lockFile)) {
unlink($lockFile);
}
}
/**
* 检查今天是否已经执行过
* @return bool
*/
protected function isExecutedToday()
{
$today = date('Y-m-d');
$flagFile = runtime_path() . $this->jobName . '_' . $today . '.flag';
return file_exists($flagFile);
}
/**
* 创建每日执行标记
*/
protected function createDailyFlag()
{
$today = date('Y-m-d');
$flagFile = runtime_path() . $this->jobName . '_' . $today . '.flag';
file_put_contents($flagFile, time());
}
/**
* 获取跳过执行的结果
* @param string $reason
* @return array
*/
protected function getSkippedResult($reason)
{
return [
'status' => 'skipped',
'reason' => $reason,
'job_name' => $this->jobName,
'timestamp' => time()
];
}
/**
* 获取执行失败的结果
* @param string $error
* @return array
*/
protected function getFailedResult($error)
{
return [
'status' => 'failed',
'error' => $error,
'job_name' => $this->jobName,
'timestamp' => time()
];
}
/**
* 获取执行成功的结果
* @param array $data
* @return array
*/
protected function getSuccessResult($data = [])
{
return array_merge([
'status' => 'success',
'job_name' => $this->jobName,
'timestamp' => time()
], $data);
}
/**
* 清理过期的标记文件(超过7天)
*/
protected function cleanupOldFlags()
{
$runtimePath = runtime_path();
$pattern = $runtimePath . $this->jobName . '_*.flag';
$files = glob($pattern);
foreach ($files as $file) {
if (file_exists($file) && (time() - filemtime($file)) > 7 * 24 * 3600) { // 7天
unlink($file);
}
}
}
}