public void onReceived( Executor executor, final String path, final int version, final String id, final Message message) { if (callback == null) { // Simply delete the message if (LOG.isDebugEnabled()) { LOG.debug("Ignoring incoming message from " + path + ": " + message); } listenFailure(zkClient.delete(path, version)); return; } executor.execute( new Runnable() { @Override public void run() { try { // Message process is synchronous for now. Making it async needs more thoughts about // race conditions. // The executor is the callbackExecutor which is a single thread executor. callback.onReceived(id, message).get(); } catch (Throwable t) { LOG.error("Exception when processing message: {}, {}, {}", id, message, path, t); } finally { listenFailure(zkClient.delete(path, version)); } } }); }
private void processMessage(final String path, final String messageId) { Futures.addCallback( zkClient.getData(path), new FutureCallback<NodeData>() { @Override public void onSuccess(NodeData result) { Message message = MessageCodec.decode(result.getData()); if (message == null) { LOG.error("Failed to decode message for " + messageId + " in " + path); listenFailure(zkClient.delete(path, result.getStat().getVersion())); return; } if (LOG.isDebugEnabled()) { LOG.debug( "Message received from " + path + ": " + new String(MessageCodec.encode(message), Charsets.UTF_8)); } if (handleStopMessage( message, getDeleteSupplier(path, result.getStat().getVersion()))) { return; } messageCallback.onReceived( callbackExecutor, path, result.getStat().getVersion(), messageId, message); } @Override public void onFailure(Throwable t) { LOG.error("Failed to fetch message content.", t); } }); }
private void watchMessages() { final String messagesPath = getZKPath("messages"); Futures.addCallback( zkClient.getChildren( messagesPath, new Watcher() { @Override public void process(WatchedEvent event) { // TODO: Do we need to deal with other type of events? if (event.getType() == Event.EventType.NodeChildrenChanged && decoratedService.isRunning()) { watchMessages(); } } }), new FutureCallback<NodeChildren>() { @Override public void onSuccess(NodeChildren result) { // Sort by the name, which is the messageId. Assumption is that message ids is ordered // by time. List<String> messages = Lists.newArrayList(result.getChildren()); Collections.sort(messages); for (String messageId : messages) { processMessage(messagesPath + "/" + messageId, messageId); } } @Override public void onFailure(Throwable t) { // TODO: what could be done besides just logging? LOG.error("Failed to watch messages.", t); } }); }
private OperationFuture<String> createLiveNode() { String liveNode = getLiveNodePath(); LOG.info("Create live node " + liveNode); JsonObject content = new JsonObject(); content.add("data", liveNodeData.get()); return ZKOperations.ignoreError( zkClient.create(liveNode, encodeJson(content), CreateMode.EPHEMERAL), KeeperException.NodeExistsException.class, liveNode); }
private OperationFuture<String> removeLiveNode() { String liveNode = getLiveNodePath(); LOG.info("Remove live node " + liveNode); return ZKOperations.ignoreError( zkClient.delete(liveNode), KeeperException.NoNodeException.class, liveNode); }