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.ApplicationContext;
|
||||||
import vassistent.bootstrap.ApplicationInitializer;
|
import vassistent.bootstrap.ApplicationInitializer;
|
||||||
|
import vassistent.bootstrap.ApplicationShutdownManager;
|
||||||
import vassistent.controller.AppWindowController;
|
import vassistent.controller.AppWindowController;
|
||||||
import vassistent.service.*;
|
|
||||||
import vassistent.util.Logger;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point for the virtual health assistant desktop application.
|
* Entry point for the virtual health assistant desktop application.
|
||||||
@ -26,44 +23,13 @@ public class App {
|
|||||||
ApplicationContext context =
|
ApplicationContext context =
|
||||||
ApplicationInitializer.initialize();
|
ApplicationInitializer.initialize();
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
ApplicationShutdownManager shutdownManager =
|
||||||
|
new ApplicationShutdownManager(context);
|
||||||
Logger.info("SYSTEM", "Programm wird beendet");
|
shutdownManager.registerJvmShutdownHook();
|
||||||
|
|
||||||
deleteDatabase();
|
|
||||||
|
|
||||||
Logger.shutdown();
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
new AppWindowController(context)
|
new AppWindowController(context, shutdownManager)
|
||||||
.createAndShowWindow();
|
.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.service.ProcessManagerService;
|
||||||
import vassistent.util.Logger;
|
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 {
|
public class ApplicationShutdownManager {
|
||||||
|
|
||||||
|
private static final String RUNTIME_DB_FILE = "data/health.db";
|
||||||
|
|
||||||
private final ApplicationContext context;
|
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
|
* @param context initialized application context
|
||||||
*/
|
*/
|
||||||
public ApplicationShutdownManager(ApplicationContext context) {
|
public ApplicationShutdownManager(ApplicationContext context) {
|
||||||
this.context = 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(
|
Runtime.getRuntime().addShutdownHook(
|
||||||
new Thread(this::shutdown)
|
new Thread(this::shutdown)
|
||||||
@ -28,11 +44,18 @@ public class ApplicationShutdownManager {
|
|||||||
* Executes shutdown steps for managed integrations.
|
* Executes shutdown steps for managed integrations.
|
||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
if (!shutdownStarted.compareAndSet(false, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Logger.info("SHUTDOWN", "Shutdown Sequencing gestartet");
|
Logger.info("SHUTDOWN", "Shutdown sequencing started");
|
||||||
|
|
||||||
disconnectMqtt();
|
disconnectMqtt();
|
||||||
stopExternalProcesses();
|
stopExternalProcesses();
|
||||||
|
deleteRuntimeDatabase();
|
||||||
|
|
||||||
|
Logger.info("SHUTDOWN", "Shutdown sequencing finished");
|
||||||
|
Logger.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,9 +70,9 @@ public class ApplicationShutdownManager {
|
|||||||
mqtt.disconnect();
|
mqtt.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("SHUTDOWN", "MQTT getrennt");
|
Logger.info("SHUTDOWN", "MQTT disconnected");
|
||||||
} catch (Exception e) {
|
} 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();
|
pm.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.info("SHUTDOWN", "Externe Prozesse beendet");
|
Logger.info("SHUTDOWN", "External processes stopped");
|
||||||
|
|
||||||
} catch (Exception e) {
|
} 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.*;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the main window lifecycle and synchronizes UI elements with app state.
|
* 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.
|
* Creates a controller for the main application window.
|
||||||
*
|
*
|
||||||
* @param context initialized application context with required services
|
* @param context initialized application context with required services
|
||||||
|
* @param shutdownManager shutdown coordinator shared with application bootstrap
|
||||||
*/
|
*/
|
||||||
public AppWindowController(ApplicationContext context) {
|
public AppWindowController(
|
||||||
this.context = context;
|
ApplicationContext context,
|
||||||
this.shutdownManager = new ApplicationShutdownManager(context);
|
ApplicationShutdownManager shutdownManager
|
||||||
|
) {
|
||||||
|
this.context = Objects.requireNonNull(context);
|
||||||
|
this.shutdownManager = Objects.requireNonNull(shutdownManager);
|
||||||
subscribeAppState();
|
subscribeAppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user