v7.0.0-beta.2 release
This commit is contained in:
1 parent
6595fd0eb5
commit
fa8eba7a0d
1165 files changed
+107118
-762127
No files matched your search
@@ -112,6 +112,42 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 설치 모드 수신 (sse | polling, 기본 sse)
|
||||
*
|
||||
* POST 본문(JSON 또는 form)에서 installation_mode 필드로 전달됩니다.
|
||||
* - sse: 기존 방식 (install-worker.php GET + EventSource)
|
||||
* - polling: install-process.php 응답 완료 후 인라인으로 runInstallationTasks() 실행,
|
||||
* 프론트엔드는 state-management.php를 1초 간격으로 폴링
|
||||
*/
|
||||
$requestBody = [];
|
||||
$rawInput = file_get_contents('php://input');
|
||||
if (!empty($rawInput)) {
|
||||
$decoded = json_decode($rawInput, true);
|
||||
if (is_array($decoded)) {
|
||||
$requestBody = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
$installationMode = $requestBody['installation_mode']
|
||||
?? $_POST['installation_mode']
|
||||
?? 'sse';
|
||||
if (!in_array($installationMode, ['sse', 'polling'], true)) {
|
||||
$installationMode = 'sse';
|
||||
}
|
||||
|
||||
/**
|
||||
* 기존 DB 처리 액션 수신 (skip | drop_tables, 기본 skip)
|
||||
*
|
||||
* 이슈 #244: Step 3에서 기존 DB 감지 후 사용자가 "강제 진행" 선택 시 전달.
|
||||
*/
|
||||
$existingDbAction = $requestBody['existing_db_action']
|
||||
?? $_POST['existing_db_action']
|
||||
?? 'skip';
|
||||
if (!in_array($existingDbAction, ['skip', 'drop_tables'], true)) {
|
||||
$existingDbAction = 'skip';
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 상태 가져오기
|
||||
*/
|
||||
@@ -134,6 +170,8 @@ try {
|
||||
$state['current_task'] = null;
|
||||
$state['config'] = $config;
|
||||
$state['error'] = null;
|
||||
$state['installation_mode'] = $installationMode;
|
||||
$state['existing_db_action'] = $existingDbAction;
|
||||
|
||||
/**
|
||||
* 로그 파일 초기화 (재시도가 아닌 경우에만)
|
||||
@@ -163,17 +201,82 @@ try {
|
||||
addLog(lang('log_installation_config_saved'));
|
||||
|
||||
/**
|
||||
* 클라이언트에 즉시 응답 전송
|
||||
*
|
||||
* JavaScript에서 이 응답을 받은 후 install-worker.php로 SSE 연결을 시작합니다.
|
||||
* 응답 JSON 준비 (echo 이전에 미리 문자열화하여 Content-Length 계산용)
|
||||
*/
|
||||
http_response_code(200);
|
||||
echo json_encode([
|
||||
$responseJson = json_encode([
|
||||
'success' => true,
|
||||
'status' => 'started',
|
||||
'message' => lang('success_installation_started'),
|
||||
'installation_mode' => $installationMode,
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
/**
|
||||
* 폴링 모드: 응답을 완전히 종료한 후 워커 인라인 실행
|
||||
*
|
||||
* 핵심 과제: 브라우저의 `await fetch(install-process.php)`가 응답 완료를
|
||||
* 인식해야 JS가 폴링 시작 코드로 진행 가능하다. Apache mod_php에서는
|
||||
* ob_end_flush() + flush() 만으로는 HTTP 연결이 끊기지 않아, 워커가
|
||||
* 인라인으로 10분간 실행되는 동안 브라우저 fetch 가 대기하게 된다.
|
||||
*
|
||||
* 해결:
|
||||
* - PHP-FPM: fastcgi_finish_request() — 응답 즉시 종료
|
||||
* - mod_php 폴백: Content-Length + Connection: close 헤더 명시 →
|
||||
* 브라우저가 지정된 바이트 수만 읽고 연결을 닫음
|
||||
*/
|
||||
if ($installationMode === 'polling') {
|
||||
ignore_user_abort(true);
|
||||
|
||||
// CRITICAL: 세션 잠금 해제 — 워커가 인라인으로 10분간 실행되는 동안
|
||||
// 세션 파일이 잠겨있으면 폴링용 state-management.php?action=get 요청이
|
||||
// session_start()에서 대기하여 진행 상황을 전혀 확인할 수 없게 됨.
|
||||
//
|
||||
// task-runner의 완료 시점 $_SESSION['installer_current_step']=5 쓰기는
|
||||
// 세션이 닫힌 후에는 효과 없으므로, 미리 여기서 저장한다.
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
$_SESSION['installer_current_step'] = 5;
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
// 기존 출력 버퍼 전부 비우기 (헤더 설정 전)
|
||||
while (ob_get_level() > 0) {
|
||||
@ob_end_clean();
|
||||
}
|
||||
|
||||
// 응답 헤더 — 브라우저가 응답 완료를 인식하도록 Content-Length + Connection: close
|
||||
http_response_code(200);
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
header('Content-Length: ' . strlen($responseJson));
|
||||
header('Connection: close');
|
||||
|
||||
echo $responseJson;
|
||||
|
||||
// 출력 플러시 + PHP-FPM 지원 시 연결 종료
|
||||
@flush();
|
||||
if (function_exists('fastcgi_finish_request')) {
|
||||
@fastcgi_finish_request();
|
||||
}
|
||||
|
||||
// 워커 타임아웃 설정 (SSE 모드와 동일)
|
||||
@set_time_limit(600);
|
||||
@ini_set('display_errors', '0');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
addLog('=== Install Worker Polling Started ===');
|
||||
addLog('Client IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown'));
|
||||
|
||||
// 폴링 모드 — NullEmitter 등록 후 task runner 실행
|
||||
require_once __DIR__ . '/../includes/progress-emitter.php';
|
||||
require_once __DIR__ . '/../includes/task-runner.php';
|
||||
|
||||
setProgressEmitter(new NullEmitter());
|
||||
runInstallationTasks();
|
||||
exit;
|
||||
}
|
||||
|
||||
// SSE 모드: 일반 JSON 응답
|
||||
http_response_code(200);
|
||||
echo $responseJson;
|
||||
|
||||
} catch (Exception $e) {
|
||||
/**
|
||||
* 에러 처리
|
||||
|
||||
Reference in new issue
Block a user