Optimzed ShutdownManager for only one clean shutdown
This commit is contained in:
parent
0804b48d68
commit
6478e046b4
@ -2,13 +2,10 @@ package vassistent;
|
||||
|
||||
import vassistent.bootstrap.ApplicationContext;
|
||||
import vassistent.bootstrap.ApplicationInitializer;
|
||||
import vassistent.bootstrap.ApplicationShutdownManager;
|
||||
import vassistent.controller.AppWindowController;
|
||||
import vassistent.service.*;
|
||||
import vassistent.util.Logger;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/**
|
||||
* Entry point for the virtual health assistant desktop application.
|
||||
@ -26,44 +23,13 @@ public class App {
|
||||
ApplicationContext context =
|
||||
ApplicationInitializer.initialize();
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
|
||||
Logger.info("SYSTEM", "Programm wird beendet");
|
||||
|
||||
deleteDatabase();
|
||||
|
||||
Logger.shutdown();
|
||||
|
||||
}));
|
||||
ApplicationShutdownManager shutdownManager =
|
||||
new ApplicationShutdownManager(context);
|
||||
shutdownManager.registerJvmShutdownHook();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
new AppWindowController(context)
|
||||
new AppWindowController(context, shutdownManager)
|
||||
.createAndShowWindow();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the runtime SQLite database file if it exists.
|
||||
*/
|
||||
private static void deleteDatabase() {
|
||||
|
||||
try {
|
||||
|
||||
File dbFile = new File("data/health.db");
|
||||
|
||||
if (dbFile.exists()) {
|
||||
|
||||
boolean deleted = dbFile.delete();
|
||||
|
||||
if (deleted) {
|
||||
Logger.info("SYSTEM", "Datenbank gelöscht");
|
||||
} else {
|
||||
Logger.warn("SYSTEM", "Datenbank konnte nicht gelöscht werden");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error("SYSTEM", "DB Löschung fehlgeschlagen", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,20 +4,36 @@ import vassistent.service.MqttClientService;
|
||||
import vassistent.service.ProcessManagerService;
|
||||
import vassistent.util.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Coordinates graceful shutdown of MQTT and managed external processes.
|
||||
* Coordinates graceful shutdown of MQTT, managed external processes, and runtime artifacts.
|
||||
*/
|
||||
public class ApplicationShutdownManager {
|
||||
|
||||
private static final String RUNTIME_DB_FILE = "data/health.db";
|
||||
|
||||
private final ApplicationContext context;
|
||||
private final AtomicBoolean shutdownStarted = new AtomicBoolean(false);
|
||||
private final AtomicBoolean shutdownHookRegistered = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* Creates a shutdown manager and registers a JVM shutdown hook.
|
||||
* Creates a shutdown manager for the provided application context.
|
||||
*
|
||||
* @param context initialized application context
|
||||
*/
|
||||
public ApplicationShutdownManager(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the JVM shutdown hook once for this manager instance.
|
||||
*/
|
||||
public void registerJvmShutdownHook() {
|
||||
if (!shutdownHookRegistered.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(
|
||||
new Thread(this::shutdown)
|
||||
@ -28,11 +44,18 @@ public class ApplicationShutdownManager {
|
||||
* Executes shutdown steps for managed integrations.
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (!shutdownStarted.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.info("SHUTDOWN", "Shutdown Sequencing gestartet");
|
||||
Logger.info("SHUTDOWN", "Shutdown sequencing started");
|
||||
|
||||
disconnectMqtt();
|
||||
stopExternalProcesses();
|
||||
deleteRuntimeDatabase();
|
||||
|
||||
Logger.info("SHUTDOWN", "Shutdown sequencing finished");
|
||||
Logger.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,9 +70,9 @@ public class ApplicationShutdownManager {
|
||||
mqtt.disconnect();
|
||||
}
|
||||
|
||||
Logger.info("SHUTDOWN", "MQTT getrennt");
|
||||
Logger.info("SHUTDOWN", "MQTT disconnected");
|
||||
} catch (Exception e) {
|
||||
Logger.error("SHUTDOWN", "MQTT Shutdown Fehler", e);
|
||||
Logger.error("SHUTDOWN", "MQTT shutdown failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,10 +89,36 @@ public class ApplicationShutdownManager {
|
||||
pm.shutdown();
|
||||
}
|
||||
|
||||
Logger.info("SHUTDOWN", "Externe Prozesse beendet");
|
||||
Logger.info("SHUTDOWN", "External processes stopped");
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error("SHUWTDOWN", "Process Shutdown Fehler", e);
|
||||
Logger.error("SHUTDOWN", "Process shutdown failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the runtime SQLite database file when present.
|
||||
*/
|
||||
private void deleteRuntimeDatabase() {
|
||||
|
||||
try {
|
||||
|
||||
File dbFile = new File(RUNTIME_DB_FILE);
|
||||
|
||||
if (!dbFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean deleted = dbFile.delete();
|
||||
|
||||
if (deleted) {
|
||||
Logger.info("SHUTDOWN", "Runtime database deleted");
|
||||
} else {
|
||||
Logger.warn("SHUTDOWN", "Runtime database could not be deleted");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error("SHUTDOWN", "Runtime database deletion failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Controls the main window lifecycle and synchronizes UI elements with app state.
|
||||
@ -27,10 +28,14 @@ public class AppWindowController {
|
||||
* Creates a controller for the main application window.
|
||||
*
|
||||
* @param context initialized application context with required services
|
||||
* @param shutdownManager shutdown coordinator shared with application bootstrap
|
||||
*/
|
||||
public AppWindowController(ApplicationContext context) {
|
||||
this.context = context;
|
||||
this.shutdownManager = new ApplicationShutdownManager(context);
|
||||
public AppWindowController(
|
||||
ApplicationContext context,
|
||||
ApplicationShutdownManager shutdownManager
|
||||
) {
|
||||
this.context = Objects.requireNonNull(context);
|
||||
this.shutdownManager = Objects.requireNonNull(shutdownManager);
|
||||
subscribeAppState();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user