Class FencingToken

java.lang.Object
io.krabka.streams.coordination.FencingToken
All Implemented Interfaces:
Comparable<FencingToken>

public final class FencingToken extends Object implements Comparable<FencingToken>
The quorum-minted proof that one member holds a role.

Kafka's transaction coordinator mints the pair when a member calls InitProducerId for the transactional.id of the role. The quorum picks the values, every broker enforces them, and a write from an older pair fails with a fenced error. A holder passes the token to every guarded write, and the broker checks it. No clock takes part in that check.

The token is a pair, and compareTo(FencingToken) reads the producer id first and the producer epoch second. The order is lexicographic. A producer epoch is a short and it wraps. Kafka handles the exhaustion with a fresh producer id and an epoch of zero. A comparison on the epoch alone ranks that fresh token below the stale one, and the old leader keeps the role after about 32000 leadership changes. Never compare the epoch on its own.

NO_EPOCH is the token of a role that no member has ever taken. It ranks below every minted token.

Example

FencingToken wrapped = FencingToken.of(4, Short.MAX_VALUE);
FencingToken fresh = FencingToken.of(5, (short) 0);
assertThat(fresh.supersedes(wrapped)).isTrue();
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final FencingToken
    The token of a role that no member has ever taken.
  • Method Summary

    Modifier and Type
    Method
    Description
    int
    Orders two tokens lexicographically.
    boolean
    equals(Object other)
    Reports whether another object is a token with the same pair.
    int
    Returns a hash of the pair.
    boolean
    Reports whether this token names a minted leadership.
    of(long producerId, short producerEpoch)
    Builds a token from a minted producer id and producer epoch.
    parse(String text)
    Parses the producer_id:producer_epoch form that toString() writes.
    short
    Returns the producer epoch the transaction coordinator minted.
    long
    Returns the producer id the transaction coordinator minted.
    boolean
    Reports whether this token ranks above another one.
    Returns the producer_id:producer_epoch form.

    Methods inherited from class Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Field Details

    • NO_EPOCH

      public static final FencingToken NO_EPOCH
      The token of a role that no member has ever taken.

      Kafka writes -1 for "no producer", and that pair proves no leadership. of(long, short) rejects a negative value, so no minted token can equal this one and every minted token supersedes it.

  • Method Details

    • of

      public static FencingToken of(long producerId, short producerEpoch)
      Builds a token from a minted producer id and producer epoch.
      Parameters:
      producerId - the producer id the transaction coordinator minted
      producerEpoch - the producer epoch the transaction coordinator minted
      Returns:
      the fencing token of the pair
      Throws:
      CoordinationException - if either value is negative
    • parse

      public static FencingToken parse(String text)
      Parses the producer_id:producer_epoch form that toString() writes.
      Parameters:
      text - the two decimal numbers, separated by one colon
      Returns:
      the fencing token the text names
      Throws:
      CoordinationException - if the text does not carry that form, or if either number is negative or out of range
    • producerId

      public long producerId()
      Returns the producer id the transaction coordinator minted.
      Returns:
      the producer id, or -1 for NO_EPOCH
    • producerEpoch

      public short producerEpoch()
      Returns the producer epoch the transaction coordinator minted.
      Returns:
      the producer epoch, or -1 for NO_EPOCH
    • minted

      public boolean minted()
      Reports whether this token names a minted leadership.
      Returns:
      true for every token but NO_EPOCH
    • compareTo

      public int compareTo(FencingToken other)
      Orders two tokens lexicographically.

      The comparison reads the producer id first, and it reads the producer epoch only for two tokens of one producer id. Kafka allocates producer ids from a monotonic block allocator and resets the epoch to zero at every new id, so the pair stays monotonic where the epoch alone does not.

      Specified by:
      compareTo in interface Comparable<FencingToken>
      Parameters:
      other - the token to compare against
      Returns:
      a negative number when this token ranks below the other one, zero for two equal tokens, and a positive number when this token supersedes the other one
    • supersedes

      public boolean supersedes(FencingToken other)
      Reports whether this token ranks above another one.
      Parameters:
      other - the token to compare against
      Returns:
      true when this token supersedes the other one
    • equals

      public boolean equals(Object other)
      Reports whether another object is a token with the same pair.
      Overrides:
      equals in class Object
      Parameters:
      other - the object to compare against
      Returns:
      true when the other object is a token of this producer id and epoch
    • hashCode

      public int hashCode()
      Returns a hash of the pair.
      Overrides:
      hashCode in class Object
      Returns:
      the hash code of the producer id and the producer epoch
    • toString

      public String toString()
      Returns the producer_id:producer_epoch form.
      Overrides:
      toString in class Object
      Returns:
      the two decimal numbers, separated by one colon