feat: add Scatter-Gather pattern (#3577) - #3601
Conversation
|
⏳ Analyzing changes in this PR... ⏳ This might take a few minutes, please wait 📥 CommitsAnalyzing changes from base (
📁 Files being considered (17)🔄 pom.xml (1 hunk) autogenerated by presubmit.ai |
There was a problem hiding this comment.
🚨 Pull request needs attention.
Review Summary
Files Processed (17)
- pom.xml (1 hunk)
- scatter-gather/README.md (1 hunk)
- scatter-gather/etc/scatter-gather.urm.puml (1 hunk)
- scatter-gather/pom.xml (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/Aggregator.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/App.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/DelayedRateProvider.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/FailingRateProvider.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/InMemoryRateProvider.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/RateProvider.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/RateQuote.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/RateRequest.java (1 hunk)
- scatter-gather/src/main/java/com/iluwatar/scattergather/ScatterGather.java (1 hunk)
- scatter-gather/src/test/java/com/iluwatar/scattergather/AggregatorTest.java (1 hunk)
- scatter-gather/src/test/java/com/iluwatar/scattergather/AppTest.java (1 hunk)
- scatter-gather/src/test/java/com/iluwatar/scattergather/RateProviderTest.java (1 hunk)
- scatter-gather/src/test/java/com/iluwatar/scattergather/ScatterGatherTest.java (1 hunk)
Actionable Comments (6)
-
scatter-gather/src/main/java/com/iluwatar/scattergather/App.java [66-66]
bug: "Logger instance naming mismatch with Lombok"
-
scatter-gather/src/main/java/com/iluwatar/scattergather/App.java [69-69]
bug: "Logger usage mismatch in gather log line"
-
scatter-gather/src/main/java/com/iluwatar/scattergather/App.java [72-72]
bug: "Logger usage mismatch in aggregate log line"
-
scatter-gather/src/main/java/com/iluwatar/scattergather/DelayedRateProvider.java [60-60]
bug: "Incorrect duration handling in Delay provider"
-
scatter-gather/src/main/java/com/iluwatar/scattergather/InMemoryRateProvider.java [56-56]
bug: "Logger naming inconsistency in InMemoryRateProvider"
-
scatter-gather/src/main/java/com/iluwatar/scattergather/ScatterGather.java [83-87]
bug: "Logger naming mismatch in ScatterGather.scatter"
Skipped Comments (0)
|
|
||
| try (var scatterGather = | ||
| new ScatterGather(Executors.newFixedThreadPool(providers.size()), Duration.ofMillis(300))) { | ||
| LOGGER.info("Scatter phase: broadcasting the same request to every provider"); |
There was a problem hiding this comment.
Replace 'LOGGER' with 'log' to align with Lombok @slf4j; 'log' is the generated logger name. Using 'LOGGER' will fail to compile.
| LOGGER.info("Scatter phase: broadcasting the same request to every provider"); | ||
| var pending = scatterGather.scatter(request, providers); | ||
|
|
||
| LOGGER.info("Gather phase: collecting replies that arrive within the timeout"); |
There was a problem hiding this comment.
Same logger name issue as above; consider using 'log'.
| LOGGER.info("Gather phase: collecting replies that arrive within the timeout"); | ||
| var quotes = scatterGather.gather(pending); | ||
|
|
||
| LOGGER.info("Aggregate phase: choosing the cheapest of {} quotes", quotes.size()); |
There was a problem hiding this comment.
Same: replace with 'log' to align with Lombok-generated logger.
| public RateQuote quote(RateRequest request) { | ||
| LOGGER.info("{} is slow and will need {} ms to answer", name(), delay.toMillis()); | ||
| try { | ||
| Thread.sleep(delay); |
There was a problem hiding this comment.
Thread.sleep expects a long value in milliseconds. Use delay.toMillis() to convert Duration to milliseconds.
| @Override | ||
| public RateQuote quote(RateRequest request) { | ||
| var total = nightlyRate.multiply(BigDecimal.valueOf(request.nights())); | ||
| LOGGER.info("{} quotes {} for {} nights in {}", name, total, request.nights(), request.city()); |
There was a problem hiding this comment.
Logger usage mismatch; should be 'log.info(...)' to match Lombok @slf4j. This will fail compilation.
| LOGGER.info( | ||
| "Scattering request for {} nights in {} to {} providers", | ||
| request.nights(), | ||
| request.city(), | ||
| providers.size()); |
There was a problem hiding this comment.
Replace 'LOGGER' with 'log' to align with Lombok @slf4j; use the generated logger field name. The multi-line snippet shows the exact log call that should be updated.
|
Note on the automated review comments: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3601 +/- ##
============================================
+ Coverage 83.79% 83.91% +0.12%
- Complexity 4277 4312 +35
============================================
Files 1121 1129 +8
Lines 15144 15240 +96
Branches 723 728 +5
============================================
+ Hits 12690 12789 +99
+ Misses 2159 2155 -4
- Partials 295 296 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
31d348c to
2df15af
Compare
|
Follow-up on the Codecov note: added two |
2df15af to
c4563e9
Compare
|
Coverage follow-up: moved the result reporting in |
What does this PR do?
Adds the Scatter-Gather pattern as a new
scatter-gathermodule.RateRequest,RateQuote,RateProvider: a travel site asking several hotel rate providers for the same stay.InMemoryRateProvider(fast),DelayedRateProvider(slow, interrupt-safe),FailingRateProvider.ScatterGather:scatter()(oneCompletableFutureper provider withorTimeout),gather()(waits for all to settle, keeps successes, logs timeouts and failures),scatterGather()chaining both with anAggregator;AutoCloseable.Aggregator: functional reduction of the gathered replies, with acheapestQuote()factory.App: four providers (two fast, one slower than the 300 ms timeout, one failing); logs the scatter, gather and aggregate phases and the best offer.README.md: intent, real-world example, sequence diagram, code walkthrough, applicability, trade-offs, related patterns including an explicit note on how Scatter-Gather differs from the existing Fan-Out/Fan-In module. PlantUML class diagram underetc/.AppTest.pom.xml../mvnw clean verify -pl scatter-gatherpasses locally on JDK 21 and inside aneclipse-temurin:21container.Note: PR #3590 also targets this issue. This implementation was written independently with a different domain and design; it includes the populated, logging
Appentry point requested in the review of #3590 and treats partial results and timeouts as the core of the pattern. Happy to align with whichever direction the maintainers prefer.Fixes #3577