java.lang.Object
io.camunda.zeebe.logstreams.impl.flowcontrol.FlowControl
All Implemented Interfaces:
LogStorage.AppendListener

public final class FlowControl extends Object implements LogStorage.AppendListener
Maintains a view of in-flight entries as they are being appended, written, committed and finally processed.

If enabled, a write rate limiter is used to limit the rate of appends to the log storage. Additionally, a request limiter is used to limit the amount of unprocessed user commands to ensure fast response times.

Thread safety

Access patterns:
  1. Calls to tryAcquire(WriteContext, List) from the sequencer, serialized through the sequencers write lock.
  2. Calls to onAppend(InFlightEntry, long) from the sequencer, serialized through the sequencers write lock.
  3. Calls to onWrite(long, long) from the log storage, serialized through the single raft thread.
  4. Calls to onCommit(long, long) from the log storage, serialized through the single raft thread.
  5. Calls to onProcessed(long) from the stream processor, serialized through the stream processor actor.
The order in which these methods are called is weakly constrained: The weak ordering forces us to program quite defensively and carefully choose where and how we modify internal state.

The inFlight map is only modified in the onAppend(InFlightEntry, long) method. All other methods only read from it.

A volatile field lastProcessedPosition is only modified in onProcessed(long) and used in onAppend(InFlightEntry, long) to clean up old entries.

The RateMeasurement#observe method only returns true when a new observation value is available. This way we prevent updating the metrics too often with repeated values. We use the RateMeasurements to update the cluster load and the exporting rate metrics.

  • Constructor Details

  • Method Details

    • tryAcquire

      public Either<FlowControl.Rejection,InFlightEntry> tryAcquire(WriteContext context, List<LogAppendEntryMetadata> batchMetadata)
      Tries to acquire a free in-flight spot, applying backpressure as needed.
      Returns:
      An Optional containing a InFlightEntry if append was accepted, an empty Optional otherwise.
    • onAppend

      public void onAppend(InFlightEntry entry, long highestPosition)
    • onWrite

      public void onWrite(long index, long highestPosition)
      Description copied from interface: LogStorage.AppendListener
      Called when the entry has been successfully written to the local storage.
      Specified by:
      onWrite in interface LogStorage.AppendListener
      Parameters:
      index - the index of the written entry
    • onCommit

      public void onCommit(long index, long highestPosition)
      Description copied from interface: LogStorage.AppendListener
      Called when the entry has been successfully committed.
      Specified by:
      onCommit in interface LogStorage.AppendListener
      Parameters:
      index - the index of the committed entry
      highestPosition - the highest position (i.e. last position) of the records within the entry that was committed.
    • onProcessed

      public void onProcessed(long position)
    • onExported

      public void onExported(long position)
    • getRequestLimit

      public com.netflix.concurrency.limits.Limit getRequestLimit()
    • setRequestLimit

      public void setRequestLimit(com.netflix.concurrency.limits.Limit requestLimit)
    • getWriteRateLimit

      public RateLimit getWriteRateLimit()
    • setWriteRateLimit

      public void setWriteRateLimit(RateLimit writeRateLimit)