Add new daemon start script and update localization for director salary
- Introduced a new script `start-daemon` in `package.json` for running the daemon server. - Added translations for "director payed out" in both English and German localization files to enhance user notifications.
This commit is contained in:
98
backend/daemonServer.js
Normal file
98
backend/daemonServer.js
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import WebSocket, { WebSocketServer } from 'ws';
|
||||||
|
|
||||||
|
const PORT = 4551;
|
||||||
|
|
||||||
|
// Einfache In-Memory-Struktur für Verbindungen (für spätere Erweiterungen)
|
||||||
|
const connections = new Set();
|
||||||
|
|
||||||
|
function createServer() {
|
||||||
|
const wss = new WebSocketServer({ port: PORT });
|
||||||
|
|
||||||
|
console.log(`[Daemon] WebSocket-Server startet auf Port ${PORT} ...`);
|
||||||
|
|
||||||
|
wss.on('connection', (ws, req) => {
|
||||||
|
const peer = req.socket.remoteAddress + ':' + req.socket.remotePort;
|
||||||
|
ws.isAlive = true;
|
||||||
|
ws.userId = null;
|
||||||
|
connections.add(ws);
|
||||||
|
|
||||||
|
console.log(`[Daemon] Neue Verbindung von ${peer}`);
|
||||||
|
|
||||||
|
ws.on('message', (message) => {
|
||||||
|
try {
|
||||||
|
if (message.toString() === 'pong') {
|
||||||
|
// Client-Pong für unser Ping
|
||||||
|
ws.isAlive = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = JSON.parse(message.toString());
|
||||||
|
|
||||||
|
// Vom Frontend gesendet nach Verbindungsaufbau
|
||||||
|
if (data.event === 'setUserId' && data.data?.userId) {
|
||||||
|
ws.userId = data.data.userId;
|
||||||
|
console.log(`[Daemon] setUserId erhalten: ${ws.userId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin-Dialog: WebSocket-Log anfordern
|
||||||
|
if (data.event === 'getWebsocketLog') {
|
||||||
|
const response = {
|
||||||
|
event: 'getWebsocketLogResponse',
|
||||||
|
entries: [] // aktuell keine Log-Historie implementiert
|
||||||
|
};
|
||||||
|
ws.send(JSON.stringify(response));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Platzhalter für spätere Events
|
||||||
|
// console.log('[Daemon] Unbekanntes Event:', data);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Daemon] Fehler beim Verarbeiten einer Nachricht:', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('close', () => {
|
||||||
|
connections.delete(ws);
|
||||||
|
console.log('[Daemon] Verbindung geschlossen');
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('error', (err) => {
|
||||||
|
console.error('[Daemon] WebSocket-Fehler (Verbindung):', err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Einfache Ping/Pong-Mechanik, damit Verbindungen sauber erkannt werden
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
for (const ws of connections) {
|
||||||
|
if (ws.isAlive === false) {
|
||||||
|
console.log('[Daemon] Verbindung wegen fehlendem Pong beendet');
|
||||||
|
ws.terminate();
|
||||||
|
connections.delete(ws);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ws.isAlive = false;
|
||||||
|
try {
|
||||||
|
ws.send('ping');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Daemon] Fehler beim Senden von Ping:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
|
wss.on('close', () => {
|
||||||
|
clearInterval(interval);
|
||||||
|
connections.clear();
|
||||||
|
console.log('[Daemon] Server gestoppt');
|
||||||
|
});
|
||||||
|
|
||||||
|
wss.on('error', (err) => {
|
||||||
|
console.error('[Daemon] Server-Fehler:', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
return wss;
|
||||||
|
}
|
||||||
|
|
||||||
|
createServer();
|
||||||
|
|
||||||
|
|
||||||
@@ -378,16 +378,19 @@ export async function createTriggers() {
|
|||||||
tp.election_id,
|
tp.election_id,
|
||||||
tp.tp_office_type_id,
|
tp.tp_office_type_id,
|
||||||
tp.tp_election_date,
|
tp.tp_election_date,
|
||||||
(
|
COALESCE(
|
||||||
SELECT json_agg(vr)
|
(
|
||||||
FROM votes vr
|
SELECT json_agg(vr)
|
||||||
WHERE vr.election_id = tp.election_id
|
FROM votes vr
|
||||||
|
WHERE vr.election_id = tp.election_id
|
||||||
|
),
|
||||||
|
'[]'::json -- oder '{}'::json, wenn dir ein Objekt lieber ist
|
||||||
),
|
),
|
||||||
NOW() AS created_at,
|
NOW() AS created_at,
|
||||||
NOW() AS updated_at
|
NOW() AS updated_at
|
||||||
FROM to_process tp
|
FROM to_process tp
|
||||||
),
|
),
|
||||||
|
|
||||||
-- 10) Cleanup: Stimmen, Kandidaten und Wahlen löschen
|
-- 10) Cleanup: Stimmen, Kandidaten und Wahlen löschen
|
||||||
_del_votes AS (
|
_del_votes AS (
|
||||||
DELETE FROM falukant_data.vote
|
DELETE FROM falukant_data.vote
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
"dev": "NODE_ENV=development node server.js",
|
"dev": "NODE_ENV=development node server.js",
|
||||||
|
"start-daemon": "node daemonServer.js",
|
||||||
"sync-db": "node sync-database.js",
|
"sync-db": "node sync-database.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -409,6 +409,7 @@
|
|||||||
"Sell all products": "Alle Produkte verkauft",
|
"Sell all products": "Alle Produkte verkauft",
|
||||||
"sell products": "Produkte verkauft",
|
"sell products": "Produkte verkauft",
|
||||||
"director starts production": "Direktor beginnt Produktion",
|
"director starts production": "Direktor beginnt Produktion",
|
||||||
|
"director payed out": "Direktorgehalt ausgezahlt",
|
||||||
"Buy storage (type: field)": "Lagerplatz gekauft (Typ: Feld)",
|
"Buy storage (type: field)": "Lagerplatz gekauft (Typ: Feld)",
|
||||||
"Buy storage (type: iron)": "Lagerplatz gekauft (Typ: Eisen)",
|
"Buy storage (type: iron)": "Lagerplatz gekauft (Typ: Eisen)",
|
||||||
"Buy storage (type: stone)": "Lagerplatz gekauft (Typ: Stein)",
|
"Buy storage (type: stone)": "Lagerplatz gekauft (Typ: Stein)",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"Sell all products": "Sell all products",
|
"Sell all products": "Sell all products",
|
||||||
"sell products": "Sell products",
|
"sell products": "Sell products",
|
||||||
"director starts production": "Director starts production",
|
"director starts production": "Director starts production",
|
||||||
|
"director payed out": "Director salary paid out",
|
||||||
"Buy storage (type: field)": "Bought storage (type: field)",
|
"Buy storage (type: field)": "Bought storage (type: field)",
|
||||||
"Buy storage (type: iron)": "Bought storage (type: iron)",
|
"Buy storage (type: iron)": "Bought storage (type: iron)",
|
||||||
"Buy storage (type: stone)": "Bought storage (type: stone)",
|
"Buy storage (type: stone)": "Bought storage (type: stone)",
|
||||||
|
|||||||
Reference in New Issue
Block a user