Class RedisOutboxAutoConfiguration

java.lang.Object
com.aim2be.platform.outbox.redis.RedisOutboxAutoConfiguration

@AutoConfiguration @AutoConfigureAfter({org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class,org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration.class}) @ConditionalOnProperty(prefix="im2be.outbox", name="backend", havingValue="REDIS") @EnableConfigurationProperties({com.aim2be.platform.outbox.OutboxProperties.class,RedisOutboxProperties.class}) @EnableScheduling public class RedisOutboxAutoConfiguration extends Object
Spring Boot auto-configuration for the redis-outbox-backend module (Wave A.2 Phase 0b).

EXPLICIT backend selection (refinement #11). Activated ONLY when im2be.outbox.enabled=true AND im2be.outbox.backend=REDIS. Redis being on the classpath must NOT auto-select Redis — PG stays the default. The im2be.outbox.backend property is owned by the outbox-publisher's OutboxProperties (the OutboxProperties.Backend enum already declares PG + REDIS); this autoconfig keys off the REDIS value via @ConditionalOnProperty.

When this autoconfig is active it supplies the OutboxBackend bean (RedisOutboxBackend). The outbox-publisher's PG @ConditionalOnMissingBean OutboxBackend therefore backs off — but note that the PG OutboxAutoConfiguration ALSO eagerly wires JPA beans (repository, completion helper) that a Redis-only consumer (identity-service) must not trigger. That JPA-conditional wiring is tracked as a Phase-0b/Phase-1 follow-up in the PG OutboxAutoConfiguration Javadoc (it is a cross-module change to a FROZEN Phase 0a file, out of scope here); a Redis-only service simply does NOT put spring-data-jpa on its classpath, so the PG autoconfig's @AutoConfigureAfter(DataSourceAutoConfiguration…) + JPA-dependent bean methods never resolve. This module deliberately does not depend on spring-data-jpa for exactly that reason.

Wires:

@EnableScheduling activates the @Scheduled poller + durability + retention + repair ticks. Side effect (be aware): because @EnableScheduling registers ScheduledAnnotationBeanPostProcessor for the WHOLE application context, enabling im2be.outbox.backend=REDIS also activates Spring's task scheduler for the consumer — any consumer @Scheduled beans that were dormant (because the consumer had not itself opted into scheduling) start running. The blast is scoped to consumers that explicitly opt into the Redis backend, but consumer teams should know that selecting this backend turns the scheduler on context-wide. This side effect is INTRINSIC, not narrowable by moving @EnableScheduling to a nested @Configuration gated on poller.enabled: the durability validator, retention worker, and repair worker are ALSO @Scheduled (durability is even unconditional), so scheduling is required whenever the backend is REDIS, not merely when the poller is on — a poller-only gate would silently stop those workers. And Spring's @EnableScheduling registers ScheduledAnnotationBeanPostProcessor for the whole context wherever it is declared, so a nested activator would not actually scope the leak. True per-module isolation would mean dropping @Scheduled for a module-private programmatic TaskScheduler — a deliberate non-goal for this module; the documented context-wide opt-in is the accepted trade-off (reviewer R1 INFO / R2 MINOR — kept as documented). Registered via META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.

  • Constructor Details

    • RedisOutboxAutoConfiguration

      public RedisOutboxAutoConfiguration(RedisOutboxProperties properties)
      Validates cross-field properties that JSR-303 field annotations cannot express, then logs the active backend. lockRenewMarginMs MUST be strictly less than lockTtlMs (refinement #4 — the renew must fire before the lease ends), otherwise the poller could never renew in time.
      Parameters:
      properties - the bound Redis-outbox properties
  • Method Details

    • redisOutboxStringRedisTemplate

      @Bean @ConditionalOnMissingBean public org.springframework.data.redis.core.StringRedisTemplate redisOutboxStringRedisTemplate(org.springframework.data.redis.connection.RedisConnectionFactory connectionFactory)
      String-typed Redis template. @ConditionalOnMissingBean so a consumer with its own template (custom serializers, cluster client) wins.
      Parameters:
      connectionFactory - the application's Redis connection factory (provided by RedisAutoConfiguration)
      Returns:
      a StringRedisTemplate
    • redisOutboxScripts

      @Bean @ConditionalOnMissingBean public RedisOutboxScripts redisOutboxScripts()
      The Lua script singletons (SHA1 computed once — see RedisOutboxScripts).
      Returns:
      the script holder
    • redisOutboxKeys

      @Bean @ConditionalOnMissingBean public RedisOutboxKeys redisOutboxKeys(RedisOutboxProperties properties)
      The hash-tagged key set derived from im2be.outbox.redis.key-prefix (refinement #8).
      Parameters:
      properties - the Redis-outbox properties
      Returns:
      the key set
    • redisOutboxBackoff

      @Bean @ConditionalOnMissingBean public RedisOutboxBackoff redisOutboxBackoff(RedisOutboxProperties properties)
      The exponential-backoff calculator for failure re-scoring (refinement #5).
      Parameters:
      properties - the Redis-outbox properties
      Returns:
      the backoff
    • redisOutboxMetrics

      @Bean @ConditionalOnMissingBean public RedisOutboxMetrics redisOutboxMetrics(org.springframework.beans.factory.ObjectProvider<io.micrometer.core.instrument.MeterRegistry> meterRegistry, org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxKeys keys)
      The metrics binder. No-op when no MeterRegistry is present (parity with the PG OutboxMetricsBinder).
      Parameters:
      meterRegistry - optional Micrometer registry
      redis - the Redis template (for the pending-gauge poll)
      keys - the key set
      Returns:
      the metrics binder
    • redisOutboxBackend

      @Bean @ConditionalOnMissingBean(com.aim2be.platform.outbox.OutboxBackend.class) public RedisOutboxBackend redisOutboxBackend(org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxScripts scripts, RedisOutboxKeys keys, RedisOutboxBackoff backoff, RedisOutboxMetrics metrics, org.springframework.beans.factory.ObjectProvider<com.fasterxml.jackson.databind.ObjectMapper> objectMapper)
      The OutboxBackend bean — satisfies the outbox-publisher's @ConditionalOnMissingBean OutboxBackend so the PG backend backs off (refinement #11). Reuses the application ObjectMapper when present, else a fresh one.
      Parameters:
      redis - the Redis template
      scripts - the Lua scripts
      keys - the key set
      backoff - the failure-rescore backoff
      metrics - the metrics binder
      objectMapper - optional application Jackson mapper
      Returns:
      the Redis outbox backend
    • redisOutboxCircuitBreakerRegistry

      @Bean @ConditionalOnMissingBean public io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry redisOutboxCircuitBreakerRegistry()
      Default Resilience4j CircuitBreakerRegistry for consumers that have not declared one (vanilla defaults — outbox-specific thresholds live on the breaker created below, not the registry default, to avoid leaking into other breakers — parity with the PG autoconfig's R4 fix).
      Returns:
      a default breaker registry
    • redisOutboxCircuitBreaker

      @Bean @ConditionalOnMissingBean(name="redisOutboxCircuitBreaker") public io.github.resilience4j.circuitbreaker.CircuitBreaker redisOutboxCircuitBreaker(RedisOutboxProperties properties, io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry registry)
      The Redis hot-relay CircuitBreaker, thresholds built explicitly from im2be.outbox.redis.circuit-breaker.* so the config takes effect regardless of which registry the consumer wired.
      Parameters:
      properties - the Redis-outbox properties
      registry - the breaker registry to register into
      Returns:
      the relay breaker
    • redisOutboxRelay

      @Bean @ConditionalOnMissingBean public RedisOutboxRelay redisOutboxRelay(OutboxBackend backend, org.springframework.kafka.core.KafkaTemplate<byte[],byte[]> kafkaTemplate, io.github.resilience4j.circuitbreaker.CircuitBreaker redisOutboxCircuitBreaker, RedisOutboxMetrics metrics, RedisOutboxProperties properties)
      The inline hot relay (own breaker — the PG AFTER_COMMIT relay is unusable for a transaction-free backend; see RedisOutboxRelay).
      Parameters:
      backend - the Redis backend (transitions)
      kafkaTemplate - the Kafka template
      redisOutboxCircuitBreaker - the relay breaker
      metrics - the metrics binder
      properties - the Redis-outbox properties (max-retries)
      Returns:
      the relay
    • redisOutboxPollerWorker

      @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix="im2be.outbox.redis.poller", name="enabled", havingValue="true", matchIfMissing=true) public RedisOutboxPollerWorker redisOutboxPollerWorker(OutboxBackend backend, org.springframework.kafka.core.KafkaTemplate<byte[],byte[]> kafkaTemplate, org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxScripts scripts, RedisOutboxKeys keys, RedisOutboxProperties properties, RedisOutboxMetrics metrics)
      The cold poller. Conditional on im2be.outbox.redis.poller.enabled (default true).
      Parameters:
      backend - the Redis backend
      kafkaTemplate - the Kafka template
      redis - the Redis template (lock acquire)
      scripts - the Lua scripts (lock renew/release)
      keys - the key set
      properties - the Redis-outbox properties
      metrics - the metrics binder
      Returns:
      the poller worker
    • redisDurabilityValidator

      @Bean @ConditionalOnMissingBean public RedisDurabilityValidator redisDurabilityValidator(org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxProperties properties, RedisOutboxMetrics metrics)
      The durability validator (startup + periodic AOF/fsync/noeviction guard, refinement #7).
      Parameters:
      redis - the Redis template (CONFIG GET)
      properties - the Redis-outbox properties (durability config)
      metrics - the metrics binder
      Returns:
      the validator
    • redisOutboxRetentionWorker

      @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix="im2be.outbox.redis.retention", name="enabled", havingValue="true", matchIfMissing=true) public RedisOutboxRetentionWorker redisOutboxRetentionWorker(org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxScripts scripts, RedisOutboxKeys keys, org.springframework.beans.factory.ObjectProvider<com.fasterxml.jackson.databind.ObjectMapper> objectMapper, RedisOutboxProperties properties, RedisOutboxMetrics metrics)
      The SENT-retention worker (refinement #9). Conditional on im2be.outbox.redis.retention.enabled (default true).
      Parameters:
      redis - the Redis template
      scripts - the Lua scripts
      keys - the key set
      objectMapper - the Jackson mapper
      properties - the Redis-outbox properties (retention config)
      metrics - the metrics binder
      Returns:
      the retention worker
    • redisOutboxRepairWorker

      @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix="im2be.outbox.redis.repair", name="enabled", havingValue="true", matchIfMissing=true) public RedisOutboxRepairWorker redisOutboxRepairWorker(org.springframework.data.redis.core.StringRedisTemplate redis, RedisOutboxScripts scripts, RedisOutboxKeys keys, org.springframework.beans.factory.ObjectProvider<com.fasterxml.jackson.databind.ObjectMapper> objectMapper, RedisOutboxMetrics metrics)
      The zset/hash repair worker (refinement #10). Conditional on im2be.outbox.redis.repair.enabled (default true).
      Parameters:
      redis - the Redis template
      scripts - the Lua scripts
      keys - the key set
      objectMapper - the Jackson mapper
      metrics - the metrics binder
      Returns:
      the repair worker