Remove deprecated Nginx configuration for stream.graff.estate and update package dependencies in session-server and client
- Deleted the Nginx configuration file for stream.graff.estate. - Updated bun.lock files in both client and session-server to include new dependencies and version updates. - Added 'tree-kill' dependency to session-server for improved process management. - Refactored process termination logic in session-server to utilize 'tree-kill' for reliable process termination.
This commit is contained in:
+5
-1
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "client",
|
||||
@@ -27,6 +28,7 @@
|
||||
"@types/uuid": "^11.0.0",
|
||||
"@vitejs/plugin-react-swc": "^4.1.0",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"baseline-browser-mapping": "^2.9.2",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.22",
|
||||
@@ -282,7 +284,7 @@
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.10", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA=="],
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.7", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg=="],
|
||||
|
||||
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
||||
|
||||
@@ -666,6 +668,8 @@
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"browserslist/baseline-browser-mapping": ["baseline-browser-mapping@2.8.10", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA=="],
|
||||
|
||||
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"engine.io-client/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 0,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "strem.graff.tech-session-server",
|
||||
"dependencies": {
|
||||
"got": "^14.4.9",
|
||||
"tree-kill": "^1.2.2",
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest",
|
||||
@@ -66,6 +68,8 @@
|
||||
|
||||
"responselike": ["responselike@3.0.0", "", { "dependencies": { "lowercase-keys": "^3.0.0" } }, "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg=="],
|
||||
|
||||
"tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
|
||||
|
||||
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
||||
|
||||
"undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"start": "bun ./dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"got": "^14.4.9"
|
||||
"got": "^14.4.9",
|
||||
"tree-kill": "^1.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
+57
-86
@@ -5,6 +5,8 @@ import { existsSync } from "fs";
|
||||
import { createServer } from "net";
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname, join } from "path";
|
||||
// @ts-ignore - tree-kill не имеет типов
|
||||
import treeKill from "tree-kill";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
@@ -593,7 +595,7 @@ async function startApplication(session: SessionData): Promise<void> {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] 🛑 Остановка Cirrus для завершённой сессии ${sessionId}`
|
||||
);
|
||||
killProcessTree(cirrus.pid);
|
||||
await killProcessTree(cirrus.pid);
|
||||
activeCirrusProcesses.delete(sessionId);
|
||||
}
|
||||
}
|
||||
@@ -620,7 +622,7 @@ async function startApplication(session: SessionData): Promise<void> {
|
||||
if (mode === "stream") {
|
||||
const cirrus = activeCirrusProcesses.get(sessionId);
|
||||
if (cirrus && cirrus.pid) {
|
||||
killProcessTree(cirrus.pid);
|
||||
await killProcessTree(cirrus.pid);
|
||||
activeCirrusProcesses.delete(sessionId);
|
||||
}
|
||||
}
|
||||
@@ -672,7 +674,7 @@ async function startApplication(session: SessionData): Promise<void> {
|
||||
if (mode === "stream") {
|
||||
const cirrus = activeCirrusProcesses.get(sessionId);
|
||||
if (cirrus && cirrus.pid) {
|
||||
killProcessTree(cirrus.pid);
|
||||
await killProcessTree(cirrus.pid);
|
||||
activeCirrusProcesses.delete(sessionId);
|
||||
}
|
||||
}
|
||||
@@ -685,74 +687,59 @@ async function startApplication(session: SessionData): Promise<void> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Убить процесс и всё его дерево дочерних процессов (для Windows)
|
||||
* Принудительное завершение без попыток мягкого закрытия
|
||||
* Убить процесс и всё его дерево дочерних процессов
|
||||
* Использует tree-kill для надёжного завершения всего дерева процессов
|
||||
*/
|
||||
function killProcessTree(pid: number): void {
|
||||
try {
|
||||
// Принудительное завершение с /F
|
||||
function killProcessTree(pid: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] 🔄 Принудительное завершение процесса PID ${pid}...`
|
||||
);
|
||||
execSync(`taskkill /pid ${pid} /T /F`, {
|
||||
stdio: "ignore",
|
||||
timeout: 30000, // Таймаут 30 секунд
|
||||
windowsHide: true,
|
||||
killSignal: "SIGKILL",
|
||||
|
||||
treeKill(pid, "SIGKILL", (err: Error | undefined) => {
|
||||
if (err) {
|
||||
// Проверяем, действительно ли процесс всё ещё существует
|
||||
const processExists = checkProcessExists(pid);
|
||||
if (!processExists) {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Процесс PID ${pid} уже завершён`
|
||||
);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(
|
||||
`[${new Date().toISOString()}] ⚠️ Ошибка при завершении дерева процессов PID ${pid}:`,
|
||||
err.message
|
||||
);
|
||||
|
||||
// Fallback: попытка через taskkill
|
||||
try {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] 🔄 Попытка завершения через taskkill для PID ${pid}`
|
||||
);
|
||||
execSync(`taskkill /pid ${pid} /T /F`, {
|
||||
stdio: "ignore",
|
||||
timeout: 10000,
|
||||
windowsHide: true,
|
||||
});
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Процесс PID ${pid} завершён через taskkill`
|
||||
);
|
||||
} catch (fallbackErr) {
|
||||
console.error(
|
||||
`[${new Date().toISOString()}] ❌ Не удалось завершить процесс PID ${pid}:`,
|
||||
fallbackErr instanceof Error ? fallbackErr.message : fallbackErr
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Дерево процессов для PID ${pid} успешно завершено`
|
||||
);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Дерево процессов для PID ${pid} успешно завершено принудительно`
|
||||
);
|
||||
} catch (error) {
|
||||
// Проверяем, действительно ли процесс всё ещё существует
|
||||
const processExists = checkProcessExists(pid);
|
||||
if (!processExists) {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Процесс PID ${pid} уже завершён`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(
|
||||
`[${new Date().toISOString()}] ⚠️ Ошибка при завершении дерева процессов PID ${pid}:`,
|
||||
error instanceof Error ? error.message : error
|
||||
);
|
||||
|
||||
// Попытка принудительного завершения через PowerShell как последний вариант
|
||||
try {
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] 🔄 Попытка принудительного завершения через PowerShell для PID ${pid}`
|
||||
);
|
||||
|
||||
// Используем агрессивный PowerShell скрипт для принудительного завершения
|
||||
const psScript = `
|
||||
$proc = Get-Process -Id ${pid} -ErrorAction SilentlyContinue;
|
||||
if ($proc) {
|
||||
# Принудительно завершаем процесс и все дочерние
|
||||
Stop-Process -Id ${pid} -Force -ErrorAction SilentlyContinue;
|
||||
# Завершаем все дочерние процессы
|
||||
Get-Process | Where-Object { $_.Parent.Id -eq ${pid} } | Stop-Process -Force -ErrorAction SilentlyContinue;
|
||||
}
|
||||
`.replace(/\n/g, " ");
|
||||
|
||||
execSync(
|
||||
`powershell -Command "${psScript}"`,
|
||||
{
|
||||
stdio: "ignore",
|
||||
timeout: 15000,
|
||||
windowsHide: true,
|
||||
}
|
||||
);
|
||||
console.log(
|
||||
`[${new Date().toISOString()}] ✅ Процесс PID ${pid} завершён через PowerShell`
|
||||
);
|
||||
} catch (psError) {
|
||||
console.error(
|
||||
`[${new Date().toISOString()}] ❌ Не удалось завершить процесс PID ${pid} даже через PowerShell:`,
|
||||
psError instanceof Error ? psError.message : psError
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,16 +809,7 @@ async function stopApplication(session: SessionData): Promise<void> {
|
||||
// Останавливаем UE приложение
|
||||
const pidToKill = appPid || appProcess?.pid;
|
||||
if (pidToKill) {
|
||||
killPromises.push(
|
||||
new Promise<void>((resolve) => {
|
||||
// Запускаем killProcessTree в отдельном потоке через setTimeout
|
||||
// чтобы не блокировать основной поток
|
||||
setTimeout(() => {
|
||||
killProcessTree(pidToKill);
|
||||
resolve();
|
||||
}, 0);
|
||||
})
|
||||
);
|
||||
killPromises.push(killProcessTree(pidToKill));
|
||||
} else {
|
||||
console.warn(
|
||||
`[${new Date().toISOString()}] ⚠️ Не удалось получить PID приложения для сессии ${sessionId}`
|
||||
@@ -842,14 +820,7 @@ async function stopApplication(session: SessionData): Promise<void> {
|
||||
if (mode === "stream") {
|
||||
const cirrusPidToKill = cirrusPid || cirrusProcess?.pid;
|
||||
if (cirrusPidToKill) {
|
||||
killPromises.push(
|
||||
new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
killProcessTree(cirrusPidToKill);
|
||||
resolve();
|
||||
}, 0);
|
||||
})
|
||||
);
|
||||
killPromises.push(killProcessTree(cirrusPidToKill));
|
||||
} else {
|
||||
console.warn(
|
||||
`[${new Date().toISOString()}] ⚠️ Не удалось получить PID Cirrus для сессии ${sessionId}`
|
||||
@@ -1011,14 +982,14 @@ async function checkSessions(): Promise<void> {
|
||||
`[${new Date().toISOString()}] ⚠️ Найден процесс для неактивной сессии ${sessionId}, остановка`
|
||||
);
|
||||
if (process.pid) {
|
||||
killProcessTree(process.pid);
|
||||
await killProcessTree(process.pid);
|
||||
}
|
||||
activeProcesses.delete(sessionId);
|
||||
|
||||
// Также останавливаем Cirrus если есть
|
||||
const cirrusProcess = activeCirrusProcesses.get(sessionId);
|
||||
if (cirrusProcess && cirrusProcess.pid) {
|
||||
killProcessTree(cirrusProcess.pid);
|
||||
await killProcessTree(cirrusProcess.pid);
|
||||
activeCirrusProcesses.delete(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name stream.graff.estate;
|
||||
root /var/www/stream.graff.estate/client/dist;
|
||||
|
||||
# SSL
|
||||
ssl_certificate /etc/letsencrypt/live/stream.graff.estate/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/stream.graff.estate/privkey.pem;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/stream.graff.estate/chain.pem;
|
||||
|
||||
# security
|
||||
include nginxconfig.io/security.conf;
|
||||
|
||||
# logging
|
||||
access_log /var/log/nginx/access.log combined buffer=512k flush=1m;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# index.html fallback
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api {
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:6000;
|
||||
proxy_set_header Host $host;
|
||||
include nginxconfig.io/proxy.conf;
|
||||
}
|
||||
|
||||
location /socket.io {
|
||||
proxy_pass http://127.0.0.1:6001;
|
||||
proxy_set_header Host $host;
|
||||
include nginxconfig.io/proxy.conf;
|
||||
}
|
||||
|
||||
# additional config
|
||||
include nginxconfig.io/general.conf;
|
||||
}
|
||||
|
||||
# HTTP redirect
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name stream.graff.estate;
|
||||
include nginxconfig.io/letsencrypt.conf;
|
||||
|
||||
location / {
|
||||
return 301 https://stream.graff.estate$request_uri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user