fix(lingxing): allow bounded configurable business request pacing
This commit is contained in:
+35
-1
@@ -13,6 +13,40 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class LingxingEgressGateTest {
|
||||
@Test void debugTimingRecordsActualCallAndCompletionWithoutContextOrPayload() {
|
||||
var logger = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory.getLogger(LingxingEgressGate.class);
|
||||
var previous = logger.getLevel();
|
||||
var appender = new ch.qos.logback.core.read.ListAppender<ch.qos.logback.classic.spi.ILoggingEvent>();
|
||||
appender.start(); logger.addAppender(appender); logger.setLevel(ch.qos.logback.classic.Level.DEBUG);
|
||||
try {
|
||||
var gate = gate();
|
||||
Object body = new Object();
|
||||
assertThat(gate.<Object>execute(context("private-attempt"), Operation.OUTBOUND_DETAIL, HASH, handle -> {
|
||||
handle.startHttp(); clock.advanceMillis(123); return body;
|
||||
})).isSameAs(body);
|
||||
assertThat(appender.list).hasSize(1);
|
||||
assertThat(appender.list.get(0).getFormattedMessage())
|
||||
.contains("operation=OUTBOUND_DETAIL", "start=" + NOW, "end=" + NOW.plusMillis(123),
|
||||
"upstreamStatus=200", "errorCode=null", "completionConfirmed=true")
|
||||
.doesNotContain("demo-account", "private-attempt", "demo-grant", HASH);
|
||||
ledger.failComplete = true;
|
||||
var failure = assertThrows(LingxingWmsException.class, () -> gate.execute(context("private-failure"),
|
||||
Operation.OUTBOUND_DETAIL, HASH, handle -> {
|
||||
handle.startHttp(); clock.advanceMillis(50); throw rateLimit();
|
||||
}));
|
||||
assertThat(failure.code()).isEqualTo("LINGXING_WMS_BUDGET_COMPLETION_UNCONFIRMED");
|
||||
assertThat(appender.list).hasSize(2);
|
||||
assertThat(appender.list.get(1).getFormattedMessage())
|
||||
.contains("upstreamStatus=429", "errorCode=RATE_LIMIT", "completionConfirmed=false")
|
||||
.doesNotContain("private-failure", "synthetic rate limit", "demo-account", HASH);
|
||||
logger.setLevel(ch.qos.logback.classic.Level.INFO);
|
||||
ledger.failComplete = false;
|
||||
gate().execute(context("debug-disabled"), Operation.WAREHOUSES, HASH, handle -> body);
|
||||
assertThat(appender.list).hasSize(2);
|
||||
} finally {
|
||||
logger.detachAppender(appender); appender.stop(); logger.setLevel(previous);
|
||||
}
|
||||
}
|
||||
static final Instant NOW = Instant.parse("2026-10-12T00:00:00Z");
|
||||
static final String HASH = "a".repeat(64);
|
||||
private final MutableClock clock = new MutableClock(NOW);
|
||||
@@ -159,7 +193,7 @@ class LingxingEgressGateTest {
|
||||
} finally { release.countDown(); executor.shutdownNow(); }
|
||||
}
|
||||
@Test void intervalCannotBeConfiguredBelowFiveSecondsAndPropertiesHideGrant() {
|
||||
assertThatThrownBy(() -> new LingxingEgressProperties(null, null, null, null, null, null, Duration.ofMillis(4999), null)).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> new LingxingEgressProperties(CollectionMode.VALIDATION, null, null, null, null, null, Duration.ofMillis(4999), null)).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(props(CollectionMode.VALIDATION, "test").toString()).doesNotContain("demo-grant", "demo-account", "127.0.0.1");
|
||||
}
|
||||
@Test void knownBudgetDenialDoesNotPermanentlyPauseOrConsumeHttp() {
|
||||
|
||||
Reference in New Issue
Block a user