addOption('file', null, InputOption::VALUE_REQUIRED, 'daily_push_*.log 文件路径');
$this->addOption('dry-run', null, InputOption::VALUE_NONE, '仅预检,不修改数据库');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$file = trim(strval($input->getOption('file') ?? ''));
if ($file === '') {
$output->writeln('必须提供 --file 日志文件路径');
return self::FAILURE;
}
$dryRun = boolval($input->getOption('dry-run'));
try {
$result = (new MallDailyPushLogReplay())->replay($file, $dryRun);
} catch (Throwable $e) {
$output->writeln('' . $e->getMessage() . '');
return self::FAILURE;
}
$output->writeln('DailyPush 日志回放' . ($dryRun ? '预检' : '完成') . '');
foreach ([
'dry_run',
'log_file',
'backup_file',
'lines',
'members',
'unique_members',
'daily_created',
'daily_updated',
'daily_unchanged',
'assets_created',
'assets_updated',
'locked_points_delta',
'invalid_lines',
'failed_members',
] as $key) {
$value = $result[$key] ?? '';
if (is_bool($value)) {
$value = $value ? 'true' : 'false';
}
$output->writeln($key . ': ' . strval($value));
}
$errors = $result['errors'] ?? [];
if (is_array($errors) && $errors !== []) {
$output->writeln('错误明细(最多显示 100 条):');
foreach ($errors as $error) {
$output->writeln('- ' . strval($error));
}
}
return intval($result['failed_members'] ?? 0) > 0 || intval($result['invalid_lines'] ?? 0) > 0
? self::FAILURE
: self::SUCCESS;
}
}