package com.jstorm.example.unittests.sequence;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichSpout;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import com.alibaba.jstorm.common.metric.AsmCounter;
import com.alibaba.jstorm.metric.MetricClient;
import com.alibaba.jstorm.utils.JStormUtils;
import com.alipay.dw.jstorm.example.sequence.SequenceTopologyDef;
import com.alipay.dw.jstorm.example.sequence.bean.Pair;
import com.alipay.dw.jstorm.example.sequence.bean.PairMaker;
import com.alipay.dw.jstorm.example.sequence.bean.TradeCustomer;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by binyang.dby on 2016/7/8.
*/
public class SequenceTestSpout implements IRichSpout
{
private MetricClient metricClient;
private AsmCounter emitCounter;
private AsmCounter successCounter;
private AsmCounter failCounter;
private AsmCounter tradeSumCounter;
private AsmCounter customerSumCounter;
private SpoutOutputCollector collector;
private boolean isFinished = false;
private static long SPOUT_MAX_SEND_NUM;
private final static long MAX_PENDING_COUNTER = Long.MAX_VALUE;
private int tupleId;
private Random idGenerator;
private AtomicLong handleCounter = new AtomicLong(0);
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("ID", "RECORD"));
declarer.declareStream(SequenceTopologyDef.CONTROL_STREAM_ID, new Fields("CONTROL"));
}
@Override
public Map<String, Object> getComponentConfiguration() {
return null;
}
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
this.metricClient = new MetricClient(context);
this.emitCounter = metricClient.registerCounter(SequenceTestMetricsDef.METRIC_SPOUT_EMIT);
this.successCounter = metricClient.registerCounter(SequenceTestMetricsDef.METRIC_SPOUT_SUCCESS);
this.failCounter = metricClient.registerCounter(SequenceTestMetricsDef.METRIC_SPOUT_FAIL);
this.tradeSumCounter = metricClient.registerCounter(SequenceTestMetricsDef.METRIC_SPOUT_TRADE_SUM);
this.customerSumCounter = metricClient.registerCounter(SequenceTestMetricsDef.METRIC_SPOUT_CUSTOMER_SUM);
this.isFinished = false;
this.idGenerator = new Random();
SPOUT_MAX_SEND_NUM = (long)conf.get("spout.max.sending.num");
JStormUtils.sleepMs(10 * 1000);
}
@Override
public void close() {
}
@Override
public void activate() {
}
@Override
public void deactivate() {
}
@Override
public void nextTuple() {
if (isFinished) {
long now = System.currentTimeMillis();
String ctrlMsg = "spout don't send message due to pending num at " + now;
collector.emit(SequenceTopologyDef.CONTROL_STREAM_ID, new Values(String.valueOf(now)), ctrlMsg);
JStormUtils.sleepMs(1000);
return;
}
if (tupleId >= SPOUT_MAX_SEND_NUM) {
isFinished = true;
return;
}
emit();
}
public void emit() {
emitCounter.inc();
Pair trade = PairMaker.makeTradeInstance();
Pair customer = PairMaker.makeCustomerInstance();
TradeCustomer tradeCustomer = new TradeCustomer();
tradeCustomer.setTrade(trade);
tradeCustomer.setCustomer(customer);
tradeCustomer.setBuffer(null);
tradeSumCounter.update(trade.getValue());
customerSumCounter.update(customer.getValue());
collector.emit(new Values(idGenerator.nextLong(), tradeCustomer), tupleId);
tupleId++;
handleCounter.incrementAndGet();
while (handleCounter.get() >= MAX_PENDING_COUNTER - 1) {
JStormUtils.sleepMs(1);
}
}
@Override
public void ack(Object msgId) {
handleCounter.decrementAndGet();
successCounter.inc();
}
@Override
public void fail(Object msgId) {
handleCounter.decrementAndGet();
failCounter.inc();
}
}