feat(self-operated): persist continuous collection and frozen coverage

This commit is contained in:
2026-10-13 21:13:31 +08:00
parent c2bb769676
commit 242a76221e
45 changed files with 1021 additions and 118 deletions
@@ -12,7 +12,8 @@ import java.time.Instant;
public record LingxingEgressProperties(@DefaultValue("OFF") CollectionMode collectionMode,
@DefaultValue("test") String environmentLabel, String sourceAccount, String externalExclusiveGrantId,
Instant externalExclusiveUntil, URI budgetAuthorityBaseUri, @DefaultValue("5s") Duration minStartInterval,
@DefaultValue("5m") Duration cooldownFallback) {
@DefaultValue("5m") Duration cooldownFallback,
@DefaultValue("false") boolean continuousBusinessCollectionEnabled) {
public LingxingEgressProperties {
collectionMode = collectionMode == null ? CollectionMode.OFF : collectionMode;
environmentLabel = environmentLabel == null ? "test" : environmentLabel;
@@ -62,7 +62,7 @@ public final class LingxingEgressGate {
|| !hash.equals(permit.requestHash()) || permit.allowedAttempts() != 1 || !permit.exclusiveConfirmed()
|| !permit.budgetConsumed() || permit.expiresAt() == null || !clock.instant().isBefore(permit.expiresAt())
|| permit.expiresAt().isAfter(clock.instant().plusSeconds(30))
|| permit.expiresAt().isAfter(properties.externalExclusiveUntil())) {
|| (!continuousBusiness() && permit.expiresAt().isAfter(properties.externalExclusiveUntil()))) {
recoverableRatePause = false; paused = true; throw failure("BUDGET_PERMIT_INVALID");
}
// A new persisted permit proves the coordinator accepted the account's cooldown/budget/root state.
@@ -106,10 +106,14 @@ public final class LingxingEgressGate {
if (context == null || context.executionPurpose() != properties.collectionMode()
|| !context.wellFormed()
|| !context.sourceAccount().equals(properties.sourceAccount())) throw failure("EGRESS_CONTEXT_INVALID");
if (properties.externalExclusiveGrantId() == null || !properties.externalExclusiveGrantId().equals(context.exclusiveGrantId())
|| properties.externalExclusiveUntil() == null || !clock.instant().isBefore(properties.externalExclusiveUntil())
if (properties.externalExclusiveGrantId() == null || properties.externalExclusiveGrantId().isBlank()
|| !properties.externalExclusiveGrantId().equals(context.exclusiveGrantId())
|| (!continuousBusiness() && (properties.externalExclusiveUntil() == null || !clock.instant().isBefore(properties.externalExclusiveUntil())))
|| properties.budgetAuthorityBaseUri() == null) throw failure("EXCLUSIVE_WINDOW_UNCONFIRMED");
}
private boolean continuousBusiness() {
return properties.collectionMode() == CollectionMode.BUSINESS && properties.continuousBusinessCollectionEnabled();
}
private static boolean identifier(String value, int maximum) {
return value != null && value.length() <= maximum && value.matches("[A-Za-z0-9][A-Za-z0-9._:-]*");
}
@@ -44,13 +44,14 @@ baiyue:
request-timeout: 15s
egress:
collection-mode: ${LINGXING_COLLECTION_MODE:OFF}
continuous-business-collection-enabled: ${LINGXING_CONTINUOUS_BUSINESS_COLLECTION_ENABLED:false}
environment-label: ${LINGXING_ENVIRONMENT_LABEL:test}
source-account: ${LINGXING_SOURCE_ACCOUNT:lingxing-primary}
external-exclusive-grant-id: ${LINGXING_EXTERNAL_EXCLUSIVE_GRANT_ID:}
budget-authority-base-uri: ${LINGXING_BUDGET_AUTHORITY_BASE_URI:http://lastleg-service:9303}
min-start-interval: 5s
cooldown-fallback: 5m
# Explicitly inject external-exclusive-until (ISO Instant) and budget-authority-base-uri.
# Finite sessions require external-exclusive-until; continuous BUSINESS still requires the exclusive grant ID and authority.
# Missing proof/authority fails closed even when the old enabled switch is true.
baidu-ocr:
enabled: ${BAIDU_OCR_ENABLED:false}