Files
Gnuboard7/app/Support/InstallerContext.php
T
HeuJung c26b49a997 fix(core): installer_completed fast-path가 빈 DB 배포 시 부팅을 깨뜨리는 문제 수정 및 7.0.3 릴리스
INSTALLER_COMPLETED=true 가 적힌 .env 를 빈 DB 새 서버에 복사한 뒤
php artisan migrate 로 테이블을 만들기 전에 앱이 부팅되면, installer_completed
fast-path 가 테이블 존재를 잘못 전제하여 뒤따르는 쿼리가 table not found 로
부팅을 깨뜨렸다. 마이그레이션을 실행하려는 부팅에서 그 명령이 오히려 실패하는
닭-달걀 상태가 된다.

fast-path 자체(매 요청 information_schema 쿼리 제거 성능 최적화)는 유지하되,
이미 존재하던 참조 구현(LanguagePackServiceProvider::isRegistryReady)의 방어
패턴을 InstallerContext::isSchemaMutatingCommand 로 SSoT 화하여 나머지 5곳에
통일 적용했다.

- app/Support/InstallerContext.php: 마이그레이션 계열 콘솔 명령 판정 헬퍼
 (migrate/migrate:fresh/migrate:refresh/migrate:rollback/migrate:reset/db:wipe)
- Caches{Module,Plugin,Template}Status: fast-path 앞에 && 가드
- {Module,Plugin}RouteServiceProvider: hasTable 검증 진입 조건에 || 가드로
 무방비 pluck 도달 차단
- LanguagePackServiceProvider: 인라인 argv 검사를 헬퍼로 치환(migrate:refresh 보강)

부류 B(NotificationHookListener, IdentityPolicyRepository)는 fast-path 이후
쿼리가 이미 try/catch 로 보호되어 빈 DB 에서도 안전하므로 수정 제외.

최초 설치 흐름은 migrate 시점에 완료 플래그가 없어(false) 이번 가드의 영향권
밖이며 원래대로 hasTable 폴백을 탄다. 가드가 실제 발동하는 유일 케이스는
"플래그 true + 빈 DB" 뿐이고, 정상 운영 웹 요청은 fast-path 성능이 유지된다.

회귀 테스트: InstallerContextTest 8건 + InstallerCompletedGuardTest 5건 추가
(수정 전 5건 fail → 수정 후 green). 관련 스위트 355 passed.

7.0.3 출시 버전 bump: 코어 버전 SSoT 7곳 + CHANGELOG 동기화.
2026-07-08 22:01:53 +09:00

41 lines
1.7 KiB
PHP

<?php
namespace App\Support;
/**
* 부팅 시점 "DB 스키마 준비성" 판정에 쓰이는 인스톨러 컨텍스트 헬퍼.
*
* `config('app.installer_completed')` fast-path 는 프로덕션에서 `Schema::hasTable()`
* 호출을 건너뛰어 매 요청 오버헤드를 제거한다. 그러나 `INSTALLER_COMPLETED=true` 가
* 기록된 `.env` 를 빈 DB 새 서버에 복사한 뒤 `php artisan migrate` 로 테이블을
* 만들기 전에 앱이 부팅되면, fast-path 가 테이블 존재를 잘못 전제하여 뒤따르는
* 쿼리가 "table not found" 로 부팅을 깨뜨린다.
*
* 이 헬퍼는 스키마를 파괴/재생성하는 마이그레이션 계열 콘솔 명령 판정을 단일
* SSoT 로 캡슐화하여, 해당 컨텍스트에서 fast-path 를 무력화하는 가드에 쓰인다.
*/
class InstallerContext
{
/**
* 스키마를 파괴/재생성하는 콘솔 명령(마이그레이션 계열)이 실행 중인지 판정합니다.
*
* 이 컨텍스트에서는 `installer_completed=true` 라도 테이블이 아직 없을 수 있으므로
* fast-path(hasTable 스킵)를 신뢰해서는 안 됩니다. 웹 요청 등 콘솔이 아닌
* 실행 경로에서는 항상 false 를 반환합니다.
*
* @return bool 마이그레이션 계열 명령 실행 중 여부
*/
public static function isSchemaMutatingCommand(): bool
{
if (! app()->runningInConsole()) {
return false;
}
return in_array(
$_SERVER['argv'][1] ?? null,
['migrate', 'migrate:fresh', 'migrate:refresh', 'migrate:rollback', 'migrate:reset', 'db:wipe'],
true
);
}
}