136 lines
5.5 KiB
C++
136 lines
5.5 KiB
C++
#include "character_creation_worker.h"
|
|
#include "produce_worker.h"
|
|
#include "stockagemanager.h"
|
|
#include "director_worker.h"
|
|
#include "valuerecalculationworker.h"
|
|
#include "connection_pool.h"
|
|
#include "websocket_server.h"
|
|
#include "message_broker.h"
|
|
#include "usercharacterworker.h"
|
|
#include "houseworker.h"
|
|
#include "politics_worker.h"
|
|
#include "underground_worker.h"
|
|
#include "config.h"
|
|
#include <csignal>
|
|
#include <atomic>
|
|
#include <iostream>
|
|
#include <thread>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <cstdlib>
|
|
#include <systemd/sd-daemon.h>
|
|
|
|
std::atomic<bool> keepRunning(true);
|
|
std::atomic<bool> shutdownRequested(false);
|
|
|
|
void handleSignal(int signal) {
|
|
std::cerr << "Signal erhalten: " << signal << ". Beende Anwendung..." << std::endl;
|
|
|
|
if (signal == SIGINT || signal == SIGTERM) {
|
|
std::cerr << "Setze Shutdown-Flags..." << std::endl;
|
|
keepRunning.store(false, std::memory_order_relaxed);
|
|
shutdownRequested.store(true, std::memory_order_relaxed);
|
|
std::cerr << "Shutdown-Flags gesetzt. keepRunning=" << keepRunning.load() << ", shutdownRequested=" << shutdownRequested.load() << std::endl;
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
std::signal(SIGINT, handleSignal);
|
|
std::signal(SIGTERM, handleSignal);
|
|
|
|
try {
|
|
Config config("/etc/yourpart/daemon.conf");
|
|
ConnectionPool pool(
|
|
config.get("DB_HOST"),
|
|
config.get("DB_PORT"),
|
|
config.get("DB_NAME"),
|
|
config.get("DB_USER"),
|
|
config.get("DB_PASSWORD"),
|
|
10
|
|
);
|
|
int websocketPort = std::stoi(config.get("WEBSOCKET_PORT"));
|
|
bool sslEnabled = config.get("WEBSOCKET_SSL_ENABLED") == "true";
|
|
std::string certPath = sslEnabled ? config.get("WEBSOCKET_SSL_CERT_PATH") : "";
|
|
std::string keyPath = sslEnabled ? config.get("WEBSOCKET_SSL_KEY_PATH") : "";
|
|
|
|
MessageBroker broker;
|
|
WebSocketServer websocketServer(websocketPort, pool, broker, sslEnabled, certPath, keyPath);
|
|
// Use C++23 features for better performance
|
|
std::vector<std::unique_ptr<Worker>> workers;
|
|
workers.reserve(9); // Pre-allocate for better performance
|
|
|
|
workers.emplace_back(std::make_unique<CharacterCreationWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<ProduceWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<StockageManager>(pool, broker));
|
|
workers.emplace_back(std::make_unique<DirectorWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<ValueRecalculationWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<UserCharacterWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<HouseWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<PoliticsWorker>(pool, broker));
|
|
workers.emplace_back(std::make_unique<UndergroundWorker>(pool, broker));
|
|
websocketServer.setWorkers(workers);
|
|
|
|
broker.start();
|
|
websocketServer.run();
|
|
for (auto &worker : workers) {
|
|
worker->startWorkerThread();
|
|
worker->enableWatchdog();
|
|
}
|
|
|
|
// Benachrichtige systemd, dass der Service bereit ist
|
|
sd_notify(0, "READY=1");
|
|
|
|
// Hauptschleife mit besserer Signal-Behandlung
|
|
std::cerr << "Hauptschleife gestartet. keepRunning=" << keepRunning.load() << ", shutdownRequested=" << shutdownRequested.load() << std::endl;
|
|
while (keepRunning.load() && !shutdownRequested.load()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
std::cerr << "Hauptschleife beendet. keepRunning=" << keepRunning.load() << ", shutdownRequested=" << shutdownRequested.load() << std::endl;
|
|
|
|
std::cerr << "Starte sauberes Herunterfahren..." << std::endl;
|
|
|
|
auto shutdownStart = std::chrono::steady_clock::now();
|
|
const auto maxShutdownTime = std::chrono::seconds(10);
|
|
|
|
// Stoppe alle Worker-Threads
|
|
std::cerr << "Stoppe Worker-Threads..." << std::endl;
|
|
for (auto &worker : workers) {
|
|
worker->stopWorkerThread();
|
|
if (std::chrono::steady_clock::now() - shutdownStart > maxShutdownTime) {
|
|
std::cerr << "Shutdown-Timeout erreicht, erzwinge Beendigung..." << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Stoppe Watchdog-Threads
|
|
std::cerr << "Stoppe Watchdog-Threads..." << std::endl;
|
|
for (auto &worker : workers) {
|
|
worker->stopWatchdogThread();
|
|
if (std::chrono::steady_clock::now() - shutdownStart > maxShutdownTime) {
|
|
std::cerr << "Shutdown-Timeout erreicht, erzwinge Beendigung..." << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Stoppe WebSocket Server
|
|
std::cerr << "Stoppe WebSocket-Server..." << std::endl;
|
|
websocketServer.stop();
|
|
|
|
// Stoppe Message Broker
|
|
std::cerr << "Stoppe Message Broker..." << std::endl;
|
|
broker.stop();
|
|
|
|
auto shutdownDuration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::steady_clock::now() - shutdownStart);
|
|
std::cerr << "Anwendung erfolgreich beendet in " << shutdownDuration.count() << "ms." << std::endl;
|
|
|
|
// Erzwinge sofortiges Exit nach Shutdown
|
|
std::cerr << "Erzwinge Prozess-Beendigung..." << std::endl;
|
|
std::_Exit(0);
|
|
} catch (const std::exception &e) {
|
|
std::cerr << "Fehler: " << e.what() << std::endl;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|