com.srotya.tau.nucleus.processor.EmissionProcessor Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2016 Ambud Sharma
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.srotya.tau.nucleus.processor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import com.lmax.disruptor.EventHandler;
import com.srotya.tau.nucleus.DisruptorUnifiedFactory;
import com.srotya.tau.wraith.Constants;
import com.srotya.tau.wraith.Event;
import com.srotya.tau.wraith.MutableInt;
import com.srotya.tau.wraith.PerformantException;
import com.srotya.tau.wraith.Utils;
import com.srotya.tau.wraith.actions.Action;
import com.srotya.tau.wraith.actions.aggregations.AggregationAction;
import com.srotya.tau.wraith.rules.Rule;
import com.srotya.tau.wraith.rules.StatelessRulesEngine;
import com.srotya.tau.wraith.store.RulesStore;
/**
* @author Ambud
*
*/
public class EmissionProcessor extends AbstractProcessor {
private static final Logger logger = Logger.getLogger(EmissionProcessor.class.getName());
private ScheduledExecutorService es;
/**
* @param outputProcessors
* 0 - State, 1 - Fine Count Aggregation, 2 - Coarse Count
* Aggregation
*/
public EmissionProcessor(DisruptorUnifiedFactory factory, Map conf,
AbstractProcessor... outputProcessors) {
super(factory, 1, 128, conf, outputProcessors);
}
public static class EmissionHandler implements EventHandler {
private Map> ruleGroupMap;
private int tickCounter;
private DisruptorUnifiedFactory factory;
private AbstractProcessor[] processors;
public EmissionHandler(DisruptorUnifiedFactory factory, AbstractProcessor[] processors) {
this.factory = factory;
this.processors = processors;
}
public void initialize(Map conf) throws Exception {
int hashSize = Integer
.parseInt(conf.getOrDefault(Constants.RULE_HASH_INIT_SIZE, Constants.DEFAULT_RULE_HASH_SIZE));
this.ruleGroupMap = new HashMap<>(hashSize);
RulesStore store = null;
try {
store = factory.getRulesStore(conf.get(Constants.RSTORE_TYPE), conf);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw e;
}
try {
store.connect();
this.ruleGroupMap.putAll(store.listGroupedRules());
store.disconnect();
} catch (IOException e) {
logger.severe("Failed to load rules from store, reason:" + e.getMessage());
throw e;
}
}
@Override
public void onEvent(Event event, long sequence, boolean endOfBatch) throws Exception {
Object type = event.getHeaders().get(Constants.FIELD_EVENT_TYPE);
if (type != null && type.equals(Constants.EVENT_TYPE_RULE_UPDATE)) {
updateRule(event.getHeaders().get(Constants.FIELD_RULE_GROUP).toString(),
event.getHeaders().get(Constants.FIELD_RULE_CONTENT).toString(),
((Boolean) event.getHeaders().get(Constants.FIELD_RULE_DELETE)));
} else {
tickCounter++;
for (String ruleGroup : ruleGroupMap.keySet()) {
Map map = ruleGroupMap.get(ruleGroup);
for (Rule rule : map.values()) {
sendEmissionsForRule(ruleGroup, rule);
}
}
}
}
public void sendEmissionsForRule(String ruleGroup, Rule rule) {
List aggregationActions = filterAggregationActions(rule);
if (aggregationActions != null) {
for (AggregationAction action : aggregationActions) {
if (tickCounter % action.getTimeWindow() == 0) {
String ruleActionId = Utils.combineRuleActionId(rule.getRuleId(), action.getActionId());
Event event = factory.buildEvent();
event.getHeaders().put(Constants.FIELD_EVENT_TYPE, Constants.EVENT_TYPE_EMISSION);
event.getHeaders().put(Constants.FIELD_AGGREGATION_WINDOW, action.getTimeWindow());
event.getHeaders().put(Constants.FIELD_RULE_GROUP, ruleGroup);
event.getHeaders().put(Constants.FIELD_RULE_ACTION_ID, ruleActionId);
switch (action.getClass().getSimpleName()) {
case "StateAggregationAction":
processors[0].processEventNonWaled(event);
break;
case "FineCountingAggregationAction":
processors[1].processEventNonWaled(event);
break;
}
}
}
}
}
public static List filterAggregationActions(Rule rule) {
List actions = new ArrayList<>();
for (Action action : rule.getActions()) {
if (action instanceof AggregationAction) {
actions.add((AggregationAction) action);
}
}
return actions;
}
/**
* Update rule and trigger emissions for that rule so there are no
* orphan entries in aggregation maps since rule update may change the
* rule configuration.
*
* @param ruleGroup
* @param ruleJson
* @param delete
* @throws Exception
*/
public void updateRule(String ruleGroup, String ruleJson, boolean delete) throws Exception {
if (ruleGroup == null) {
throw new PerformantException("Supplied rule group is null");
}
Map ruleMap = ruleGroupMap.get(ruleGroup);
if (ruleMap == null) {
ruleMap = new LinkedHashMap<>(10);
ruleGroupMap.put(ruleGroup, ruleMap);
}
Rule rule = StatelessRulesEngine.updateRuleMap(ruleMap, ruleJson, delete);
logger.info("Processed rule update:" + rule);
sendEmissionsForRule(ruleGroup, rule);
}
}
@Override
public EventHandler instantiateAndInitializeHandler(int taskId, MutableInt parallelism,
Map conf, DisruptorUnifiedFactory factory) throws Exception {
es = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
es.scheduleAtFixedRate(() -> {
Event event = factory.buildEvent();
event.getHeaders().put(Constants.FIELD_EVENT_TYPE, "-1");
processEventNonWaled(event);
}, 10, 1, TimeUnit.SECONDS);
EmissionHandler handler = new EmissionHandler(factory, getOutputProcessors());
handler.initialize(conf);
return handler;
}
@Override
public String getConfigPrefix() {
return null;
}
@Override
public Logger getLogger() {
return logger;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy