WorkflowOutboxRetentionSettings.java
package org.hammer.audio.workflow.collaboration.retention;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
/**
* Conservative settings for bounded published-outbox retention.
*
* <p>This contract does not delete session aggregates, accepted operations or Git checkpoints.
* Command ids therefore remain available indefinitely unless a separate, explicitly proven
* operation-compaction policy is introduced later.
*
* @param publishedRetention minimum age of a successfully published event before eligibility
* @param batchSize maximum candidates captured by one immutable plan
*/
public record WorkflowOutboxRetentionSettings(Duration publishedRetention, int batchSize) {
/** Default published-event diagnostic horizon. */
public static final Duration DEFAULT_PUBLISHED_RETENTION = Duration.ofDays(30);
/** Conservative default batch size. */
public static final int DEFAULT_BATCH_SIZE = 100;
/** Hard upper bound preventing accidental unbounded cleanup transactions. */
public static final int MAXIMUM_BATCH_SIZE = 1000;
public WorkflowOutboxRetentionSettings {
// Validate settings once before they can participate in candidate selection.
Objects.requireNonNull(publishedRetention, "publishedRetention");
if (publishedRetention.isZero() || publishedRetention.isNegative()) {
throw new IllegalArgumentException("publishedRetention must be positive");
}
if (batchSize <= 0 || batchSize > MAXIMUM_BATCH_SIZE) {
throw new IllegalArgumentException("batchSize must be between 1 and " + MAXIMUM_BATCH_SIZE);
}
}
/** Returns settings that retain published rows for 30 days and delete at most 100 per batch. */
public static WorkflowOutboxRetentionSettings conservativeDefaults() {
return new WorkflowOutboxRetentionSettings(DEFAULT_PUBLISHED_RETENTION, DEFAULT_BATCH_SIZE);
}
/** Computes the inclusive publication cutoff for one logical cleanup time. */
public Instant publishedCutoffAt(Instant plannedAt) {
return Objects.requireNonNull(plannedAt, "plannedAt").minus(publishedRetention);
}
}