package io.teknek.nibiru.trigger; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import io.teknek.nibiru.Keyspace; import io.teknek.nibiru.Server; import io.teknek.nibiru.Store; import io.teknek.nibiru.TriggerDefinition; import io.teknek.nibiru.TriggerLevel; import io.teknek.nibiru.transport.BaseMessage; import io.teknek.nibiru.transport.Response; public class TriggerManager { private ExecutorService executor; private final Server server; public TriggerManager(Server server){ this.server = server; } public CoordinatorTrigger getReusableTrigger(TriggerDefinition d){ try { CoordinatorTrigger ct = (CoordinatorTrigger) Class.forName(d.getTriggerClass()).newInstance(); return ct; } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { throw new RuntimeException(e); } } public Response executeTriggers(final BaseMessage message, final Response response, Keyspace keyspace, Store store, long timeoutInMs, long requestStart){ long now = System.currentTimeMillis(); for (TriggerDefinition d : store.getStoreMetadata().getCoordinatorTriggers()){ if (d.getTriggerLevel() == TriggerLevel.BLOCKING){ long remaining = (requestStart + timeoutInMs) - now; if (remaining > 0){ final CoordinatorTrigger ct = getReusableTrigger(d); Callable<Boolean> c = new Callable<Boolean>(){ public Boolean call() throws Exception { ct.exec(message, response, server); return Boolean.TRUE; } }; Future<Boolean> f = null; try { f = executor.submit(c); Boolean b = f.get(remaining, TimeUnit.MILLISECONDS); if (!b.equals(Boolean.TRUE)){ return new Response().withProperty("exception", "trigger returned false"); } } catch (InterruptedException | ExecutionException | TimeoutException e) { f.cancel(true); return new Response().withProperty("exception", "trigger exception " + e.getMessage()); } } } } return response; } public void init() { executor = Executors.newFixedThreadPool(1024); } public void shutdown() { executor.shutdown(); } }