/* * Copyright 2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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 io.atomix.group.messaging; import io.atomix.catalyst.annotations.Experimental; /** * Provides an interface for consuming messages sent either directly or indirectly to a group member. * <p> * Each {@link io.atomix.group.LocalMember member} of a group has a reference to a message service through * which the member can receive messages from other nodes in the cluster. Messages can be sent to a member * of a group either directly through the {@link io.atomix.group.GroupMember} API or indirectly via the * group-wide {@link MessageClient}. * <p> * When messages are received by a {@link MessageService} instance, the consumer(s) listeners for the * associated message queue will be called. Clients can register multiple consumers for a single queue. If * multiple consumers are registered, a single consumer will be called for each message using a round-robin * pattern. * <pre> * {@code * LocalMember localMember = group.join("foo").join(); * MessageConsumer<String> consumer = localMember.messaging().consumer("bar"); * consumer.onMessage(message -> { * message.ack(); * }); * } * </pre> * Messages can be handled by consumers in several ways. The message service can be used to receive * and acknowledge tasks or to receive messages for which the producer is awaiting a reply. The behavior * expected of a consumer is dependent on the producer configuration. For example, if the producer expects * a reply then consumers should reply. Consumers must always call either {@link Message#ack()} or * {@link Message#reply(Object)} on each message to complete the processing of the message. * <pre> * localMember.messaging().consumer("foo").onMessage(message -> { * message.reply("Hello world!"); * }); * </pre> * * @author <a href="http://github.com/kuujo>Jordan Halterman</a> */ @Experimental public interface MessageService extends MessageClient { /** * Creates a new named message consumer. * <p> * The returned consumer will consume messages sent to the service using a producer of the same name. * When a message is received by the member that owns this service, a single {@link MessageConsumer} * instance for the message will be called. If multiple consumers were created for the same queue on * the same {@link MessageService} instance, consumers will be called using a round-robin pattern. * <pre> * {@code * LocalMember localMember = group.join("foo").join(); * MessageConsumer<String> consumer = localMember.messaging().consumer("bar"); * consumer.onMessage(message -> { * message.ack(); * }); * } * </pre> * Messages can be handled by consumers in several ways. The message service can be used to receive * and acknowledge tasks or to receive messages for which the producer is awaiting a reply. The behavior * expected of a consumer is dependent on the producer configuration. For example, if the producer expects * a reply then consumers should reply. Consumers must always call either {@link Message#ack()} or * {@link Message#reply(Object)} on each message to complete the processing of the message. * * @param name The consumer name. * @param <T> The message type. * @return A new message consumer. * @throws NullPointerException if the consumer {@code name} is {@code null} */ default <T> MessageConsumer<T> consumer(String name) { return consumer(name, null); } /** * Creates a new named message consumer. * <p> * The returned consumer will consume messages sent to the service using a producer of the same name. * When a message is received by the member that owns this service, a single {@link MessageConsumer} * instance for the message will be called. If multiple consumers were created for the same queue on * the same {@link MessageService} instance, consumers will be called using a round-robin pattern. * <pre> * {@code * LocalMember localMember = group.join("foo").join(); * MessageConsumer<String> consumer = localMember.messaging().consumer("bar"); * consumer.onMessage(message -> { * message.ack(); * }); * } * </pre> * Messages can be handled by consumers in several ways. The message service can be used to receive * and acknowledge tasks or to receive messages for which the producer is awaiting a reply. The behavior * expected of a consumer is dependent on the producer configuration. For example, if the producer expects * a reply then consumers should reply. Consumers must always call either {@link Message#ack()} or * {@link Message#reply(Object)} on each message to complete the processing of the message. * * @param name The consumer name. * @param options The consumer options. * @param <T> The message type. * @return A new message consumer. * @throws NullPointerException if the consumer {@code name} is {@code null} */ <T> MessageConsumer<T> consumer(String name, MessageConsumer.Options options); }