Skip to content

Commit

Permalink
Add documentation for the transport layer.
Browse files Browse the repository at this point in the history
  • Loading branch information
kuujo committed Jul 20, 2015
1 parent 3666b56 commit e46f15b
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 14 deletions.
18 changes: 17 additions & 1 deletion transport/src/main/java/net/kuujo/copycat/transport/Client.java
Expand Up @@ -21,20 +21,33 @@


/** /**
* Transport client. * Transport client.
* <p>
* This is a low-level abstraction through which Copycat clients connect to {@link net.kuujo.copycat.transport.Server servers}.
* Users should never use this API directly.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public interface Client { public interface Client {


/** /**
* Returns the client ID. * Returns the client ID.
* <p>
* The client ID is a globally unique {@link java.util.UUID} that identifies connections between this
* {@link net.kuujo.copycat.transport.Client} and a remote {@link net.kuujo.copycat.transport.Server}.
* <p>
* When a client connects to a server, the client will establish the connection by sending the server its ID. This allows
* the server to identify connected clients via {@link net.kuujo.copycat.transport.Connection#id()}.
* *
* @return The client ID. * @return The client ID.
*/ */
UUID id(); UUID id();


/** /**
* Connects the client. * Connects the client to the given address.
* <p>
* Once the client connects to the given address, the {@link net.kuujo.copycat.transport.Connection} will be established
* by sharing the client's {@link #id()} with the server and the returned {@link java.util.concurrent.CompletableFuture future}
* will be completed. The resulting {@link Connection#id()} will equal the client {@link #id()}.
* *
* @param address The address to which to connect. * @param address The address to which to connect.
* @return A completable future to be completed once the client has been connected. * @return A completable future to be completed once the client has been connected.
Expand All @@ -43,6 +56,9 @@ public interface Client {


/** /**
* Closes the client. * Closes the client.
* <p>
* Before the client is closed, all {@link net.kuujo.copycat.transport.Connection}s opened by the client will be closed
* and any registered {@link Connection#closeListener(net.kuujo.copycat.Listener)}s will be invoked.
* *
* @return A completable future to be called once the client is closed. * @return A completable future to be called once the client is closed.
*/ */
Expand Down
70 changes: 59 additions & 11 deletions transport/src/main/java/net/kuujo/copycat/transport/Connection.java
Expand Up @@ -22,41 +22,79 @@
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;


/** /**
* Client/server connection. * Transport connection.
* <p>
* This is a low-level abstraction through which clients and servers communicate with one another once connected.
* This is more or less a lightweight interface over sockets that supports arbitrary messages.
* <p>
* Messages sent over a connection must be serializable by the registered {@link net.kuujo.alleycat.Alleycat} serializer.
* This means that messages must implement {@link java.io.Serializable}, {@link java.io.Externalizable}, or
* {@link net.kuujo.alleycat.AlleycatSerializable} or provide a custom {@link net.kuujo.alleycat.Serializer}.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public interface Connection { public interface Connection {


/** /**
* Returns the connection ID. * Returns the connection ID.
* <p>
* The connection ID is inherited from the {@link net.kuujo.copycat.transport.Client} that is connected. When the connection
* is created, the client will send its {@link net.kuujo.copycat.transport.Client#id()} to the {@link net.kuujo.copycat.transport.Server}
* and the connection ID will reflect the client's ID on both the client and server side.
* *
* @return The connection ID. * @return The connection ID.
*/ */
UUID id(); UUID id();


/** /**
* Sends a request. * Sends a message to the other side of the connection.
* <p>
* The message must be serializable via the configured {@link net.kuujo.alleycat.Alleycat} instance. This means it
* must implement {@link java.io.Serializable}, {@link java.io.Externalizable}, or {@link net.kuujo.alleycat.AlleycatSerializable}
* or provide a custom {@link net.kuujo.alleycat.Serializer}.
* <p>
* Note that {@link net.kuujo.copycat.transport.Connection}s are bi-directional. That is, messages can be send either
* by the client or the server. All messages must have a reply, even if the reply is {@code null}. Once the reply
* has been received from the other side of the connection, the returned {@link java.util.concurrent.CompletableFuture}
* will be completed.
* <p>
* {@link net.kuujo.copycat.transport.Connection} implementations must guarantee that all reply
* {@link java.util.concurrent.CompletableFuture futures} will be completed in the same
* {@link net.kuujo.copycat.util.concurrent.CopycatThread Copycat thread}.
* *
* @param request The request to send. * @param message The message to send.
* @param <T> The request type. * @param <T> The message type.
* @param <U> The response type. * @param <U> The reply type.
* @return A completable future to be completed with the response. * @return A completable future to be completed with the response.
*/ */
<T, U> CompletableFuture<U> send(T request); <T, U> CompletableFuture<U> send(T message);


