Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.*;
- import java.util.concurrent.*;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.concurrent.locks.ReentrantLock;
- public class ProcessingEngine {
- public sealed interface TaskOutcome permits TaskSuccess, TaskFailure, TaskTimeout {
- String taskId();
- }
- public record TaskSuccess(String taskId, Object result) implements TaskOutcome {}
- public record TaskFailure(String taskId, Throwable error) implements TaskOutcome {}
- public record TaskTimeout(String taskId) implements TaskOutcome {}
- public record ExecutionSummary(
- int submitted, int success, int failed, int timeout, Map<String, TaskOutcome> snapshot
- ) {}
- static class BoundedOrderedConcurrentMap<K, V> {
- private final int capacity;
- private final ReentrantLock lock = new ReentrantLock();
- private final Map<K, Node<K, V>> map = new HashMap<>();
- private Node<K, V> head, tail;
- private static class Node<K, V> {
- K key; V value; Node<K, V> prev, next;
- Node(K key, V value) { this.key = key; this.value = value; }
- }
- public BoundedOrderedConcurrentMap(int capacity) { this.capacity = capacity; }
- public void put(K key, V value) {
- lock.lock();
- try {
- if (map.containsKey(key)) {
- map.get(key).value = value;
- return;
- }
- if (map.size() >= capacity && head != null) {
- map.remove(head.key);
- removeNode(head);
- }
- Node<K, V> newNode = new Node<>(key, value);
- addLast(newNode);
- map.put(key, newNode);
- } finally { lock.unlock(); }
- }
- private void removeNode(Node<K, V> node) {
- if (node.prev != null) node.prev.next = node.next; else head = node.next;
- if (node.next != null) node.next.prev = node.prev; else tail = node.prev;
- }
- private void addLast(Node<K, V> node) {
- if (tail == null) head = tail = node;
- else { tail.next = node; node.prev = tail; tail = node; }
- }
- public Map<K, V> getSnapshot() {
- lock.lock();
- try {
- Map<K, V> snapshot = new LinkedHashMap<>();
- for (Node<K, V> curr = head; curr != null; curr = curr.next) {
- snapshot.put(curr.key, curr.value);
- }
- return snapshot;
- } finally { lock.unlock(); }
- }
- }
- private final ExecutorService executor;
- private final BoundedOrderedConcurrentMap<String, TaskOutcome> storage;
- public ProcessingEngine(int poolThreads, int maxCapacity) {
- this.executor = Executors.newFixedThreadPool(poolThreads);
- this.storage = new BoundedOrderedConcurrentMap<>(maxCapacity);
- }
- public ExecutionSummary processTasks(Map<String, Callable<Object>> tasks, long timeout, TimeUnit unit) {
- AtomicInteger success = new AtomicInteger(0), failed = new AtomicInteger(0), timedOut = new AtomicInteger(0);
- List<CompletableFuture<Void>> futures = new ArrayList<>();
- for (var entry : tasks.entrySet()) {
- String taskId = entry.getKey();
- futures.add(CompletableFuture.supplyAsync(() -> {
- try { return entry.getValue().call(); }
- catch (Exception e) { throw new CompletionException(e); }
- }, executor)
- .orTimeout(timeout, unit)
- .handle((res, ex) -> {
- TaskOutcome outcome;
- if (ex != null) {
- Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
- if (cause instanceof TimeoutException) {
- outcome = new TaskTimeout(taskId);
- timedOut.incrementAndGet();
- } else {
- outcome = new TaskFailure(taskId, cause);
- failed.incrementAndGet();
- }
- } else {
- outcome = new TaskSuccess(taskId, res);
- success.incrementAndGet();
- }
- storage.put(taskId, outcome);
- return null;
- }));
- }
- CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
- return new ExecutionSummary(tasks.size(), success.get(), failed.get(), timedOut.get(), storage.getSnapshot());
- }
- public void shutdown() {
- executor.shutdown();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment