/** * Starts the consumer which will register a queue or topic listener with Hazelcast and enable * message consumption (push or pull). If the consumer is already active, this method does * nothing. */ void start() { if (active) { return; } receiveLock.lock(); try { // Start listening for events. We currently always listen for events even // if we don't have a message listener. If this has a performance impact // on Hazelcast we may want to only listen if there is a registered // message listener that we need to notify. IQueue<byte[]> queue = hazelcastMQContext.resolveQueue(destination); if (queue != null) { // Get the raw queue outside of any transactional context so we can add // an item listener. queue = config.getHazelcastInstance().getQueue(queue.getName()); queueListener = new HzQueueListener(queue); } // If we are a consumer on a topic, immediately start listening for events // so we can buffer them for (a)synchronous consumption. ITopic<byte[]> topic = hazelcastMQContext.resolveTopic(destination); if (topic != null) { topicListener = new HzTopicListener(topic); } active = true; if (messageListener != null) { // We have a message listener, so tell the context to drain the dispatch // ready queues. hazelcastMQContext.onConsumerDispatchReady(id); } else { // Signal that any receive requests can continue. receiveCondition.signalAll(); } } finally { receiveLock.unlock(); } }
/** * Attempts to receive a message using the given strategy. The method will continue to attempt to * receive until either {@link ReceiveStrategy#isRetryable()} returns false, a message is * received, or the consumer is stopped. * * @param strategy the strategy to use for receiving the message and determining retries * @return the message or null if no message was received */ private HazelcastMQMessage doReceive(ReceiveStrategy strategy) { HazelcastMQMessage msg = null; do { receiveLock.lock(); try { IQueue<byte[]> queue = hazelcastMQContext.resolveQueue(destination); if (queue == null && topicListener == null) { throw new HazelcastMQException( format("Destination cannot be resolved [%s].", destination)); } else if (queue == null) { queue = topicListener.getQueue(); } byte[] msgData = strategy.receive(queue); if (msgData != null) { msg = config.getMessageConverter().toMessage(msgData); } // Check for message expiration if we have a message with expiration // time. if (msg != null && msg.getHeaders().get(Headers.EXPIRATION) != null) { long expirationTime = Long.parseLong(msg.getHeaders().get(Headers.EXPIRATION)); if (expirationTime != 0 && expirationTime <= System.currentTimeMillis()) { log.info("Dropping message [{}] because it has expired.", msg.getId()); msg = null; } } } finally { receiveLock.unlock(); } } while (msg == null && !closed && strategy.isRetryable()); return msg; }