/* * 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.group.DistributedGroup; import java.util.concurrent.CompletableFuture; /** * Represents a reliable message received by a member to be processed and acknowledged. * <p> * Messages are {@link MessageProducer#send(Object) sent} by {@link DistributedGroup} users to any member of a group. * Messages are replicated and persisted within the Atomix cluster before being pushed to clients on a queue. Once a message * is received by a message listener, the message may be processed asynchronously and either {@link #ack() acknowledged} or * {@link #fail() failed} once processing is complete. * <pre> * {@code * DistributedGroup group = atomix.getGroup("message-group").get(); * group.join().thenAccept(member -> { * MessageConsumer<String> consumer = member.messaging().consumer("foo"); * consumer.onMessage(message -> { * processTask(message).thenRun(() -> { * message.ack(); * }); * }); * }); * } * </pre> * Consumers may also send replies to messages. To send a reply, use the {@link #reply(Object)} method. Note that * replies may or may not be received by producers depending on their configuration. Producers must specify support * for the {@link io.atomix.group.messaging.MessageProducer.Execution#REQUEST_REPLY REQUEST_REPLY} execution policy * to receive replies. * <pre> * {@code * consumer.onMessage(message -> { * message.reply("Hello world!"); * }); * } * </pre> * * @author <a href="http://github.com/kuujo>Jordan Halterman</a> */ public interface Message<T> { /** * Returns the message ID. * <p> * The message ID is guaranteed to be unique and monotonically increasing within a given message queue. Tasks received * across members are not associated with one another. * * @return The monotonically increasing message ID. */ long id(); /** * Returns the message value. * <p> * This is the value that was {@link MessageProducer#send(Object) submitted} by the sending process. * * @return The message value. */ T message(); /** * Replies to the message. * <p> * Replies are sent through the Atomix cluster as a write operation. Users can await the completion of the underlying * write operation through the returned {@link CompletableFuture}. * * @param message The reply message. * @return A completable future to be completed once the reply has been sent. */ CompletableFuture<Void> reply(Object message); /** * Acknowledges completion of the message. * <p> * Once a message is acknowledged, an ack will be sent back to the process that submitted the message. Acknowledging * completion of a message does not guarantee that the sender will learn of the acknowledgement. The acknowledgement * itself may fail to reach the cluster or the sender may crash before the acknowledgement can be received. * Acks serve only as positive acknowledgement, but the lack of an ack does not indicate failure. * * @return A completable future to be completed once the message has been acknowledged. */ CompletableFuture<Void> ack(); /** * Fails processing of the message. * <p> * Once a message is failed, a failure message will be sent back to the process that submitted the message for processing. * Failing a message does not guarantee that the sender will learn of the failure. The process that submitted the message * may itself fail. * * @return A completable future to be completed once the message has been failed. */ CompletableFuture<Void> fail(); }