package com.xfestudio.xfeservermanager.infra.http;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.Clock;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
class IdempotencyRegistryTest {
@Test
void invokesAnOperationOnceAndRejectsKeyReuseWithDifferentPayload() {
var registry = new IdempotencyRegistry(4, Duration.ofMinutes(10), Clock.systemUTC());
var calls = new AtomicInteger();
UUID actor = UUID.randomUUID();
var first = registry.execute(actor, "POST", "/operations", "request-key", "body-a", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("accepted");
});
var replay = registry.execute(actor, "POST", "/operations", "request-key", "body-a", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("wrong");
});
assertThat(first.toCompletableFuture().join()).isEqualTo("accepted");
assertThat(replay.toCompletableFuture().join()).isEqualTo("accepted");
assertThat(calls).hasValue(1);
assertThatThrownBy(() -> registry.execute(
actor,
"POST",
"/operations",
"request-key",
"body-b",
() -> CompletableFuture.completedFuture("wrong")))
.isInstanceOf(IdempotencyRegistry.IdempotencyConflictException.class);
}
@Test
void capacityPressureNeverEvictsAnUnexpiredCompletedResult() {
var registry = new IdempotencyRegistry(1, Duration.ofMinutes(10), Clock.systemUTC());
UUID actor = UUID.randomUUID();
var calls = new AtomicInteger();
registry.execute(actor, "POST", "/operations", "first-key", "body", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("first-result");
}).toCompletableFuture().join();
assertThatThrownBy(() -> registry.execute(
actor, "POST", "/operations", "second-key", "body",
() -> CompletableFuture.completedFuture("must-not-run")))
.isInstanceOf(IdempotencyRegistry.IdempotencyCapacityException.class);
assertThat(registry.execute(
actor, "POST", "/operations", "first-key", "body", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("duplicate");
}).toCompletableFuture().join())
.isEqualTo("first-result");
assertThat(calls).hasValue(1);
}
}
package com.xfestudio.xfeservermanager.infra.http;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.Clock;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.Test;
class IdempotencyRegistryTest {
@Test
void invokesAnOperationOnceAndRejectsKeyReuseWithDifferentPayload() {
var registry = new IdempotencyRegistry(4, Duration.ofMinutes(10), Clock.systemUTC());
var calls = new AtomicInteger();
UUID actor = UUID.randomUUID();
var first = registry.execute(actor, "POST", "/operations", "request-key", "body-a", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("accepted");
});
var replay = registry.execute(actor, "POST", "/operations", "request-key", "body-a", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("wrong");
});
assertThat(first.toCompletableFuture().join()).isEqualTo("accepted");
assertThat(replay.toCompletableFuture().join()).isEqualTo("accepted");
assertThat(calls).hasValue(1);
assertThatThrownBy(() -> registry.execute(
actor,
"POST",
"/operations",
"request-key",
"body-b",
() -> CompletableFuture.completedFuture("wrong")))
.isInstanceOf(IdempotencyRegistry.IdempotencyConflictException.class);
}
@Test
void capacityPressureNeverEvictsAnUnexpiredCompletedResult() {
var registry = new IdempotencyRegistry(1, Duration.ofMinutes(10), Clock.systemUTC());
UUID actor = UUID.randomUUID();
var calls = new AtomicInteger();
registry.execute(actor, "POST", "/operations", "first-key", "body", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("first-result");
}).toCompletableFuture().join();
assertThatThrownBy(() -> registry.execute(
actor, "POST", "/operations", "second-key", "body",
() -> CompletableFuture.completedFuture("must-not-run")))
.isInstanceOf(IdempotencyRegistry.IdempotencyCapacityException.class);
assertThat(registry.execute(
actor, "POST", "/operations", "first-key", "body", () -> {
calls.incrementAndGet();
return CompletableFuture.completedFuture("duplicate");
}).toCompletableFuture().join())
.isEqualTo("first-result");
assertThat(calls).hasValue(1);
}
}