M2 Vorläufige Freigabe nach Sonnet-Review
This commit is contained in:
@@ -3,7 +3,6 @@ package de.gecheckt.pdf.umbenenner.application.usecase;
|
||||
import de.gecheckt.pdf.umbenenner.application.config.StartConfiguration;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.RunBatchProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.RunLockPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.RunLockUnavailableException;
|
||||
import de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext;
|
||||
@@ -21,8 +20,7 @@ import org.apache.logging.log4j.Logger;
|
||||
* <ul>
|
||||
* <li>Acquire exclusive run lock to prevent concurrent instances</li>
|
||||
* <li>Initialize batch execution with the provided run context</li>
|
||||
* <li>Coordinate outbound port interactions (configuration, lock management)</li>
|
||||
* <li>Release lock and finish cleanly regardless of execution path</li>
|
||||
* <li>Release lock only if it was successfully acquired</li>
|
||||
* <li>Return structured outcome for Bootstrap exit code mapping</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
@@ -45,40 +43,42 @@ public class M2BatchRunProcessingUseCase implements RunBatchProcessingUseCase {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(M2BatchRunProcessingUseCase.class);
|
||||
|
||||
private final ConfigurationPort configurationPort;
|
||||
private final StartConfiguration configuration;
|
||||
private final RunLockPort runLockPort;
|
||||
|
||||
/**
|
||||
* Creates the M2 batch use case with required outbound ports.
|
||||
* Creates the M2 batch use case with the already-loaded startup configuration and run lock port.
|
||||
* <p>
|
||||
* The configuration is loaded and validated by Bootstrap before use case creation;
|
||||
* the use case receives the result directly and does not re-read it.
|
||||
*
|
||||
* @param configurationPort for loading startup configuration
|
||||
* @param configuration the validated startup configuration
|
||||
* @param runLockPort for exclusive run locking
|
||||
* @throws NullPointerException if any port is null
|
||||
* @throws NullPointerException if any parameter is null
|
||||
*/
|
||||
public M2BatchRunProcessingUseCase(ConfigurationPort configurationPort, RunLockPort runLockPort) {
|
||||
this.configurationPort = configurationPort;
|
||||
public M2BatchRunProcessingUseCase(StartConfiguration configuration, RunLockPort runLockPort) {
|
||||
this.configuration = configuration;
|
||||
this.runLockPort = runLockPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchRunOutcome execute(BatchRunContext context) {
|
||||
LOG.info("M2 batch processing initiated with RunId: {}", context.runId());
|
||||
boolean lockAcquired = false;
|
||||
|
||||
try {
|
||||
// Step 1: Acquire exclusive run lock (prevents concurrent instances)
|
||||
try {
|
||||
runLockPort.acquire();
|
||||
lockAcquired = true;
|
||||
LOG.debug("Run lock acquired successfully.");
|
||||
} catch (RunLockUnavailableException e) {
|
||||
LOG.warn("Run lock not available – another instance is already running. This instance terminates immediately.");
|
||||
return BatchRunOutcome.LOCK_UNAVAILABLE;
|
||||
}
|
||||
|
||||
// Step 2: Load configuration (already validated in Bootstrap, but accessible to use case)
|
||||
StartConfiguration config = configurationPort.loadConfiguration();
|
||||
LOG.debug("Configuration available: source={}, target={}", config.sourceFolder(), config.targetFolder());
|
||||
|
||||
// Step 3: M2 Batch execution frame (no document processing)
|
||||
// Step 2: M2 Batch execution frame (no document processing)
|
||||
LOG.debug("Configuration in use: source={}, target={}", configuration.sourceFolder(), configuration.targetFolder());
|
||||
LOG.info("Batch execution frame initialized - RunId: {}, Start: {}", context.runId(), context.startInstant());
|
||||
|
||||
// M2 Non-goal: No source folder scanning, PDF processing, persistence, or filename generation
|
||||
@@ -92,12 +92,16 @@ public class M2BatchRunProcessingUseCase implements RunBatchProcessingUseCase {
|
||||
LOG.error("Unexpected error during batch processing", e);
|
||||
return BatchRunOutcome.FAILURE;
|
||||
} finally {
|
||||
// Step 4: Always release the run lock (critical for M2 start protection)
|
||||
try {
|
||||
runLockPort.release();
|
||||
LOG.debug("Run lock released");
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Warning: Failed to release run lock", e);
|
||||
// Release the run lock only if it was successfully acquired.
|
||||
// If acquire() threw RunLockUnavailableException, the lock belongs to another instance
|
||||
// and must not be deleted by this instance.
|
||||
if (lockAcquired) {
|
||||
try {
|
||||
runLockPort.release();
|
||||
LOG.debug("Run lock released");
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Warning: Failed to release run lock", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package de.gecheckt.pdf.umbenenner.application.usecase;
|
||||
|
||||
import de.gecheckt.pdf.umbenenner.application.config.StartConfiguration;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.RunBatchProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort;
|
||||
import de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Minimal no-op implementation of {@link RunBatchProcessingUseCase}.
|
||||
* <p>
|
||||
* AP-003 Implementation: Provides a controlled, non-functional startup path
|
||||
* without any business logic, PDF processing, or infrastructure access.
|
||||
* <p>
|
||||
* AP-005: Accepts {@link ConfigurationPort} to load typed startup configuration.
|
||||
* <p>
|
||||
* M2-AP-002 Update: Returns {@link BatchRunOutcome} instead of boolean,
|
||||
* enabling structured result handling by Bootstrap and CLI layers.
|
||||
* <p>
|
||||
* M2-AP-003 Update: Accepts {@link BatchRunContext} to enable run ID and timing tracking.
|
||||
*/
|
||||
public class NoOpRunBatchProcessingUseCase implements RunBatchProcessingUseCase {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(NoOpRunBatchProcessingUseCase.class);
|
||||
private final ConfigurationPort configurationPort;
|
||||
|
||||
/**
|
||||
* Creates the no-op use case with a configuration port.
|
||||
*
|
||||
* @param configurationPort the configuration port for loading startup configuration
|
||||
*/
|
||||
public NoOpRunBatchProcessingUseCase(ConfigurationPort configurationPort) {
|
||||
this.configurationPort = configurationPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchRunOutcome execute(BatchRunContext context) {
|
||||
// AP-005: Load configuration through the port (technical loading only)
|
||||
StartConfiguration config = configurationPort.loadConfiguration();
|
||||
LOG.info("Configuration loaded successfully. Source: {}, Target: {}", config.sourceFolder(), config.targetFolder());
|
||||
|
||||
// M2-AP-003: Log run context information for traceability
|
||||
LOG.info("Batch run started with RunId: {}, started at: {}", context.runId(), context.startInstant());
|
||||
|
||||
// AP-003: Intentional no-op - validates the technical call chain only
|
||||
// M2-AP-002: Return structured outcome instead of boolean
|
||||
return BatchRunOutcome.SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user