Reload WebSocket on control source changes
This commit is contained in:
@@ -50,7 +50,7 @@ Control은 라즈베리파이/리눅스 호스트의 팬과 시스템 상태를
|
|||||||
- `config/config.php`: DB, 인증, CSRF, Push, shell 실행 공통 함수
|
- `config/config.php`: DB, 인증, CSRF, Push, shell 실행 공통 함수
|
||||||
- `config/vapid.php`: 외부 secret 기반 VAPID 설정 bridge
|
- `config/vapid.php`: 외부 secret 기반 VAPID 설정 bridge
|
||||||
- `apply_policy.php`: CLI/cron 팬 정책 적용
|
- `apply_policy.php`: CLI/cron 팬 정책 적용
|
||||||
- `bin/control_ws.php`: WebSocket 서버
|
- `bin/control_ws.php`: WebSocket 서버. 핵심 PHP 파일 변경 감지 시 종료되고 systemd가 재시작해 새 코드를 로드
|
||||||
- `bin/push_healthcheck.php`: 작업스케줄러용 Push 헬스체크 CLI
|
- `bin/push_healthcheck.php`: 작업스케줄러용 Push 헬스체크 CLI
|
||||||
|
|
||||||
## 데이터/저장소
|
## 데이터/저장소
|
||||||
@@ -155,6 +155,7 @@ control-push-healthcheck.service
|
|||||||
- 센서 수집 주기와 DB 증가량을 확인합니다.
|
- 센서 수집 주기와 DB 증가량을 확인합니다.
|
||||||
- 하드웨어 또는 OS 변경 후 fan sysfs 경로를 확인합니다.
|
- 하드웨어 또는 OS 변경 후 fan sysfs 경로를 확인합니다.
|
||||||
- 5G WiFi 연결 시간은 외부 모듈이 값을 제공하지 않을 때 서버가 처음 감지한 시각 기준으로 계산되므로, 장치 재시작이나 DB 초기화 후에는 다시 0부터 누적됩니다.
|
- 5G WiFi 연결 시간은 외부 모듈이 값을 제공하지 않을 때 서버가 처음 감지한 시각 기준으로 계산되므로, 장치 재시작이나 DB 초기화 후에는 다시 0부터 누적됩니다.
|
||||||
|
- WebSocket은 장기 실행 프로세스이므로 `public/api.php`, `config/config.php`, `bin/control_ws.php` 변경을 감지하면 15초 안에 종료되고 `control-websocket.service`가 새 프로세스로 재시작합니다.
|
||||||
- WebSocket 장기 실행 중 DB 연결이 끊길 수 있으므로 reconnect 로그를 확인합니다.
|
- WebSocket 장기 실행 중 DB 연결이 끊길 수 있으므로 reconnect 로그를 확인합니다.
|
||||||
- Push 구독 자동 복구가 과도한 반복 등록을 만들지 않는지 확인합니다.
|
- Push 구독 자동 복구가 과도한 반복 등록을 만들지 않는지 확인합니다.
|
||||||
- Push 헬스체크 timer 상태는 `systemctl list-timers --all control-push-healthcheck.timer`로 확인합니다.
|
- Push 헬스체크 timer 상태는 `systemctl list-timers --all control-push-healthcheck.timer`로 확인합니다.
|
||||||
|
|||||||
@@ -260,9 +260,34 @@ final class ControlWebSocket implements MessageComponentInterface
|
|||||||
$address = getenv('CONTROL_WS_ADDRESS') ?: '127.0.0.1:8088';
|
$address = getenv('CONTROL_WS_ADDRESS') ?: '127.0.0.1:8088';
|
||||||
$loop = Loop::get();
|
$loop = Loop::get();
|
||||||
$app = new ControlWebSocket();
|
$app = new ControlWebSocket();
|
||||||
|
$watchFiles = [
|
||||||
|
__FILE__,
|
||||||
|
__DIR__ . '/../public/api.php',
|
||||||
|
__DIR__ . '/../config/config.php',
|
||||||
|
];
|
||||||
|
$watchSignature = static function (array $files): string {
|
||||||
|
$parts = [];
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$parts[] = is_file($file)
|
||||||
|
? $file . ':' . filemtime($file) . ':' . filesize($file)
|
||||||
|
: $file . ':missing';
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode('|', $parts);
|
||||||
|
};
|
||||||
|
$startedSignature = $watchSignature($watchFiles);
|
||||||
|
|
||||||
$loop->addPeriodicTimer(1.0, static fn() => $app->broadcastStatus());
|
$loop->addPeriodicTimer(1.0, static fn() => $app->broadcastStatus());
|
||||||
$loop->addPeriodicTimer(1.0, static fn() => $app->broadcastDmesg());
|
$loop->addPeriodicTimer(1.0, static fn() => $app->broadcastDmesg());
|
||||||
|
$loop->addPeriodicTimer(15.0, static function () use ($watchFiles, $watchSignature, $startedSignature): void {
|
||||||
|
if ($watchSignature($watchFiles) === $startedSignature) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(STDOUT, 'Control WebSocket source changed; restarting' . PHP_EOL);
|
||||||
|
exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
$socket = new SocketServer($address, [], $loop);
|
$socket = new SocketServer($address, [], $loop);
|
||||||
$server = new IoServer(
|
$server = new IoServer(
|
||||||
|
|||||||
Reference in New Issue
Block a user