@Override public void discard(String queueMsgId) { Objects.requireNonNull(queueMsgId); LOG.debug("Discarding message id {}", queueMsgId); workerQueue.discardTask(queueMsgId); stats.incrementTasksDiscarded(); }
@Override public void abandon(final String queueMsgId, final Exception e) { LOG.debug("Rejecting message id {}", queueMsgId); workerQueue.rejectTask(queueMsgId); stats.incrementTasksRejected(); workerQueue.disconnectIncoming(); transientHealthCheck.addTransientExceptionToRegistry(e.getMessage()); healthCheckRegistry.runHealthCheck("transient"); }
/** * Begin accepting tasks to process. * * @throws QueueException if the queues cannot be started */ public void start() throws QueueException { workerQueue.start(callback); }
@Override public void forward(String queueMsgId, String queue, TaskMessage forwardedMessage, Map<String, Object> headers) { Objects.requireNonNull(queueMsgId); Objects.requireNonNull(forwardedMessage); // queue can be null for a dead end worker LOG.debug("Task {} (message id: {}) being forwarded to queue {}", forwardedMessage.getTaskId(), queueMsgId, queue); checkForTrackingTermination(queueMsgId, queue, forwardedMessage); try { // If the queue is null, acknowledge the task rather than forwarding it if (queue == null) { workerQueue.acknowledgeTask(queueMsgId); } else { // Else forward the task byte[] output = codec.serialise(forwardedMessage); workerQueue.publish(queueMsgId, output, queue, headers, forwardedMessage.getPriority() == null ? 0 : forwardedMessage.getPriority()); stats.incrementTasksForwarded(); //TODO - I'm guessing this stat should not be updated for forwarded messages: // stats.getOutputSizes().update(output.length); } } catch (CodecException | QueueException e) { LOG.error("Cannot publish data for forwarded task {}, rejecting", forwardedMessage.getTaskId(), e); abandon(queueMsgId, e); } }
/** * Disconnects the queue if any health check fails and re-connects it when the worker becomes healthy again. */ @Override protected Result check() throws Exception { synchronized (healthCheckLock) { final Result result = healthCheck.execute(); if (!result.isHealthy()) { // Add the name of the failed health check to the set of unhealthy checks unhealthySet.add(name); } else if (!unhealthySet.isEmpty()) { // Remove the name of the health check if it is present in the unhealthy set unhealthySet.remove(name); } if (unhealthySet.isEmpty()) { LOG.debug("Reconnecting the incoming queue as all health checks are passing"); workerQueue.reconnectIncoming(); } else { LOG.debug("Disconnecting the incoming queue due to the [{}] health check failing", name); workerQueue.disconnectIncoming(); } return result; } } }
@Override public void reportUpdate(final String queueMsgId, final TaskMessage reportUpdateMessage) { Objects.requireNonNull(queueMsgId); Objects.requireNonNull(reportUpdateMessage); LOG.debug("Sending report updates to queue {})", reportUpdateMessage.getTo()); final byte[] output; try { output = codec.serialise(reportUpdateMessage); } catch (final CodecException ex) { throw new RuntimeException(ex); } final int priority = reportUpdateMessage.getPriority() == null ? 0 : reportUpdateMessage.getPriority(); try { workerQueue.publish("-1", output, reportUpdateMessage.getTo(), Collections.emptyMap(), priority); } catch (final QueueException ex) { throw new RuntimeException(ex); } }
private void initComponentMetrics(final MetricRegistry metrics, final ManagedConfigurationSource config, final ManagedDataStore store, final WorkerCore core) { metrics.register(MetricRegistry.name("config.lookups"), (Gauge<Integer>) config::getConfigurationRequests); metrics.register(MetricRegistry.name("config.errors"), (Gauge<Integer>) config::getConfigurationErrors); if (store.getMetrics() != null) { metrics.register(MetricRegistry.name("store.writes"), (Gauge<Integer>) store.getMetrics()::getStoreRequests); metrics.register(MetricRegistry.name("store.reads"), (Gauge<Integer>) store.getMetrics()::getRetrieveRequests); metrics.register(MetricRegistry.name("store.deletes"), (Gauge<Integer>) store.getMetrics()::getDeleteRequests); metrics.register(MetricRegistry.name("store.errors"), (Gauge<Integer>) store.getMetrics()::getErrors); } if (core.getWorkerQueue().getMetrics() != null) { metrics.register(MetricRegistry.name("queue.received"), (Gauge<Integer>) core.getWorkerQueue().getMetrics()::getMessagesReceived); metrics.register(MetricRegistry.name("queue.published"), (Gauge<Integer>) core.getWorkerQueue().getMetrics()::getMessagesPublished); metrics.register(MetricRegistry.name("queue.rejected"), (Gauge<Integer>) core.getWorkerQueue().getMetrics()::getMessagesRejected); metrics.register(MetricRegistry.name("queue.dropped"), (Gauge<Integer>) core.getWorkerQueue().getMetrics()::getMessagesDropped); metrics.register(MetricRegistry.name("queue.errors"), (Gauge<Integer>) core.getWorkerQueue().getMetrics()::getQueueErrors); } } }
private void registerNewTaskImpl(final String queueMsgId, final byte[] taskMessage, Map<String, Object> headers) throws InvalidTaskException, TaskRejectedException { try { TaskMessage tm = codec.deserialise(taskMessage, TaskMessage.class, DecodeMethod.LENIENT); LOG.debug("Received task {} (message id: {})", tm.getTaskId(), queueMsgId); boolean poison = isTaskPoisoned(headers); validateTaskMessage(tm); boolean taskIsActive = checkStatus(tm); if (taskIsActive) { if (tm.getTo() != null && tm.getTo().equalsIgnoreCase(workerQueue.getInputQueue())) { LOG.debug("Task {} (message id: {}) on input queue {} {}", tm.getTaskId(), queueMsgId, workerQueue.getInputQueue(), (tm.getTo() != null) ? "is intended for this worker" : "has no explicit destination, therefore assuming it is intended for this worker"); executor.executeTask(tm, queueMsgId, poison, headers, codec); } else { LOG.debug("Task {} (message id: {}) is not intended for this worker: input queue {} does not match message destination queue {}", tm.getTaskId(), queueMsgId, workerQueue.getInputQueue(), tm.getTo()); executor.forwardTask(tm, queueMsgId, headers); } } else { LOG.debug("Task {} is no longer active. The task message (message id: {}) will not be executed", tm.getTaskId(), queueMsgId); executor.discardTask(tm, queueMsgId); } } catch (CodecException e) { throw new InvalidTaskException("Queue data did not deserialise to a TaskMessage", e); } catch (InvalidJobTaskIdException ijte) { throw new InvalidTaskException("TaskMessage contains an invalid job task identifier", ijte); } }
workerQueue.acknowledgeTask(queueMsgId); } else { workerQueue.publish(queueMsgId, output, queue, Collections.emptyMap(), responseMessage.getPriority() == null ? 0 : responseMessage.getPriority()); stats.getOutputSizes().update(output.length);
@Override public void send(final String queueMsgId, final TaskMessage responseMessage) { Objects.requireNonNull(queueMsgId); Objects.requireNonNull(responseMessage); LOG.debug("Sending task {} complete (message id: {})", responseMessage.getTaskId(), queueMsgId); final String queue = responseMessage.getTo(); checkForTrackingTermination(queueMsgId, queue, responseMessage); final byte[] output; try { output = codec.serialise(responseMessage); } catch (final CodecException ex) { throw new RuntimeException(ex); } final int priority = responseMessage.getPriority() == null ? 0 : responseMessage.getPriority(); try { workerQueue.publish("-1", output, queue, Collections.emptyMap(), priority); } catch (final QueueException ex) { throw new RuntimeException(ex); } }