{
List<String> partitionNames = message.getPartitionNames();
AtomicInteger countDown = new AtomicInteger(partitionNames.size());
for (String partitionName : partitionNames)
{
Message msg = new Message(message.getRecord());
msg.setPartitionName(partitionName);
msg.setGroupMsgCountDown(countDown);
logger.info("Creating handler for group message " + msg.getMsgId() + "/"
+ partitionName);
MessageHandler handler = createMessageHandler(msg, changeContext);
// We did not find a MessageHandlerFactory for the message;
// we will keep the message and we may be able to handler it when
// the corresponding MessageHandlerFactory factory is registered.
if (handler == null)
{
logger.warn("Message handler factory not found for group message type:"
+ msg.getMsgType() + ", message:" + msg);
continue;
}
handlers.add(handler);
handleMessages.add(msg);
}
}
}
catch (Exception e)
{
logger.error("Failed to create message handler for " + message.getMsgId(), e);
String error =
"Failed to create message handler for " + message.getMsgId()
+ " exception: " + e;
_statusUpdateUtil.logError(message,
HelixStateMachineEngine.class,
e,
error,
accessor);
// Mark the message as UNPROCESSABLE if we hit a exception while creating
// handler for it. The message will stay on ZK and not be processed.
message.setMsgState(MessageState.UNPROCESSABLE);
if (message.getTgtName().equalsIgnoreCase("controller"))
{
accessor.updateProperty(keyBuilder.controllerMessage(message.getId()),
message);
}
else
{
accessor.updateProperty(keyBuilder.message(instanceName, message.getId()),
message);
}
continue;
}
// update msgState to read
message.setMsgState(MessageState.READ);
message.setReadTimeStamp(new Date().getTime());
message.setExecuteSessionId(changeContext.getManager().getSessionId());
_statusUpdateUtil.logInfo(message,
HelixStateMachineEngine.class,
"New Message",
accessor);
// batch all messages
readMsgs.add(message);
if (message.getTgtName().equalsIgnoreCase("controller"))
{
readMsgKeys.add(keyBuilder.controllerMessage(message.getMsgId()));
}
else
{
// batch all creation of current state meta data
// do it for state transition messages only
if (message.getMsgType()
.equals(Message.MessageType.STATE_TRANSITION.toString()))
{
String resourceName = message.getResourceName();
if (!curResourceNames.contains(resourceName)
&& !createCurStateNames.contains(resourceName))
{
createCurStateNames.add(resourceName);
createCurStateKeys.add(keyBuilder.currentState(instanceName,
sessionId,
resourceName));
CurrentState metaCurState = new CurrentState(resourceName);
metaCurState.setBucketSize(message.getBucketSize());
metaCurState.setStateModelDefRef(message.getStateModelDef());
metaCurState.setSessionId(sessionId);
metaCurState.setGroupMessageMode(message.getGroupMessageMode());
String ftyName = message.getStateModelFactoryName();
if (ftyName != null)
{
metaCurState.setStateModelFactoryName(ftyName);
}
else
{
metaCurState.setStateModelFactoryName(HelixConstants.DEFAULT_STATE_MODEL_FACTORY);
}
metaCurStates.add(metaCurState);
}
}
readMsgKeys.add(keyBuilder.message(instanceName, message.getMsgId()));
}
}
else
{
// This will happen because we don't delete the message as soon as we
// read it.
// We keep it until the current state is changed.
// We will read the message again if there is a new message but we
// check for the status and ignore if its already read
logger.trace("Message already read" + message.getMsgId());
// _statusUpdateUtil.logInfo(message, StateMachineEngine.class,
// "Message already read", client);
}
}
else
{
String warningMessage =
"Session Id does not match. Expected sessionId: " + sessionId
+ ", sessionId from Message: " + tgtSessionId + ". MessageId: "
+ message.getMsgId();
logger.warn(warningMessage);
accessor.removeProperty(keyBuilder.message(instanceName, message.getId()));
_statusUpdateUtil.logWarning(message,
HelixStateMachineEngine.class,
warningMessage,
accessor);
}
}
// batch create curState meta
if (createCurStateKeys.size() > 0)
{
try
{
accessor.createChildren(createCurStateKeys, metaCurStates);
}
catch (Exception e)
{
logger.error(e);
}
}
// update messages in batch and schedule all read messages
if (readMsgs.size() > 0)
{
accessor.setChildren(readMsgKeys, readMsgs);
for (int i = 0; i < handlers.size(); i++)
{
MessageHandler handler = handlers.get(i);
Message handleMessage = handleMessages.get(i);
scheduleTask(handleMessage, handler, changeContext);
}
}
}