/** /**
* Sets a request handler on the connection. * Sets a message handler on the connection.
* <p>
* The message handler will be invoked each time a message of the given type is received from the other side of the
* connection. All messages are classified by type, and only one {@link net.kuujo.copycat.transport.MessageHandler} may
* be registered on the connection for any given type.
* <p>
* The message handler must return a {@link java.util.concurrent.CompletableFuture} to be completed with the message
* reply. The reply value must be serializable via the configured {@link net.kuujo.alleycat.Alleycat} instance. This means it
* must implement {@link java.io.Serializable}, {@link java.io.Externalizable}, or {@link net.kuujo.alleycat.AlleycatSerializable}
* or provide a custom {@link net.kuujo.alleycat.Serializer}.
* *
* @param type The request type for which to listen. * @param type The message type for which to listen. This can be any class that is serializable by the configured
* @param handler The request handler. * {@link net.kuujo.alleycat.Alleycat} instance.
* @param <T> The request type. * @param handler The type-specific message handler.
* @param <U> The response type. * @param <T> The message type.
* @param <U> The reply type.
*/ */
<T, U> Connection handler(Class<T> type, MessageHandler<T, U> handler); <T, U> Connection handler(Class<T> type, MessageHandler<T, U> handler);


/** /**
* Sets an exception listener on the connection. * Sets an exception listener on the connection.
* <p>
* In the event of an exception in the connection, the provided listener's {@link Listener#accept(Object)} method will
* be invoked. To unregister the listener, simply {@link net.kuujo.copycat.ListenerContext#close()} the returned
* {@link net.kuujo.copycat.ListenerContext}.
* *
* @param listener The exception listener. * @param listener The exception listener.
* @return The connection. * @return The connection.
Expand All @@ -65,6 +103,10 @@ public interface Connection {


/** /**
* Sets a close listener on the connection. * Sets a close listener on the connection.
* <p>
* The provided listener's {@link Listener#accept(Object)} method will be invoked when the connection is closed. Note
* that a close event can be triggered via {@link net.kuujo.copycat.transport.Connection#close()} or by the
* {@link net.kuujo.copycat.transport.Client} or {@link net.kuujo.copycat.transport.Server} that created the connection.
* *
* @param listener The close listener. * @param listener The close listener.
* @return The connection. * @return The connection.
Expand All @@ -73,6 +115,12 @@ public interface Connection {


/** /**
* Closes the connection. * Closes the connection.
* <p>
* Once the connection is closed, no more messages can be {@link Connection#send(Object) sent} or
* {@link Connection#handler(Class, MessageHandler) received} by the connection. Any
* {@link Connection#closeListener(net.kuujo.copycat.Listener) close listeners} registered on the connection will be
* invoked, and the returned {@link java.util.concurrent.CompletableFuture} will be completed once the connection has
* been closed.
* *
* @return A completable future to be completed once the connection is closed. * @return A completable future to be completed once the connection is closed.
*/ */
Expand Down
Expand Up @@ -18,14 +18,31 @@
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;


/** /**
* Message handler. * Transport layer message handler.
* <p>
* This is a functional interface for handling messages on a {@link net.kuujo.copycat.transport.Connection} instance.
* Message handlers are {@link Connection#handler(Class, MessageHandler) registered} for specific types. When
* {@link MessageHandler#handle(Object)} is invoked by a {@link net.kuujo.copycat.transport.Connection}, the handler
* <em>must</em> return a valid {@link java.util.concurrent.CompletableFuture} to be completed with the message reply.
* <p>
* Note that input and output for the message handler must be serializable via the configured {@link net.kuujo.alleycat.Alleycat}
* instance. This means it must implement {@link java.io.Serializable}, {@link java.io.Externalizable}, or
* {@link net.kuujo.alleycat.AlleycatSerializable} or provide a custom {@link net.kuujo.alleycat.Serializer}.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
@FunctionalInterface
public interface MessageHandler<T, U> { public interface MessageHandler<T, U> {


/** /**
* Handles a message. * Handles a message.
* <p>
* The handler must synchronously return a {@link java.util.concurrent.CompletableFuture} to be completed with the
* message response. If the message is handled synchronously, return {@link CompletableFuture#completedFuture(Object)}
* to immediately complete the returned future. Otherwise, create a {@link java.util.concurrent.CompletableFuture}
* and call {@link java.util.concurrent.CompletableFuture#complete(Object)} or
* {@link java.util.concurrent.CompletableFuture#completeExceptionally(Throwable)} to complete the future with a reply
* or error respectively.
* *
* @param message The message to handle. * @param message The message to handle.
* @return A completable future to be completed with the message response. * @return A completable future to be completed with the message response.
Expand Down
17 changes: 17 additions & 0 deletions transport/src/main/java/net/kuujo/copycat/transport/Server.java
Expand Up @@ -23,20 +23,34 @@


/** /**
* Transport server. * Transport server.
* <p>
* This is a low-level abstraction through which Copycat servers receive connections from clients. Users should never use
* this API directly.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public interface Server { public interface Server {


/** /**
* Returns the server ID. * Returns the server ID.
* <p>
* The server ID is a globally unique {@link java.util.UUID} through which the server can be identified.
* *
* @return The server ID. * @return The server ID.
*/ */
UUID id(); UUID id();


