package org.myeslib.example.hazelcast.routes; import java.util.List; import java.util.UUID; import java.util.Vector; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.myeslib.core.data.Snapshot; import org.myeslib.core.storage.SnapshotReader; import org.myeslib.example.SampleDomain.InventoryItemAggregateRoot; import com.google.inject.Inject; import com.hazelcast.core.IMap; import com.hazelcast.core.IQueue; @Slf4j @RequiredArgsConstructor(onConstructor=@__(@Inject)) public class HzConsumeEventsRoute extends RouteBuilder { static final String ID = "ID"; static final int MAX_EVENTS_PER_POOLING = 100; final int eventsQueueConsumers; final SnapshotReader<UUID, InventoryItemAggregateRoot> snapshotReader; final IMap<UUID, Snapshot<InventoryItemAggregateRoot>> lastSnapshotMap; final IQueue<UUID> eventsQueue; final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); @Override public void configure() throws Exception { from("timer://eventsQueuePolling?fixedRate=true&period=1s") .routeId("timer:eventsQueuePolling") .process(new EventsQueuePoolerProcessor()) .split(body()) .parallelProcessing() .streaming() //.log("received ${body}") .process(new Processor() { @Override public void process(Exchange e) throws Exception { UUID id = e.getIn().getBody(UUID.class); Snapshot<InventoryItemAggregateRoot> snapshot = snapshotReader.get(id); e.getOut().setHeader(ID, id); e.getOut().setBody(snapshot); } }) //.log("produced ${body}") .to("direct:reflect-last-snapshot", "direct:reflect-query-model") ; from("direct:reflect-last-snapshot") .routeId("direct:reflect-last-snapshot") .process(new Processor() { @SuppressWarnings("unchecked") @Override public void process(Exchange e) throws Exception { lastSnapshotMap.set(header(ID).evaluate(e, UUID.class), body().evaluate(e, Snapshot.class)); } }) ; from("direct:reflect-query-model") .routeId("direct:reflect-query-model") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { // do nothing } }); } class EventsQueuePoolerProcessor implements Processor { @Override public void process(Exchange e) throws Exception { log.debug("will start polling eventsQueue..."); Future<List<UUID>> pooledEvents = singleThreadExecutor.submit(new EventsQueuePooler()); singleThreadExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS); e.getOut().setBody(pooledEvents.get(), List.class); if (pooledEvents.get().size()>0){ log.info("found {} events", e.getOut().getBody(List.class).size()); } } } class EventsQueuePooler implements Callable<List<UUID>> { @Override public List<UUID> call() throws Exception { final List<UUID> pooledEvents = new Vector<>(); for (int i = 0; i < MAX_EVENTS_PER_POOLING; i++) { try { //log.info("polling step {} ", i); UUID uuid = eventsQueue.poll(10, TimeUnit.MILLISECONDS); if (uuid !=null ) { log.debug("found {}", uuid.toString()); pooledEvents.add(uuid); } else { log.debug("did not found any event"); } } catch ( InterruptedException e){ log.debug("interrupted..."); } } return pooledEvents; } } }