/* * Copyright (c) 2014 Globo.com - ATeam * All rights reserved. * * This source is subject to the Apache License, Version 2.0. * Please see the LICENSE file for more information. * * Authors: See AUTHORS file * * 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.globo.galeb.bus; import static com.globo.galeb.bus.IQueueService.ACTION.*; import java.io.UnsupportedEncodingException; import org.vertx.java.core.Handler; import org.vertx.java.core.eventbus.EventBus; import org.vertx.java.core.eventbus.Message; import org.vertx.java.core.json.DecodeException; import org.vertx.java.core.json.JsonObject; import org.vertx.java.platform.Verticle; import com.globo.galeb.entity.IJsonable; import com.globo.galeb.logger.SafeLogger; /** * Class VertxQueueService. * * @author: See AUTHORS file. * @version: 1.0.0, Oct 23, 2014. */ public class VertxQueueService implements IQueueService { /** The Vertx EventBus. */ private final EventBus eb; /** The logger. */ private final SafeLogger log; /** * Instantiates a new vertxQueueService. * * @param eb the eb * @param log the log */ public VertxQueueService(final EventBus eb, final SafeLogger log) { this.eb=eb; this.log=log; } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#queueToAdd(com.globo.galeb.core.SafeJsonObject, java.lang.String) */ @Override public void queueToAdd(JsonObject json, final String uri) { putMessageToQueue(json, IQueueService.ACTION.ADD, uri); } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#queueToDel(com.globo.galeb.core.SafeJsonObject, java.lang.String) */ @Override public void queueToDel(JsonObject json, final String uri) { putMessageToQueue(json, IQueueService.ACTION.DEL, uri); } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#queueToChange(com.globo.galeb.core.SafeJsonObject, java.lang.String) */ @Override public void queueToChange(JsonObject json, final String uri) { // putMessageToQueue(json, ACTION.CHANGE, uri); String messageLog = String.format("%s: Change not implemented", this.toString()); if (log!=null) { log.warn(messageLog); } else { System.out.println(messageLog); } } /** * Put message to queue. * * @param json the json * @param action the action * @param uri the uri */ private void putMessageToQueue(JsonObject json, IQueueService.ACTION action, final String uri) { Long version = 0L; try { version = json.getLong("version"); } catch (DecodeException e) { if (log!=null) { log.error(e.getMessage()); } else { System.err.println(e.getMessage()); } return; } json.removeField("version"); String parentId = json.getString(MessageBus.PARENT_ID_FIELDNAME, ""); MessageBus messageBus = new MessageBus() .setUri(uri) .setEntity(json.encode()); if (!"".equals(parentId)) { messageBus.setParentId(parentId); } String message = messageBus.make().toString(); publishAction(message, action); publishAction(String.format("%d", version), IQueueService.ACTION.SET_VERSION); } /** * Publish action. * * @param message the message * @param action the action */ private void publishAction(String message, final IQueueService.ACTION action) { if (eb!=null) { eb.publish(action.toString(), message); } else { System.out.println(String.format("publish at %s queue: %s", action.toString(), message)); } String debugMessage = String.format("Sending %s to %s",message, action.toString()); if (log!=null) { log.debug(debugMessage); } else { System.out.println(debugMessage); } } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#registerHealthcheck(com.globo.galeb.core.bus.ICallbackHealthcheck) */ @Override public void registerHealthcheck(final ICallbackHealthcheck callbackHealthcheck) { if (eb==null) { return; } eb.registerHandler(IQueueService.QUEUE_HEALTHCHECK_OK, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { JsonObject backend = message.body(); try { callbackHealthcheck.moveBackend(backend, true); } catch (UnsupportedEncodingException e) { log.error(e.getMessage()); } log.debug(String.format("Backend %s OK", backend)); }; }); eb.registerHandler(IQueueService.QUEUE_HEALTHCHECK_FAIL, new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { JsonObject backend = message.body(); try { callbackHealthcheck.moveBackend(backend, false); } catch (UnsupportedEncodingException e) { log.error(e.getMessage()); } log.error(String.format("Backend %s FAIL", backend)); }; }); } /* (non-Javadoc) * @see com.globo.galeb.bus.IQueueService#publishBackendOk(org.vertx.java.core.json.JsonObject) */ @Override public void publishBackendOk(JsonObject backend) { if (eb==null) { return; } String backendId = backend.getString(IJsonable.ID_FIELDNAME); eb.publish(IQueueService.QUEUE_HEALTHCHECK_OK, backend); log.info(String.format("Backend %s OK. Enabling it", backendId)); } /* (non-Javadoc) * @see com.globo.galeb.bus.IQueueService#publishBackendFail(org.vertx.java.core.json.JsonObject) */ @Override public void publishBackendFail(JsonObject backend) { if (eb==null) { return; } String backendId = backend.getString(IJsonable.ID_FIELDNAME); eb.publish(IQueueService.QUEUE_HEALTHCHECK_FAIL, backend); log.info(String.format("Backend %s Fail. disabling it", backendId)); } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#publishBackendConnections(java.lang.String, com.globo.galeb.core.SafeJsonObject) */ @Override public void publishBackendConnections(String queueActiveConnections, JsonObject myConnections) { eb.publish(queueActiveConnections, myConnections); } /** * Connection counter handler. * * @param connectionsCounter the connections counter * @return the handler */ private Handler<Message<JsonObject>> connectionCounterHandler(final ICallbackConnectionCounter connectionsCounter) { return new Handler<Message<JsonObject>>() { @Override public void handle(Message<JsonObject> message) { connectionsCounter.callbackGlobalConnectionsInfo(message.body()); } }; } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#registerConnectionsCounter(com.globo.galeb.core.bus.ICallbackConnectionCounter, java.lang.String) */ @Override public void registerConnectionsCounter(final ICallbackConnectionCounter connectionsCounter, String queueActiveConnections) { if (eb==null) { return; } if (!connectionsCounter.isRegistered()) { eb.registerLocalHandler(queueActiveConnections, connectionCounterHandler(connectionsCounter)); connectionsCounter.setRegistered(true); } } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#publishActiveConnections(java.lang.String, com.globo.galeb.core.SafeJsonObject) */ @Override public void publishActiveConnections(String queueActiveConnections, JsonObject myConnections) { if (eb==null) { return; } eb.publish(queueActiveConnections, myConnections); } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#unregisterConnectionsCounter(com.globo.galeb.core.bus.ICallbackConnectionCounter, java.lang.String) */ @Override public void unregisterConnectionsCounter(final ICallbackConnectionCounter connectionsCounter, String queueActiveConnections) { if (connectionsCounter.isRegistered() && eb!=null) { eb.unregisterHandler(queueActiveConnections, connectionCounterHandler(connectionsCounter)); connectionsCounter.setRegistered(false); } } /** * Log if eventBus is null. */ private void logEventBusNull() { String logMessage = "registerQueueAdd is not possible: EventBus is null"; if (log!=null) { log.warn(logMessage); } else { System.err.println(logMessage); } } /** * Log queue registered. * * @param starter the starter * @param queue the queue */ private void logQueueRegistered(String starter, String queue) { String message = String.format("[%s] %s registered", starter, queue); if (log!=null) { log.info(message); } else { System.err.println(message); } } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#registerQueueAdd(java.lang.Object, com.globo.galeb.core.bus.ICallbackQueueAction) */ @Override public void registerQueueAdd(final Object starter, final ICallbackQueueAction callbackQueueAction) { final Verticle verticle; if (starter instanceof Verticle) { verticle = (Verticle)starter; } else { log.error("Starter is not instanceof Verticle"); return; } Handler<Message<String>> addHandler = new Handler<Message<String>>() { @Override public void handle(Message<String> message) { log.debug(String.format("Received %s at %s queue", message.body(), ADD.toString())); callbackQueueAction.addToMap(message.body()); if (verticle != null && verticle instanceof IEventObserver) { ((IEventObserver)verticle).postAddEvent(message.body()); } } }; if (eb!=null) { eb.registerHandler(ADD.toString(), addHandler); logQueueRegistered(starter.toString(), ADD.toString()); } else { logEventBusNull(); } } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#registerQueueDel(java.lang.Object, com.globo.galeb.core.bus.ICallbackQueueAction) */ @Override public void registerQueueDel(final Object starter, final ICallbackQueueAction callbackQueueAction) { final Verticle verticle; if (starter instanceof Verticle) { verticle = (Verticle)starter; } else { log.error("Starter is not instanceof Verticle"); return; } Handler<Message<String>> queueDelHandler = new Handler<Message<String>>() { @Override public void handle(Message<String> message) { log.debug(String.format("Received %s at %s queue", message.body(), DEL.toString())); callbackQueueAction.delFromMap(message.body()); if (verticle != null && verticle instanceof IEventObserver) { ((IEventObserver)verticle).postDelEvent(message.body()); } } }; if (eb!=null) { eb.registerHandler(DEL.toString(),queueDelHandler); logQueueRegistered(starter.toString(), DEL.toString()); } else { logEventBusNull(); } } /* (non-Javadoc) * @see com.globo.galeb.core.bus.IQueueService#registerQueueVersion(java.lang.Object, com.globo.galeb.core.bus.ICallbackQueueAction) */ @Override public void registerQueueVersion(final Object starter, final ICallbackQueueAction callbackQueueAction) { Handler<Message<String>> queueVersionHandler = new Handler<Message<String>>() { @Override public void handle(Message<String> message) { log.debug(String.format("Received %s at %s queue", message.body(), SET_VERSION.toString())); try { callbackQueueAction.setVersion(Long.parseLong(message.body())); } catch (java.lang.NumberFormatException ignore) { // not change version } } }; if (eb!=null) { eb.registerHandler(SET_VERSION.toString(), queueVersionHandler); logQueueRegistered(starter.toString(), SET_VERSION.toString()); } else { logEventBusNull(); } } }