Interface StreamReplicator

All Superinterfaces:
AutoCloseable, Closeable, Replicator

public interface StreamReplicator extends Replicator
Low-level replication interface, which receives messages in a non-delineated stream. Applications using this interface are responsible for encoding messages such that they can be properly separated. Consider an application which writes these two messages (inside the quotes): ["hello", "world"]. The messages might be read back as ["hello", "world"], ["helloworld"], ["he", "llowor", "ld"], etc.

For ensuring that messages aren't torn in the middle when a new leader is elected, messages must be written into the replicator with properly defined boundaries. When writing ["hello", "world"], a leader election can cause the second message to be dropped, and then only ["hello"] is read. If ["helloworld"] was written, no tearing of the two words can occur. They might both be read or both be dropped, atomically.

StreamReplicators require that a control message acceptor be installed for supporting group membership changes. Consider using MessageReplicator instead, although it has slightly higher overhead. In order for control messages to be processed, replicas must be actively reading and calling controlMessageReceived as necessary.

See Also:
  • Method Details

    • open

      static StreamReplicator open(ReplicatorConfig config) throws IOException
      Open a StreamReplicator instance, creating it if necessary. Be sure to call the start method too.
      Throws:
      IllegalArgumentException - if misconfigured
      IOException
    • newReader

      StreamReplicator.Reader newReader(long position, boolean follow)
      Returns a new reader which accesses data starting from the given position. The reader returns EOF whenever the end of a term is reached. At the end of a term, try to obtain a new writer to determine if the local member has become the leader.

      When passing true for the follow parameter, a reader is always provided at the requested position. When passing false for the follow parameter, null is returned if the current member is the leader for the given position.

      Note: Reader instances are not expected to be thread-safe.

      Specified by:
      newReader in interface Replicator
      Parameters:
      position - position to start reading from, known to have been committed
      follow - pass true to obtain an active reader, even if local member is the leader
      Returns:
      reader or possibly null when follow is false
      Throws:
      InvalidReadException - if position is lower than the start position
    • newWriter

      Returns a new writer for the leader to write into, or else returns null if the local member isn't the leader. The writer stops accepting messages when the term has ended, and possibly another leader has been elected.

      Note: Writer instances are not expected to be thread-safe.

      Specified by:
      newWriter in interface Replicator
      Returns:
      writer or null if not the leader
      Throws:
      IllegalStateException - if an existing writer for the current term already exists
    • newWriter

      StreamReplicator.Writer newWriter(long position)
      Returns a new writer for the leader to write into, or else returns null if the local member isn't the leader. The writer stops accepting messages when the term has ended, and possibly another leader has been elected.

      Note: Writer instances are not expected to be thread-safe.

      Specified by:
      newWriter in interface Replicator
      Parameters:
      position - expected position to start writing from as leader; method returns null if the given position is lower
      Returns:
      writer or null if not the leader
      Throws:
      IllegalStateException - if an existing writer for the current term already exists
    • controlMessageReceived

      void controlMessageReceived(long position, byte[] message) throws IOException
      Called to pass along a control message, which was originally provided through an acceptor. Control messages must be passed along in the original order in which they were created. A control message cannot be treated as applied until after this method returns.
      Parameters:
      position - log position just after the message
      Throws:
      IOException
    • controlMessageAcceptor

      void controlMessageAcceptor(Consumer<byte[]> acceptor)
      Install a callback to be invoked when the replicator needs to send control messages, which must propagate through the replication log. From the perspective of the acceptor, control messages should be treated as opaque. Control messages are primarily used for supporting group membership changes, and without an acceptor, members cannot be added or removed.

      Acceptor implementations are expected to wrap messages such that they can be propagated along with regular messages, and then later be passed to the controlMessageReceived method. If a control message cannot be written (possibly because the local member isn't the leader), it might be silently dropped. Implementations are not required to pass control messages to a remote leader.

      Parameters:
      acceptor - acceptor to use, or pass null to disable