subStats.incrementFailedOps();
ServerStats.getInstance().incrementRequestsRedirect();
return;
}
final SubscribeRequest subRequest = request.getSubscribeRequest();
final ByteString subscriberId = subRequest.getSubscriberId();
MessageSeqId lastSeqIdPublished = MessageSeqId.newBuilder(seqId).setLocalComponent(seqId.getLocalComponent()).build();
final long requestTime = MathUtils.now();
subMgr.serveSubscribeRequest(topic, subRequest, lastSeqIdPublished, new Callback<SubscriptionData>() {
@Override
public void operationFailed(Object ctx, PubSubException exception) {
channel.write(PubSubResponseUtils.getResponseForException(exception, request.getTxnId())).addListener(
ChannelFutureListener.CLOSE);
logger.error("Error serving subscribe request (" + request.getTxnId() + ") for (topic: "
+ topic.toStringUtf8() + " , subscriber: " + subscriberId.toStringUtf8() + ")", exception);
subStats.incrementFailedOps();
}
@Override
public void operationFinished(Object ctx, final SubscriptionData subData) {
TopicSubscriber topicSub = new TopicSubscriber(topic, subscriberId);
synchronized (channel) {
if (!channel.isConnected()) {
// channel got disconnected while we were processing the
// subscribe request,
// nothing much we can do in this case
subStats.incrementFailedOps();
return;
}
}
// initialize the message filter
PipelineFilter filter = new PipelineFilter();
try {
// the filter pipeline should be
// 1) AllToAllTopologyFilter to filter cross-region messages
filter.addLast(new AllToAllTopologyFilter());
// 2) User-Customized MessageFilter
if (subData.hasPreferences() &&
subData.getPreferences().hasMessageFilter()) {
String messageFilterName = subData.getPreferences().getMessageFilter();
filter.addLast(ReflectionUtils.newInstance(messageFilterName, ServerMessageFilter.class));
}
// initialize the filter
filter.initialize(cfg.getConf());
filter.setSubscriptionPreferences(topic, subscriberId,
subData.getPreferences());
} catch (RuntimeException re) {
String errMsg = "RuntimeException caught when instantiating message filter for (topic:"
+ topic.toStringUtf8() + ", subscriber:" + subscriberId.toStringUtf8() + ")."
+ "It might be introduced by programming error in message filter.";
logger.error(errMsg, re);
PubSubException pse = new PubSubException.InvalidMessageFilterException(errMsg, re);
subStats.incrementFailedOps();
// we should not close the subscription channel, just response error
// client decide to close it or not.
channel.write(PubSubResponseUtils.getResponseForException(pse, request.getTxnId()));
return;
} catch (Throwable t) {
String errMsg = "Failed to instantiate message filter for (topic:" + topic.toStringUtf8()
+ ", subscriber:" + subscriberId.toStringUtf8() + ").";
logger.error(errMsg, t);
PubSubException pse = new PubSubException.InvalidMessageFilterException(errMsg, t);
subStats.incrementFailedOps();
channel.write(PubSubResponseUtils.getResponseForException(pse, request.getTxnId()))
.addListener(ChannelFutureListener.CLOSE);
return;
}
boolean forceAttach = false;
if (subRequest.hasForceAttach()) {
forceAttach = subRequest.getForceAttach();
}
// Try to store the subscription channel for the topic subscriber
Channel oldChannel = subChannelMgr.put(topicSub, channel, forceAttach);
if (null != oldChannel) {
PubSubException pse = new PubSubException.TopicBusyException(