This commit is contained in:
2026-06-28 17:31:59 +08:00
parent 94111ccba6
commit ad7a958662
7 changed files with 687 additions and 356 deletions
+18 -58
View File
@@ -11,10 +11,9 @@
*
* 任务定义方式:
* 1. 配置文件: config/crontab.php 的 tasks 中声明
* 2. 注解自动扫描: 在任务类上使用 #[Crontab] 注解,配置 scan_paths 目录
* 2. 注解自动扫描: 在任务类上使用 #[Crontab] 注解
*
* 确保项目根目录有 config/crontab.php 配置文件
* 并在其中定义 Redis 连接 (redis)、调度参数 (scheduler) 和扫描路径 (scan_paths)
* CrontabProcess 启动时会自动完成配置任务注册和注解扫描
*/
declare(strict_types=1);
@@ -41,14 +40,16 @@ if ($autoloadPath === null) {
require $autoloadPath;
use Kiri\Crontab\CrontabCommand;
use Kiri\Crontab\TaskRegistry;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
// 解析命令行参数
$args = $argv;
$script = array_shift($args);
$action = array_shift($args) ?: 'status';
// 查找配置文件
// 查找配置文件,获取 PID 文件路径
$configFiles = [
getcwd() . '/config/crontab.php',
__DIR__ . '/../config/crontab.php',
@@ -73,60 +74,19 @@ if (!is_array($config)) {
exit(1);
}
// 初始化任务注册中心 (静态注册表)
// 1. 注册配置文件中的任务
$taskList = $config['tasks'] ?? [];
foreach ($taskList as $taskConfig) {
try {
TaskRegistry::register($taskConfig);
} catch (\Throwable $throwable) {
fwrite(STDERR, "任务注册失败: {$throwable->getMessage()}" . PHP_EOL);
}
}
// PID 文件路径
$pidFile = $config['scheduler']['pid_file'] ?? (getcwd() . '/storage/crontab.pid');
// 2. 发现注解任务 (检查类上的 #[Crontab] 注解)
foreach (get_declared_classes() as $className) {
try {
$reflect = new ReflectionClass($className);
if ($reflect->isAbstract()) continue;
if (!in_array(Kiri\Crontab\TaskInterface::class, class_implements($className), true)) continue;
// 创建 Console Application 并执行
$application = new Application('kiri-crontab', '1.0.0');
$application->setAutoExit(false);
$attributes = $reflect->getAttributes(Kiri\Crontab\Annotate\Crontab::class);
if (empty($attributes)) continue;
$command = new CrontabCommand($pidFile);
$command->setName('crontab');
$application->add($command);
$instance = $attributes[0]->newInstance();
$expr = $instance->buildExpression();
if ($expr === '') continue;
$input = new ArgvInput(['crontab', $action]);
$output = new ConsoleOutput();
Kiri\Crontab\TaskRegistry::register([
'class' => $className,
'name' => $instance->name !== '' ? $instance->name : $className,
'expression' => $expr,
'status' => $instance->status,
]);
} catch (\Throwable) {}
}
echo "[Crontab] 任务总数: " . TaskRegistry::count() . PHP_EOL;
// PID 文件和日志文件
$pidFile = $config['scheduler']['pid_file'] ?? (getcwd() . '/storage/crontab.pid');
$logFile = $config['scheduler']['log_file'] ?? '';
// 创建命令实例
$command = new CrontabCommand($pidFile, $logFile);
// 路由到对应操作
try {
match ($action) {
'start' => $command->start($config),
'stop' => $command->stop(),
'restart' => $command->restart($config),
'status' => $command->status(),
default => fwrite(STDERR, "未知操作: {$action} (支持: start|stop|restart|status)" . PHP_EOL),
};
} catch (\Throwable $throwable) {
fwrite(STDERR, "执行失败: {$throwable->getMessage()}" . PHP_EOL);
fwrite(STDERR, "{$throwable->getTraceAsString()}" . PHP_EOL);
exit(1);
}
$exitCode = $application->run($input, $output);
exit($exitCode);