prosgarz35 opened a new pull request, #3211: URL: https://github.com/apache/james-project/pull/3211
## Summary This pull request integrates a high-performance in-memory cache powered by [Caffeine](https://github.com/ben-manes/caffeine) directly into `DNSJavaService`. It intercepts queries ahead of dnsjava's internal cache, offering per-entry dynamic TTL expiration, SOA negative caching support, bounded corridor enforcement, and backward-compatible XML configuration. --- ## Motivation & Problem Statement In high-throughput mail processing environments (SMTP reception, relaying, SPF/DKIM/DMARC checks), DNS resolution latency and upstream resolver rate-limiting can become severe bottlenecks: 1. **Redundant Upstream DNS Queries**: High-frequency lookups (`MX`, `A`, `ALL_A`, `TXT`, and `PTR`) frequently query upstream resolvers even for identical records when upstream TTLs are short or negative lookups occur. 2. **Lack of Per-Record TTL & Corridor Controls**: The existing dnsjava `Cache` implementation lacks flexible, granular control over per-entry expiration, corridor clamping (min/max protection), and negative caching tuning without affecting global JVM properties. 3. **Cache Stampede & Zero-TTL Thrashing**: Misconfigured or malicious upstream records specifying a 0-second TTL force constant network round-trips without a lower protective floor. --- ## Key Changes & Architecture ### 1. Caffeine Cache Integration - Embedded Caffeine cache (`caffeineCache`) introduced in front of dnsjava `Lookup`. - Type-safe composite key `DnsKey(DnsRecordType type, Object target)` supporting: - `MX`: Mail exchange lookups - `A`: Hostname to IPv4/IPv6 single address - `ALL_A`: Hostname to all IP addresses - `TXT`: Text records (SPF, DKIM, DMARC) - `PTR`: Reverse IP resolution (FCrDNS, connection logging) - Normalized case handling (`normalizeKey`) for hostnames using `Locale.US` to avoid redundant misses. - Values stored wrapped in `DnsValue<T>(T value, long ttlSeconds)`. ### 2. Per-Entry Dynamic Expiration (`Expiry`) - Implemented a custom `Expiry<DnsKey, DnsValue<?>>` policy dynamically calculating nanos via `ttlNanos(value)` using individual record TTLs. - Eviction honors both max capacity (`maxcachesize`, default: 50,000) and entry-level TTLs. ### 3. Granular Positive & Negative TTL Corridor Protection To prevent cache stampede from 0-second TTLs while simultaneously ensuring stale records do not persist indefinitely: - **Corridor Bounds**: - `cacheMinTTL` (default: 60s, hard floor: 60s) to `cacheMaxTTL` (default: 86400s / 1 day, hard cap: 7 days). - `negativeCacheMinTTL` (default: 60s, hard floor: 60s) to `negativeCacheMaxTTL` (default: 3600s / 1 hour). - **Inheritance & Fallbacks**: - `inheritTTL`: When `true`, uses minimum TTL across returned DNS records clamped within the corridor. When `false`, uses `cacheFallbackTTL` (default: 300s). - `inheritNegativeTTL`: When `true`, respects upstream SOA negative TTL clamped within the corridor. When `false` or if SOA is absent, uses `negativeCacheFallbackTTL` (default: 60s). - **JVM Fallback Integration**: - Automatically respects `networkaddress.cache.ttl` and `networkaddress.cache.negative.ttl` (as well as `sun.net.inetaddr.*`) as defaults if explicit XML overrides are not provided. ### 4. Configuration Schema Updates (`dnsservice.xml`) Added comprehensive, documented XML elements with full backward compatibility (all tags optional): ```xml <dnsservice> <autodiscover>true</autodiscover> <authoritative>false</authoritative> <maxcachesize>50000</maxcachesize> <!-- Positive Cache Settings --> <inheritTTL>true</inheritTTL> <cacheFallbackTTL>300</cacheFallbackTTL> <cacheMinTTL>60</cacheMinTTL> <cacheMaxTTL>86400</cacheMaxTTL> <!-- Negative Cache Settings --> <inheritNegativeTTL>true</inheritNegativeTTL> <negativeCacheFallbackTTL>60</negativeCacheFallbackTTL> <negativeCacheMinTTL>60</negativeCacheMinTTL> <negativeCacheMaxTTL>3600</negativeCacheMaxTTL> </dnsservice> ``` ### 5. Dependency Updates - Upgraded `com.github.ben-manes.caffeine:caffeine` from `3.2.1` to `3.3.0` in root `pom.xml`. - Added `caffeine` dependency to `server/dns-service/dnsservice-dnsjava/pom.xml`. --- ## Clean Code, KISS & DRY Compliance - **DRY**: Extracted static helpers `normalizeKey()`, `ttlNanos()`, `sanitizeBoundedTtl()`, `resolveJvmSecurityTtl()`, and `computeRecordsTtl()`. - **KISS**: Separated fallback defaults from max bounds to avoid dual-purpose ambiguity; eliminated dead constants (`CACHE_TTL_DISABLE`). - **Formatting & Imports**: Fully conforms to Apache James checkstyle rules (ordered import groups: `java.*`, `jakarta.*`, `org.*`, `com.*`). --- ## Verification & Testing - Built and validated with Maven 3.9.16 on JDK 25 (targeting release 21): ```bash mvn compile checkstyle:check -pl server/dns-service/dnsservice-dnsjava ``` - **Results**: - `BUILD SUCCESS` - `0 Checkstyle violations` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