/** /**
* Listens for connections on the server. * Listens for connections on the server.
* <p>
* Once the server has started listening on the provided {@code address}, {@link Listener#accept(Object)} will be
* called for the provided {@link net.kuujo.copycat.Listener} each time a new connection to the server is established.
* The provided connection's {@link net.kuujo.copycat.transport.Connection#id()} will reflect the
* {@link net.kuujo.copycat.transport.Client#id()} of the client that connected to the server and not the
* {@link net.kuujo.copycat.transport.Server#id()} of the server itself.
* <p>
* Once the server has bound to the provided {@link java.net.InetSocketAddress address} the returned
* {@link java.util.concurrent.CompletableFuture} will be completed.
* *
* @param address The address on which to listen for connections. * @param address The address on which to listen for connections.
* @return A completable future to be called once the server has started listening for connections. * @return A completable future to be called once the server has started listening for connections.
Expand All @@ -45,6 +59,9 @@ public interface Server {


/** /**
* Closes the server. * Closes the server.
* <p>
* When the server is closed, any {@link Connection#closeListener(net.kuujo.copycat.Listener) close listeners} registered
* on the server's {@link net.kuujo.copycat.transport.Connection}s will be invoked prior to shutdown.
* *
* @return A completable future to be completed once the server is closed. * @return A completable future to be completed once the server is closed.
*/ */
Expand Down
Expand Up @@ -19,14 +19,29 @@
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;


/** /**
* Transport. * Transport provider.
* <p>
* This is a low level abstraction that serves to provide Copycat clients and servers with {@link net.kuujo.copycat.transport.Client}
* and {@link net.kuujo.copycat.transport.Server} instances. Throughout the lifetime of a {@code Transport}, Copycat may
* call on the transport to create multiple {@link net.kuujo.copycat.transport.Client} and {@link net.kuujo.copycat.transport.Server}
* objects. Each {@code Client} and {@code Server} is identified by a {@link java.util.UUID} which is assumed to be unique
* to that instance across the entire Copycat cluster.
* <p>
* When the {@link net.kuujo.copycat.transport.Transport} is closed, it should close all {@link net.kuujo.copycat.transport.Client}
* and {@link net.kuujo.copycat.transport.Server} instances created by it if they're not already closed.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public interface Transport { public interface Transport {


/** /**
* Creates a transport client. * Creates a transport client.
* <p>
* The provided {@link java.util.UUID} is a cluster-wide unique identifier for the client. The {@link Connection#id()}
* for all {@link net.kuujo.copycat.transport.Connection} objects created by the client should reflect the provided
* {@code id}. Additionally, {@link net.kuujo.copycat.transport.Connection} objects created by any
* {@link net.kuujo.copycat.transport.Server} to which the provided client connects should have the same
* {@link net.kuujo.copycat.transport.Connection#id()} .
* *
* @param id The client ID. * @param id The client ID.
* @return The transport client. * @return The transport client.
Expand All @@ -35,6 +50,11 @@ public interface Transport {


/** /**
* Creates a transport server. * Creates a transport server.
* <p>
* The provided {@link java.util.UUID} is a cluster-wide unique identifier for the client. However, note that
* {@link net.kuujo.copycat.transport.Connection} objects created by the provided {@link net.kuujo.copycat.transport.Server}
* should be created with the {@link Connection#id()} of the connecting {@link net.kuujo.copycat.transport.Client} and
* not the provided {@link net.kuujo.copycat.transport.Server} itself.
* *
* @param id The server ID. * @param id The server ID.
* @return The transport server. * @return The transport server.
Expand All @@ -43,6 +63,9 @@ public interface Transport {


/** /**
* Closes the transport. * Closes the transport.
* <p>
* When the transport is closed, all {@link net.kuujo.copycat.transport.Client} and {@link net.kuujo.copycat.transport.Server}
* objects provided by the {@link net.kuujo.copycat.transport.Transport} should be closed if not closed already.
* *
* @return A completable future to be completed once the transport is closed. * @return A completable future to be completed once the transport is closed.
*/ */
Expand Down
@@ -0,0 +1,26 @@
/*
* Copyright 2015 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.
*/

/**
* The Transport layer provides a low-level interface via which Copycat clients and servers communicate.
* <p>
* A {@link net.kuujo.copycat.transport.Transport} is a simple provider for {@link net.kuujo.copycat.transport.Client}
* and {@link net.kuujo.copycat.transport.Server} objects. The {@link net.kuujo.copycat.transport.Client} and
* {@link net.kuujo.copycat.transport.Server} are the interfaces through which clients and servers communicate respectively.
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
package net.kuujo.copycat.transport;

0 comments on commit e46f15b

Please sign in to comment.