Scheduler: Autostart-Feature entfernen
Der Scheduler startet niemals automatisch beim Programmstart. Der Nutzer startet ihn ausschliesslich bewusst ueber den Start-Button im Scheduler-Tab. scheduler.enabled wird nicht mehr gelesen oder geschrieben; das Property ist obsolet. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+1
-24
@@ -56,7 +56,6 @@ public class FileChannelConfigurationAccessAdapter
|
||||
private static final long ACQUIRE_TIMEOUT_MS = 3000L;
|
||||
private static final long ACQUIRE_RETRY_INTERVAL_MS = 100L;
|
||||
|
||||
private static final String KEY_ENABLED = "scheduler.enabled";
|
||||
private static final String KEY_INTERVAL = "scheduler.interval.seconds";
|
||||
|
||||
private final Path configFile;
|
||||
@@ -191,23 +190,8 @@ public class FileChannelConfigurationAccessAdapter
|
||||
+ "Standardwerte werden verwendet. Datei: {}", configFile, e);
|
||||
return SchedulerSettings.defaults();
|
||||
}
|
||||
boolean enabled = parseEnabled(props.getProperty(KEY_ENABLED));
|
||||
int intervalSeconds = parseInterval(props.getProperty(KEY_INTERVAL));
|
||||
return new SchedulerSettings(enabled, intervalSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt den Wert von {@code scheduler.enabled} in die Konfigurationsdatei.
|
||||
* <p>
|
||||
* Alle übrigen Inhalte der Datei bleiben unverändert. Existiert der Key
|
||||
* noch nicht, wird er am Ende der Datei ergänzt.
|
||||
*
|
||||
* @param enabled neuer Wert für {@code scheduler.enabled}
|
||||
* @throws SchedulerSettingsWriteException wenn der Schreibvorgang fehlschlägt
|
||||
*/
|
||||
@Override
|
||||
public void saveEnabled(boolean enabled) throws SchedulerSettingsWriteException {
|
||||
updateProperty(KEY_ENABLED, String.valueOf(enabled));
|
||||
return new SchedulerSettings(intervalSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,13 +213,6 @@ public class FileChannelConfigurationAccessAdapter
|
||||
// Hilfsmethoden: Parsen
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private boolean parseEnabled(String raw) {
|
||||
if (raw == null || raw.isBlank()) {
|
||||
return SchedulerSettings.DEFAULT_ENABLED;
|
||||
}
|
||||
return Boolean.parseBoolean(raw.trim());
|
||||
}
|
||||
|
||||
private int parseInterval(String raw) {
|
||||
if (raw == null || raw.isBlank()) {
|
||||
return SchedulerSettings.DEFAULT_INTERVAL_SECONDS;
|
||||
|
||||
+45
-130
@@ -16,22 +16,12 @@ import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationFileLockException;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.SchedulerSettings;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.SchedulerSettingsWriteException;
|
||||
|
||||
/**
|
||||
* Unit-Tests für {@link FileChannelConfigurationAccessAdapter}.
|
||||
* <p>
|
||||
* Deckt das Lock-Protokoll (Erwerb, Freigabe, Idempotenz), die Settings-Lese-
|
||||
* und Schreiblogik sowie die format-erhaltenden Zeileneigenschaften ab.
|
||||
* Alle Tests arbeiten auf einer temporären {@code .properties}-Datei im
|
||||
* JUnit-eigenen {@code @TempDir}.
|
||||
*/
|
||||
class FileChannelConfigurationAccessAdapterTest {
|
||||
|
||||
// =========================================================================
|
||||
// Lock-Protokoll
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void isLocked_returnsFalseBeforeAnyAcquire(@TempDir Path tempDir) throws IOException {
|
||||
Path config = createConfigFile(tempDir, "");
|
||||
@@ -115,10 +105,6 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
.isInstanceOf(ConfigurationFileLockException.class);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// loadSettings
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void loadSettings_returnsDefaultsWhenKeysAreMissing(@TempDir Path tempDir) throws IOException {
|
||||
Path config = createConfigFile(tempDir, "source.folder=S:\\source\n");
|
||||
@@ -127,27 +113,25 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
|
||||
SchedulerSettings settings = adapter.loadSettings();
|
||||
|
||||
assertThat(settings.enabled()).isEqualTo(SchedulerSettings.DEFAULT_ENABLED);
|
||||
assertThat(settings.intervalSeconds()).isEqualTo(SchedulerSettings.DEFAULT_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadSettings_returnsConfiguredValues(@TempDir Path tempDir) throws IOException {
|
||||
String content = "scheduler.enabled=true\nscheduler.interval.seconds=300\n";
|
||||
String content = "scheduler.interval.seconds=300\n";
|
||||
Path config = createConfigFile(tempDir, content);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
SchedulerSettings settings = adapter.loadSettings();
|
||||
|
||||
assertThat(settings.enabled()).isTrue();
|
||||
assertThat(settings.intervalSeconds()).isEqualTo(300);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadSettings_returnsDefaultIntervalForNonNumericValue(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String content = "scheduler.enabled=false\nscheduler.interval.seconds=not-a-number\n";
|
||||
String content = "scheduler.interval.seconds=not-a-number\n";
|
||||
Path config = createConfigFile(tempDir, content);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
@@ -157,19 +141,6 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
assertThat(settings.intervalSeconds()).isEqualTo(SchedulerSettings.DEFAULT_INTERVAL_SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadSettings_returnsDefaultEnabledForBlankValue(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String content = "scheduler.enabled=\nscheduler.interval.seconds=180\n";
|
||||
Path config = createConfigFile(tempDir, content);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
SchedulerSettings settings = adapter.loadSettings();
|
||||
|
||||
assertThat(settings.enabled()).isEqualTo(SchedulerSettings.DEFAULT_ENABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadSettings_returnsDefaultsWhenFileIsEmpty(@TempDir Path tempDir) throws IOException {
|
||||
Path config = createConfigFile(tempDir, "");
|
||||
@@ -181,78 +152,10 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
assertThat(settings).isEqualTo(SchedulerSettings.defaults());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// saveEnabled
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void saveEnabled_updatesExistingKeyAndPreservesOtherLines(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String initial = "source.folder=/opt/source\nscheduler.enabled=false\ntarget.folder=/opt/target\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveEnabled(true);
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.enabled")).isEqualTo("true");
|
||||
assertThat(props.getProperty("source.folder")).isEqualTo("/opt/source");
|
||||
assertThat(props.getProperty("target.folder")).isEqualTo("/opt/target");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEnabled_appendsKeyWhenMissing(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "source.folder=/opt/source\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveEnabled(true);
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.enabled")).isEqualTo("true");
|
||||
assertThat(props.getProperty("source.folder")).isEqualTo("/opt/source");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEnabled_writesCorrectlyThroughChannelWhenLocked(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String initial = "scheduler.enabled=false\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.acquireLock();
|
||||
try {
|
||||
adapter.saveEnabled(true);
|
||||
} finally {
|
||||
adapter.releaseLock();
|
||||
}
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.enabled")).isEqualTo("true");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEnabled_throwsSchedulerSettingsWriteException_whenFileDoesNotExist(
|
||||
@TempDir Path tempDir) {
|
||||
Path nonExistent = tempDir.resolve("missing.properties");
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(nonExistent);
|
||||
|
||||
assertThatThrownBy(() -> adapter.saveEnabled(true))
|
||||
.isInstanceOf(SchedulerSettingsWriteException.class);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// saveIntervalSeconds
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void saveIntervalSeconds_updatesExistingKeyAndPreservesOtherLines(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String initial = "scheduler.interval.seconds=180\nscheduler.enabled=false\n";
|
||||
String initial = "source.folder=/opt/source\nscheduler.interval.seconds=180\ntarget.folder=/opt/target\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
@@ -261,12 +164,13 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.interval.seconds")).isEqualTo("300");
|
||||
assertThat(props.getProperty("scheduler.enabled")).isEqualTo("false");
|
||||
assertThat(props.getProperty("source.folder")).isEqualTo("/opt/source");
|
||||
assertThat(props.getProperty("target.folder")).isEqualTo("/opt/target");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveIntervalSeconds_appendsKeyWhenMissing(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "scheduler.enabled=true\n";
|
||||
String initial = "source.folder=/opt/source\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
@@ -275,47 +179,58 @@ class FileChannelConfigurationAccessAdapterTest {
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.interval.seconds")).isEqualTo("240");
|
||||
assertThat(props.getProperty("scheduler.enabled")).isEqualTo("true");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Zeilenenden-Erhaltung
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
void saveEnabled_preservesCrlfLineEndings(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "scheduler.enabled=false\r\nother.key=value\r\n";
|
||||
Path config = createConfigFileBinary(tempDir, initial.getBytes(StandardCharsets.UTF_8));
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveEnabled(true);
|
||||
|
||||
byte[] resultBytes = Files.readAllBytes(config);
|
||||
String result = new String(resultBytes, StandardCharsets.UTF_8);
|
||||
assertThat(result).contains("scheduler.enabled=true\r\n");
|
||||
assertThat(result).contains("other.key=value\r\n");
|
||||
assertThat(props.getProperty("source.folder")).isEqualTo("/opt/source");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEnabled_preservesLfLineEndings(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "scheduler.enabled=false\nother.key=value\n";
|
||||
void saveIntervalSeconds_writesCorrectlyThroughChannelWhenLocked(@TempDir Path tempDir)
|
||||
throws IOException {
|
||||
String initial = "scheduler.interval.seconds=180\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveEnabled(true);
|
||||
adapter.acquireLock();
|
||||
try {
|
||||
adapter.saveIntervalSeconds(300);
|
||||
} finally {
|
||||
adapter.releaseLock();
|
||||
}
|
||||
|
||||
Properties props = loadProperties(config);
|
||||
assertThat(props.getProperty("scheduler.interval.seconds")).isEqualTo("300");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveIntervalSeconds_preservesCrlfLineEndings(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "scheduler.interval.seconds=180\r\nother.key=value\r\n";
|
||||
Path config = createConfigFileBinary(tempDir, initial.getBytes(StandardCharsets.UTF_8));
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveIntervalSeconds(300);
|
||||
|
||||
byte[] resultBytes = Files.readAllBytes(config);
|
||||
String result = new String(resultBytes, StandardCharsets.UTF_8);
|
||||
assertThat(result).contains("scheduler.interval.seconds=300\r\n");
|
||||
assertThat(result).contains("other.key=value\r\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveIntervalSeconds_preservesLfLineEndings(@TempDir Path tempDir) throws IOException {
|
||||
String initial = "scheduler.interval.seconds=180\nother.key=value\n";
|
||||
Path config = createConfigFile(tempDir, initial);
|
||||
FileChannelConfigurationAccessAdapter adapter =
|
||||
new FileChannelConfigurationAccessAdapter(config);
|
||||
|
||||
adapter.saveIntervalSeconds(300);
|
||||
|
||||
String result = Files.readString(config, StandardCharsets.UTF_8);
|
||||
assertThat(result).contains("scheduler.enabled=true\n");
|
||||
assertThat(result).contains("scheduler.interval.seconds=300\n");
|
||||
assertThat(result).contains("other.key=value\n");
|
||||
assertThat(result).doesNotContain("\r\n");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Hilfsmethoden
|
||||
// =========================================================================
|
||||
|
||||
private static Path createConfigFile(Path tempDir, String content) throws IOException {
|
||||
Path config = tempDir.resolve("test.properties");
|
||||
Files.writeString(config, content, StandardCharsets.UTF_8);
|
||||
|
||||
Reference in New Issue
Block a user