fix: keep metrics snapshot sorted and translate rejected submissions · iluwatar/java-design-patterns@9124ada · GitHub
Skip to content

Commit 9124ada

Browse files
committed
fix: keep metrics snapshot sorted and translate rejected submissions
- TimeoutMetrics.snapshot() returns an unmodifiable SortedMap so the sorted view promised by its javadoc survives, covered by a new ordering test - TimeoutExecutor submits inside the try and wraps RejectedExecutionException in ServiceCallException, matching its @throws contract - timeout.urm.puml: mark TimeoutPolicy as a record, drop the synthetic App constructor, show ServiceCallException extending RuntimeException, add the App to TimeoutPolicy and TimeoutMetrics dependencies - README: inline mermaid class diagram instead of the raw .puml link, and note that the timeout warning and the worker interrupt lines may interleave
1 parent 1b50cb4 commit 9124ada

5 files changed

Lines changed: 105 additions & 15 deletions

File tree

‎timeout/README.md‎

Lines changed: 69 additions & 4 deletions

‎timeout/etc/timeout.urm.puml‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@startuml
22
package com.iluwatar.timeout {
3-
class TimeoutPolicy {
3+
class TimeoutPolicy <<record>> {
44
- serviceName : String
55
- timeout : Duration
66
+ TimeoutPolicy(serviceName : String, timeout : Duration)
@@ -20,7 +20,7 @@ package com.iluwatar.timeout {
2020
+ TimeoutMetrics()
2121
+ recordTimeout(serviceName : String) : void
2222
+ timeoutCount(serviceName : String) : int
23-
+ snapshot() : Map<String, Integer>
23+
+ snapshot() : SortedMap<String, Integer>
2424
}
2525
class TimeoutExecutor {
2626
- executor : ExecutorService
@@ -48,18 +48,20 @@ package com.iluwatar.timeout {
4848
}
4949
class App {
5050
- POPULAR_ITEMS : List<String> {static}
51-
+ App()
5251
+ main(args : String[]) : void
5352
~ loadProducts(executor : TimeoutExecutor, registry : TimeoutRegistry, catalog : ProductCatalogService) : List<String> {static}
5453
~ loadRecommendations(executor : TimeoutExecutor, registry : TimeoutRegistry, recommendations : RecommendationService, customer : String) : List<String> {static}
5554
}
5655
}
56+
ServiceCallException --|> RuntimeException
5757
TimeoutExecutor --> TimeoutMetrics
5858
TimeoutExecutor ..> TimeoutPolicy
5959
TimeoutExecutor ..> ServiceCallException
6060
TimeoutRegistry --> "*" TimeoutPolicy
6161
App ..> TimeoutRegistry
62+
App ..> TimeoutPolicy
6263
App ..> TimeoutExecutor
64+
App ..> TimeoutMetrics
6365
App ..> ProductCatalogService
6466
App ..> RecommendationService
6567
@enduml

‎timeout/src/main/java/com/iluwatar/timeout/TimeoutExecutor.java‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.concurrent.ExecutionException;
3030
import java.util.concurrent.ExecutorService;
3131
import java.util.concurrent.Executors;
32+
import java.util.concurrent.Future;
33+
import java.util.concurrent.RejectedExecutionException;
3234
import java.util.concurrent.TimeUnit;
3335
import java.util.concurrent.TimeoutException;
3436
import java.util.function.Supplier;
@@ -71,13 +73,15 @@ public TimeoutExecutor(ExecutorService executor) {
7173
* @param fallback answer to use when the call does not complete in time
7274
* @param <T> type of the response
7375
* @return the response of the call, or the fallback if the limit was exceeded
74-
* @throws ServiceCallException if the call fails or the waiting thread is interrupted
76+
* @throws ServiceCallException if the call cannot be submitted, fails, or the waiting thread is
77+
* interrupted
7578
*/
7679
public <T> T execute(TimeoutPolicy policy, Callable<T> call, Supplier<T> fallback) {
7780
var serviceName = policy.serviceName();
7881
var limitMillis = policy.timeout().toMillis();
79-
var future = executor.submit(call);
82+
Future<T> future = null;
8083
try {
84+
future = executor.submit(call);
8185
var result = future.get(limitMillis, TimeUnit.MILLISECONDS);
8286
LOGGER.info("{} responded within its {} ms limit", serviceName, limitMillis);
8387
return result;
@@ -93,6 +97,8 @@ public <T> T execute(TimeoutPolicy policy, Callable<T> call, Supplier<T> fallbac
9397
future.cancel(true);
9498
Thread.currentThread().interrupt();
9599
throw new ServiceCallException(serviceName, e);
100+
} catch (RejectedExecutionException e) {
101+
throw new ServiceCallException(serviceName, e);
96102
}
97103
}
98104

‎timeout/src/main/java/com/iluwatar/timeout/TimeoutMetrics.java‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
*/
2525
package com.iluwatar.timeout;
2626

27-
import java.util.Map;
27+
import java.util.Collections;
28+
import java.util.SortedMap;
2829
import java.util.TreeMap;
2930
import java.util.concurrent.ConcurrentHashMap;
3031
import java.util.concurrent.ConcurrentMap;
@@ -63,9 +64,9 @@ public int timeoutCount(String serviceName) {
6364
*
6465
* @return service name to timeout count
6566
*/
66-
public Map<String, Integer> snapshot() {
67+
public SortedMap<String, Integer> snapshot() {
6768
var snapshot = new TreeMap<String, Integer>();
6869
timeouts.forEach((name, counter) -> snapshot.put(name, counter.get()));
69-
return Map.copyOf(snapshot);
70+
return Collections.unmodifiableSortedMap(snapshot);
7071
}
7172
}

‎timeout/src/test/java/com/iluwatar/timeout/TimeoutExecutorTest.java‎

Lines changed: 19 additions & 3 deletions

0 commit comments

Comments
 (0)