Files
Gnuboard7/app/Console/Commands/Core/ExecuteUpgradeStepsCommand.php
T
2026-04-23 17:36:31 +09:00

95 lines
3.7 KiB
PHP

<?php
namespace App\Console\Commands\Core;
use App\Exceptions\UpgradeHandoffException;
use App\Services\CoreUpdateService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
/**
* 코어 업그레이드 스텝을 별도 프로세스에서 실행합니다.
*
* CoreUpdateCommand 의 Step 10 에서 proc_open 으로 호출하여 최신 버전 클래스·
* config 를 새 PHP 프로세스에서 로드하게 하는 진입점. 새 프로세스에서 실행되므로
* upgrade step 이 신규 Service/Repository/Controller 등을 자유롭게 호출할 수 있다.
*
* 단, 이는 beta.3 이후 업그레이드 경로(경로 B)에만 적용된다. beta.1 → beta.2
* 업그레이드는 beta.1 의 CoreUpdateCommand 가 본 커맨드를 알지 못하므로 spawn
* 효과를 받지 못한다(경로 A) — 이 경우 upgrade step 파일 내부 로컬 로직으로
* 후처리를 수행해야 한다. 상세는 docs/extension/upgrade-step-guide.md 참조.
*/
class ExecuteUpgradeStepsCommand extends Command
{
protected $signature = 'core:execute-upgrade-steps
{--from= : 시작 버전}
{--to= : 대상 버전}
{--force : 동일 버전 강제 실행}';
protected $description = '코어 업그레이드 스텝을 별도 프로세스에서 실행합니다 (CoreUpdateCommand 내부용)';
/**
* 커맨드를 실행합니다.
*
* @param CoreUpdateService $service 코어 업데이트 서비스
* @return int 종료 코드
*/
public function handle(CoreUpdateService $service): int
{
$from = (string) $this->option('from');
$to = (string) $this->option('to');
$force = (bool) $this->option('force');
if ($from === '' || $to === '') {
$this->error('--from 과 --to 는 필수 옵션입니다.');
return self::INVALID;
}
try {
$service->runUpgradeSteps(
$from,
$to,
fn (string $version) => $this->info("upgrade step 실행: {$version}"),
$force,
);
} catch (UpgradeHandoffException $e) {
// 업그레이드 스텝이 새 PHP 프로세스 재진입을 요청했다.
// 부모 프로세스(spawnUpgradeStepsProcess)가 [HANDOFF] 라인을 stdout 에서
// 읽어 페이로드를 복원하고 UpgradeHandoffException 재구성 후 상위로 던지도록,
// JSON 페이로드를 표식과 함께 출력한다. 표식 문자열은 구분자 역할이므로 일반
// step 출력과 충돌하지 않게 고정된 접두사를 사용한다.
//
// resumeCommand 는 step 작성자가 null 로 두는 것을 권장(CoreUpdateCommand 가
// from/to 버전을 사용해 자동 생성). null 도 JSON 으로 그대로 전달.
$payload = json_encode([
'afterVersion' => $e->afterVersion,
'reason' => $e->reason,
'resumeCommand' => $e->resumeCommand,
], JSON_UNESCAPED_UNICODE);
$this->line('[HANDOFF] '.$payload);
Log::info('core:execute-upgrade-steps 핸드오프', [
'from' => $from,
'to' => $to,
'after' => $e->afterVersion,
'reason' => $e->reason,
]);
return UpgradeHandoffException::EXIT_CODE;
} catch (\Throwable $e) {
Log::error('core:execute-upgrade-steps 실패', [
'from' => $from,
'to' => $to,
'error' => $e->getMessage(),
]);
$this->error($e->getMessage());
return self::FAILURE;
}
return self::SUCCESS;
}
}