diff --git a/CHANGELOG.md b/CHANGELOG.md index 352c5c3d03..a470ab134b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ When updating the changelog, remember to be very clear about what behavior has c and what APIs have changed, if applicable. ## [Unreleased] +## [29.49.3] - 2024-01-03 +- Fix rate limiter for dual-read mode switch ## [29.49.2] - 2024-01-02 - add back publish original cluster for symlink cluster @@ -5600,7 +5602,8 @@ patch operations can re-use these classes for generating patch messages. ## [0.14.1] -[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.49.2...master +[Unreleased]: https://github.com/linkedin/rest.li/compare/v29.49.3...master +[29.49.3]: https://github.com/linkedin/rest.li/compare/v29.49.2...v29.49.3 [29.49.2]: https://github.com/linkedin/rest.li/compare/v29.49.1...v29.49.2 [29.49.1]: https://github.com/linkedin/rest.li/compare/v29.49.0...v29.49.1 [29.49.0]: https://github.com/linkedin/rest.li/compare/v29.48.9...v29.49.0 diff --git a/d2/src/main/java/com/linkedin/d2/balancer/dualread/DualReadStateManager.java b/d2/src/main/java/com/linkedin/d2/balancer/dualread/DualReadStateManager.java index d00c6a413f..eafd26f0fa 100644 --- a/d2/src/main/java/com/linkedin/d2/balancer/dualread/DualReadStateManager.java +++ b/d2/src/main/java/com/linkedin/d2/balancer/dualread/DualReadStateManager.java @@ -51,6 +51,7 @@ public class DualReadStateManager private final DualReadModeProvider _dualReadModeProvider; private final ScheduledExecutorService _executorService; private final RateLimiter _rateLimiter; + private final ConcurrentMap _serviceToRateLimiterMap; // Stores global dual read mode private volatile DualReadModeProvider.DualReadMode _dualReadMode = DualReadModeProvider.DualReadMode.OLD_LB_ONLY; private final Set _globalDualReadModeWatchers; @@ -79,6 +80,7 @@ public DualReadStateManager(DualReadModeProvider dualReadModeProvider, Scheduled _dualReadModeProvider = dualReadModeProvider; _executorService = executorService; _rateLimiter = RateLimiter.create((double) 1 / DUAL_READ_MODE_SWITCH_MIN_INTERVAL); + _serviceToRateLimiterMap = new ConcurrentHashMap<>(); _globalDualReadModeWatchers = ConcurrentHashMap.newKeySet(); _serviceDualReadModeWatchers = new ConcurrentHashMap<>(); _clusterDualReadModeWatchers = new ConcurrentHashMap<>(); @@ -191,15 +193,21 @@ public void checkAndSwitchMode(String d2ServiceName) _executorService.execute(() -> { - boolean shouldCheck = _rateLimiter.tryAcquire(); - if (shouldCheck) + if (d2ServiceName == null) { - // Check and switch global dual read mode - updateGlobal(_dualReadModeProvider.getDualReadMode()); - - // Check and switch service-level dual read mode - if (d2ServiceName != null) + if (_rateLimiter.tryAcquire()) + { + // Check and switch global dual read mode + updateGlobal(_dualReadModeProvider.getDualReadMode()); + } + } + else + { + RateLimiter serviceRateLimiter = _serviceToRateLimiterMap.computeIfAbsent(d2ServiceName, + key -> RateLimiter.create((double) 1 / DUAL_READ_MODE_SWITCH_MIN_INTERVAL)); + if (serviceRateLimiter.tryAcquire()) { + // Check and switch service-level dual read mode updateService(d2ServiceName, _dualReadModeProvider.getDualReadMode(d2ServiceName)); } } diff --git a/gradle.properties b/gradle.properties index d4de7b8043..1065fc8c24 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=29.49.2 +version=29.49.3 group=com.linkedin.pegasus org.gradle.configureondemand=true org.gradle.parallel=true