initial import server-manager
This commit is contained in:
+6
-1
@@ -1,7 +1,12 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
.env
|
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
.env
|
||||||
|
|
||||||
|
*-state.json
|
||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.idea/
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"usedPorts": [
|
|
||||||
7777,
|
|
||||||
7778
|
|
||||||
],
|
|
||||||
"usedQueryPorts": [
|
|
||||||
27015,
|
|
||||||
27016
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"servers": [
|
|
||||||
{
|
|
||||||
"id": "srv-ba25028b",
|
|
||||||
"name": "[EU] druecktieR | Crimson",
|
|
||||||
"wrapperId": "wrp-8adcbbf2",
|
|
||||||
"port": 7777,
|
|
||||||
"queryPort": 27015,
|
|
||||||
"created": 1784578015578
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "srv-d70d5c3a",
|
|
||||||
"name": "[EU] druecktieR | Azure",
|
|
||||||
"wrapperId": "wrp-8adcbbf2",
|
|
||||||
"port": 7778,
|
|
||||||
"queryPort": 27016,
|
|
||||||
"created": 1784653753332
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
+15
-8
@@ -1,14 +1,21 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.QUERY_PORT_START = exports.GAME_PORT_START = exports.DEFAULT_DESIRED_SERVERS = exports.LIFECYCLE_CRASH_TIMEOUT = exports.LIFECYCLE_SCALE_COOLDOWN = exports.LIFECYCLE_SCALE_DOWN_THRESHOLD = exports.LIFECYCLE_MIN_UPTIME = exports.LIFECYCLE_STARTUP_GRACE_PERIOD = exports.LIFECYCLE_EMPTY_TIMEOUT = exports.LIFECYCLE_CHECK_INTERVAL = exports.RABBITMQ_URL = void 0;
|
exports.QUERY_PORT_START = exports.GAME_PORT_START = exports.DEFAULT_DESIRED_SERVERS = exports.LIFECYCLE_CRASH_RETENTION = exports.LIFECYCLE_CRASH_TIMEOUT = exports.LIFECYCLE_SCALE_COOLDOWN = exports.LIFECYCLE_STARTUP_GRACE_PERIOD = exports.LIFECYCLE_SCALE_DOWN_THRESHOLD = exports.LIFECYCLE_MIN_UPTIME = exports.LIFECYCLE_EMPTY_TIMEOUT = exports.LIFECYCLE_CHECK_INTERVAL = exports.RABBITMQ_URL = void 0;
|
||||||
exports.RABBITMQ_URL = "amqp://manager:gigi1337@192.168.1.74";
|
exports.RABBITMQ_URL = "amqp://manager:gigi1337@192.168.1.74";
|
||||||
exports.LIFECYCLE_CHECK_INTERVAL = 10000;
|
// Lifecycle
|
||||||
exports.LIFECYCLE_EMPTY_TIMEOUT = 300000;
|
exports.LIFECYCLE_CHECK_INTERVAL = 10000; // Alle 10 Sekunden prüfen
|
||||||
exports.LIFECYCLE_STARTUP_GRACE_PERIOD = 60000;
|
// Scale Down
|
||||||
exports.LIFECYCLE_MIN_UPTIME = 300000;
|
exports.LIFECYCLE_EMPTY_TIMEOUT = 300000; // 5 Minuten leer
|
||||||
exports.LIFECYCLE_SCALE_DOWN_THRESHOLD = 0.30;
|
exports.LIFECYCLE_MIN_UPTIME = 600000; // 10 Minuten Mindestlaufzeit
|
||||||
exports.LIFECYCLE_SCALE_COOLDOWN = 60000;
|
exports.LIFECYCLE_SCALE_DOWN_THRESHOLD = 0.30; // Unter 30% Gesamtauslastung darf abgebaut werden
|
||||||
exports.LIFECYCLE_CRASH_TIMEOUT = 30000;
|
// Scale Up
|
||||||
|
exports.LIFECYCLE_STARTUP_GRACE_PERIOD = 60000; // 1 Minute Schutz nach Start
|
||||||
|
exports.LIFECYCLE_SCALE_COOLDOWN = 120000; // 2 Minuten zwischen Scale-Up Aktionen
|
||||||
|
// Crash Detection
|
||||||
|
exports.LIFECYCLE_CRASH_TIMEOUT = 120000; // 2 Minuten ohne Status -> Crash
|
||||||
|
exports.LIFECYCLE_CRASH_RETENTION = 300000; // 5 Minuten sichtbar nach Crash
|
||||||
|
// Default
|
||||||
exports.DEFAULT_DESIRED_SERVERS = 1;
|
exports.DEFAULT_DESIRED_SERVERS = 1;
|
||||||
|
// Ports
|
||||||
exports.GAME_PORT_START = 7777;
|
exports.GAME_PORT_START = 7777;
|
||||||
exports.QUERY_PORT_START = 27015;
|
exports.QUERY_PORT_START = 27015;
|
||||||
|
|||||||
+18
-7
@@ -1,13 +1,24 @@
|
|||||||
export const RABBITMQ_URL = "amqp://manager:gigi1337@192.168.1.74";
|
export const RABBITMQ_URL = "amqp://manager:gigi1337@192.168.1.74";
|
||||||
|
|
||||||
export const LIFECYCLE_CHECK_INTERVAL = 10000;
|
// Lifecycle
|
||||||
export const LIFECYCLE_EMPTY_TIMEOUT = 300000;
|
export const LIFECYCLE_CHECK_INTERVAL = 10000; // Alle 10 Sekunden prüfen
|
||||||
export const LIFECYCLE_STARTUP_GRACE_PERIOD = 60000;
|
|
||||||
export const LIFECYCLE_MIN_UPTIME = 300000;
|
// Scale Down
|
||||||
export const LIFECYCLE_SCALE_DOWN_THRESHOLD = 0.30;
|
export const LIFECYCLE_EMPTY_TIMEOUT = 300000; // 5 Minuten leer
|
||||||
export const LIFECYCLE_SCALE_COOLDOWN = 60000;
|
export const LIFECYCLE_MIN_UPTIME = 600000; // 10 Minuten Mindestlaufzeit
|
||||||
export const LIFECYCLE_CRASH_TIMEOUT = 30000;
|
export const LIFECYCLE_SCALE_DOWN_THRESHOLD = 0.30; // Unter 30% Gesamtauslastung darf abgebaut werden
|
||||||
|
|
||||||
|
// Scale Up
|
||||||
|
export const LIFECYCLE_STARTUP_GRACE_PERIOD = 60000; // 1 Minute Schutz nach Start
|
||||||
|
export const LIFECYCLE_SCALE_COOLDOWN = 120000; // 2 Minuten zwischen Scale-Up Aktionen
|
||||||
|
|
||||||
|
// Crash Detection
|
||||||
|
export const LIFECYCLE_CRASH_TIMEOUT = 120000; // 2 Minuten ohne Status -> Crash
|
||||||
|
export const LIFECYCLE_CRASH_RETENTION = 300000; // 5 Minuten sichtbar nach Crash
|
||||||
|
|
||||||
|
// Default
|
||||||
export const DEFAULT_DESIRED_SERVERS = 1;
|
export const DEFAULT_DESIRED_SERVERS = 1;
|
||||||
|
|
||||||
|
// Ports
|
||||||
export const GAME_PORT_START = 7777;
|
export const GAME_PORT_START = 7777;
|
||||||
export const QUERY_PORT_START = 27015;
|
export const QUERY_PORT_START = 27015;
|
||||||
|
|||||||
@@ -51,6 +51,19 @@ class ServerLifecycle {
|
|||||||
logger.info("Server RUNNING:", server.name, "PID:", server.pid);
|
logger.info("Server RUNNING:", server.name, "PID:", server.pid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "RECOVERING":
|
||||||
|
if (Date.now() -
|
||||||
|
server.lastSeen
|
||||||
|
>
|
||||||
|
config_1.LIFECYCLE_CRASH_TIMEOUT) {
|
||||||
|
server.status =
|
||||||
|
"CRASHED";
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
this.serverRegistry.update(server);
|
||||||
|
logger.error("Server-Recovery fehlgeschlagen:", server.name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "RUNNING":
|
case "RUNNING":
|
||||||
/*
|
/*
|
||||||
Crash Detection
|
Crash Detection
|
||||||
@@ -61,6 +74,8 @@ class ServerLifecycle {
|
|||||||
config_1.LIFECYCLE_CRASH_TIMEOUT) {
|
config_1.LIFECYCLE_CRASH_TIMEOUT) {
|
||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
this.serverRegistry.update(server);
|
this.serverRegistry.update(server);
|
||||||
logger.error("Server abgestürzt:", server.name);
|
logger.error("Server abgestürzt:", server.name);
|
||||||
break;
|
break;
|
||||||
@@ -92,9 +107,22 @@ class ServerLifecycle {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "CRASHED":
|
case "CRASHED":
|
||||||
|
if (!server.crashedAt) {
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
this.serverRegistry.update(server);
|
||||||
logger.error("Server abgestürzt erkannt:", server.name);
|
logger.error("Server abgestürzt erkannt:", server.name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (Date.now() -
|
||||||
|
server.crashedAt
|
||||||
|
>
|
||||||
|
config_1.LIFECYCLE_CRASH_RETENTION) {
|
||||||
|
logger.info("Entferne abgestürzten Server nach Grace-Zeit:", server.name);
|
||||||
|
this.serverRegistry.remove(server.id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
AKTIVE SERVER
|
AKTIVE SERVER
|
||||||
@@ -102,7 +130,8 @@ class ServerLifecycle {
|
|||||||
const activeServers = this.serverRegistry
|
const activeServers = this.serverRegistry
|
||||||
.getAll()
|
.getAll()
|
||||||
.filter(server => server.status === "RUNNING" ||
|
.filter(server => server.status === "RUNNING" ||
|
||||||
server.status === "STARTING");
|
server.status === "STARTING" ||
|
||||||
|
server.status === "RECOVERING");
|
||||||
/*
|
/*
|
||||||
SLOT AUSLASTUNG
|
SLOT AUSLASTUNG
|
||||||
*/
|
*/
|
||||||
@@ -166,14 +195,14 @@ class ServerLifecycle {
|
|||||||
const activeCount = this.serverRegistry
|
const activeCount = this.serverRegistry
|
||||||
.getAll()
|
.getAll()
|
||||||
.filter(s => s.status === "RUNNING" ||
|
.filter(s => s.status === "RUNNING" ||
|
||||||
s.status === "STARTING")
|
s.status === "STARTING" ||
|
||||||
|
s.status === "RECOVERING")
|
||||||
.length;
|
.length;
|
||||||
if (activeCount <=
|
if (activeCount <=
|
||||||
this.desiredServers) {
|
this.desiredServers) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
logger.info("Stoppe leeren Server:", server.name);
|
logger.info("Stoppe leeren Server:", server.name);
|
||||||
logger.info("Stoppe leeren Server:", server.name);
|
|
||||||
this.serverManager.stopServer(server.id);
|
this.serverManager.stopServer(server.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
LIFECYCLE_SCALE_DOWN_THRESHOLD,
|
LIFECYCLE_SCALE_DOWN_THRESHOLD,
|
||||||
LIFECYCLE_SCALE_COOLDOWN,
|
LIFECYCLE_SCALE_COOLDOWN,
|
||||||
LIFECYCLE_CRASH_TIMEOUT,
|
LIFECYCLE_CRASH_TIMEOUT,
|
||||||
|
LIFECYCLE_CRASH_RETENTION,
|
||||||
DEFAULT_DESIRED_SERVERS
|
DEFAULT_DESIRED_SERVERS
|
||||||
} from "./config";
|
} from "./config";
|
||||||
|
|
||||||
@@ -178,6 +179,9 @@ export class ServerLifecycle {
|
|||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
|
||||||
this.serverRegistry.update(
|
this.serverRegistry.update(
|
||||||
server
|
server
|
||||||
@@ -218,6 +222,9 @@ export class ServerLifecycle {
|
|||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
|
||||||
this.serverRegistry.update(
|
this.serverRegistry.update(
|
||||||
server
|
server
|
||||||
@@ -317,12 +324,43 @@ export class ServerLifecycle {
|
|||||||
case "CRASHED":
|
case "CRASHED":
|
||||||
|
|
||||||
|
|
||||||
|
if(!server.crashedAt){
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
this.serverRegistry.update(
|
||||||
|
server
|
||||||
|
);
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
"Server abgestürzt erkannt:",
|
"Server abgestürzt erkannt:",
|
||||||
server.name
|
server.name
|
||||||
);
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(
|
||||||
|
Date.now() -
|
||||||
|
server.crashedAt
|
||||||
|
>
|
||||||
|
LIFECYCLE_CRASH_RETENTION
|
||||||
|
){
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Entferne abgestürzten Server nach Grace-Zeit:",
|
||||||
|
server.name
|
||||||
|
);
|
||||||
|
|
||||||
|
this.serverRegistry.remove(
|
||||||
|
server.id
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ServerRegistry {
|
|||||||
port: serverData.port,
|
port: serverData.port,
|
||||||
queryPort: serverData.queryPort,
|
queryPort: serverData.queryPort,
|
||||||
created: serverData.created,
|
created: serverData.created,
|
||||||
status: "STARTING",
|
status: "RECOVERING",
|
||||||
players: 0,
|
players: 0,
|
||||||
maxPlayers: 0,
|
maxPlayers: 0,
|
||||||
lastSeen: Date.now()
|
lastSeen: Date.now()
|
||||||
@@ -96,9 +96,14 @@ class ServerRegistry {
|
|||||||
logger.debug("Server cleanly stopped:", server.name);
|
logger.debug("Server cleanly stopped:", server.name);
|
||||||
this.remove(server.id);
|
this.remove(server.id);
|
||||||
}
|
}
|
||||||
else if (server.status === "RUNNING") {
|
else if (server.status === "RUNNING" ||
|
||||||
|
server.status === "RECOVERING") {
|
||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
if (!server.crashedAt) {
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
}
|
||||||
this.servers.set(server.id, server);
|
this.servers.set(server.id, server);
|
||||||
logger.warn("Server crashed:", server.name);
|
logger.warn("Server crashed:", server.name);
|
||||||
}
|
}
|
||||||
@@ -117,7 +122,9 @@ class ServerRegistry {
|
|||||||
server.lastSeen =
|
server.lastSeen =
|
||||||
Date.now();
|
Date.now();
|
||||||
const oldStatus = server.status;
|
const oldStatus = server.status;
|
||||||
if (srv.alive) {
|
if (srv.alive && server.status !== "STOPPING") {
|
||||||
|
server.crashedAt =
|
||||||
|
undefined;
|
||||||
if (!server.startedAt) {
|
if (!server.startedAt) {
|
||||||
server.startedAt =
|
server.startedAt =
|
||||||
srv.started;
|
srv.started;
|
||||||
@@ -125,9 +132,14 @@ class ServerRegistry {
|
|||||||
server.status =
|
server.status =
|
||||||
"RUNNING";
|
"RUNNING";
|
||||||
}
|
}
|
||||||
else if (server.status === "RUNNING") {
|
else if (server.status === "RUNNING" ||
|
||||||
|
server.status === "RECOVERING") {
|
||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
if (!server.crashedAt) {
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oldStatus !== server.status) {
|
if (oldStatus !== server.status) {
|
||||||
logger.debug("Status change:", server.name, oldStatus, "->", server.status);
|
logger.debug("Status change:", server.name, oldStatus, "->", server.status);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ export interface ServerInfo {
|
|||||||
|
|
||||||
startedAt?:number;
|
startedAt?:number;
|
||||||
|
|
||||||
|
crashedAt?:number;
|
||||||
|
|
||||||
lastSeen:number;
|
lastSeen:number;
|
||||||
|
|
||||||
|
|
||||||
@@ -357,6 +359,13 @@ export class ServerRegistry {
|
|||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
|
||||||
|
if(!server.crashedAt){
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.servers.set(
|
this.servers.set(
|
||||||
server.id,
|
server.id,
|
||||||
@@ -416,6 +425,9 @@ export class ServerRegistry {
|
|||||||
|
|
||||||
if(srv.alive && server.status !== "STOPPING"){
|
if(srv.alive && server.status !== "STOPPING"){
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
undefined;
|
||||||
|
|
||||||
if(!server.startedAt){
|
if(!server.startedAt){
|
||||||
|
|
||||||
server.startedAt =
|
server.startedAt =
|
||||||
@@ -435,6 +447,13 @@ export class ServerRegistry {
|
|||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
|
||||||
|
if(!server.crashedAt){
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class ServerStatusManager {
|
|||||||
return;
|
return;
|
||||||
server.status =
|
server.status =
|
||||||
"RUNNING";
|
"RUNNING";
|
||||||
|
server.crashedAt =
|
||||||
|
undefined;
|
||||||
if (!server.startedAt) {
|
if (!server.startedAt) {
|
||||||
server.startedAt =
|
server.startedAt =
|
||||||
Date.now();
|
Date.now();
|
||||||
@@ -48,6 +50,10 @@ class ServerStatusManager {
|
|||||||
return;
|
return;
|
||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
if (!server.crashedAt) {
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
}
|
||||||
this.registry.update(server);
|
this.registry.update(server);
|
||||||
logger.info("Server stopped:", data.serverId);
|
logger.info("Server stopped:", data.serverId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,9 @@ export class ServerStatusManager {
|
|||||||
server.status =
|
server.status =
|
||||||
"RUNNING";
|
"RUNNING";
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
undefined;
|
||||||
|
|
||||||
|
|
||||||
if(!server.startedAt){
|
if(!server.startedAt){
|
||||||
|
|
||||||
@@ -221,6 +224,13 @@ export class ServerStatusManager {
|
|||||||
server.status =
|
server.status =
|
||||||
"CRASHED";
|
"CRASHED";
|
||||||
|
|
||||||
|
if(!server.crashedAt){
|
||||||
|
|
||||||
|
server.crashedAt =
|
||||||
|
Date.now();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class WebApi {
|
|||||||
name: server.name,
|
name: server.name,
|
||||||
status: server.status,
|
status: server.status,
|
||||||
wrapperId: server.wrapperId,
|
wrapperId: server.wrapperId,
|
||||||
|
pid: server.pid,
|
||||||
port: server.port,
|
port: server.port,
|
||||||
queryPort: server.queryPort,
|
queryPort: server.queryPort,
|
||||||
players: server.players,
|
players: server.players,
|
||||||
@@ -95,6 +96,7 @@ class WebApi {
|
|||||||
name: server.name,
|
name: server.name,
|
||||||
status: server.status,
|
status: server.status,
|
||||||
wrapperId: server.wrapperId,
|
wrapperId: server.wrapperId,
|
||||||
|
pid: server.pid,
|
||||||
port: server.port,
|
port: server.port,
|
||||||
queryPort: server.queryPort,
|
queryPort: server.queryPort,
|
||||||
players: server.players,
|
players: server.players,
|
||||||
|
|||||||
+4
-1
@@ -6,5 +6,8 @@
|
|||||||
"wrapper",
|
"wrapper",
|
||||||
"shared",
|
"shared",
|
||||||
"dashboard"
|
"dashboard"
|
||||||
]
|
],
|
||||||
|
"allowScripts": {
|
||||||
|
"esbuild@0.21.5": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user