java.lang.Object
io.helidon.common.concurrency.limits.ThroughputLimit
All Implemented Interfaces:
RuntimeType.Api<ThroughputLimitConfig>, Limit, LimitAlgorithm, SemaphoreLimit, NamedService, NamedService

public class ThroughputLimit extends Object implements RuntimeType.Api<ThroughputLimitConfig>
Throughput based limit, that is backed by a semaphore with timeout on the queue. The default behavior is non-queuing.
See Also:
  • Field Details

    • DEFAULT_AMOUNT

      public static final int DEFAULT_AMOUNT
      Default amount, meaning unlimited execution.
      See Also:
    • DEFAULT_DURATION

      public static final String DEFAULT_DURATION
      Default duration over which to count operations.
      See Also:
    • DEFAULT_QUEUE_LENGTH

      public static final int DEFAULT_QUEUE_LENGTH
      Default length of the queue.
      See Also:
    • DEFAULT_QUEUE_TIMEOUT_DURATION

      public static final String DEFAULT_QUEUE_TIMEOUT_DURATION
      Timeout of a request that is enqueued.
      See Also:
  • Method Details

    • builder

      public static ThroughputLimitConfig.Builder builder()
      Create a new fluent API builder to construct ThroughputLimit instance.
      Returns:
      fluent API builder
    • create

      public static ThroughputLimit create()
      Create a new instance with all defaults (no limit).
      Returns:
      a new limit instance
    • create

      public static ThroughputLimit create(Semaphore semaphore)
      Create an instance from the provided semaphore.
      Parameters:
      semaphore - semaphore to use
      Returns:
      a new throughput limit backed by the provided semaphore
    • create

      @Deprecated(since="4.4.0", forRemoval=true) public static ThroughputLimit create(Config config)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Create a new instance from configuration.
      Parameters:
      config - configuration of the throughput limit
      Returns:
      a new limit instance configured from config
    • create

      public static ThroughputLimit create(Config config)
      Create a new instance from configuration.
      Parameters:
      config - configuration of the throughput limit
      Returns:
      a new limit instance configured from config
    • create

      public static ThroughputLimit create(ThroughputLimitConfig config)
      Create a new instance from configuration.
      Parameters:
      config - configuration of the throughput limit
      Returns:
      a new limit instance configured from config
    • create

      public static ThroughputLimit create(Consumer<ThroughputLimitConfig.Builder> consumer)
      Create a new instance customizing its configuration.
      Parameters:
      consumer - consumer of configuration builder
      Returns:
      a new limit instance configured from the builder
    • prototype

      public ThroughputLimitConfig prototype()
      Description copied from interface: RuntimeType.Api
      The prototype as it was received when creating this runtime object instance.
      Specified by:
      prototype in interface RuntimeType.Api<ThroughputLimitConfig>
      Returns:
      prototype object used to create this instance
    • name

      public String name()
      Description copied from interface: NamedService
      Name of this implementation, as provided in ConfiguredProvider.create(io.helidon.common.config.Config, String).
      Specified by:
      name in interface NamedService
      Specified by:
      name in interface NamedService
      Returns:
      name of this service
    • type

      public String type()
      Description copied from interface: NamedService
      Type of this implementation, to distinguish instances of same type, with different NamedService.name(). Use for example ConfiguredProvider.configKey() to define the type.
      Specified by:
      type in interface NamedService
      Specified by:
      type in interface NamedService
      Returns:
      type of this service
    • copy

      public Limit copy()
      Description copied from interface: Limit
      Create a copy of this limit with the same configuration.
      Specified by:
      copy in interface Limit
      Returns:
      a copy of this limit
    • tryAcquireOutcome

      public LimitAlgorithm.Outcome tryAcquireOutcome(boolean wait)
      Description copied from interface: LimitAlgorithm
      Tries to acquire a token, waiting for available permits for the configured amount of time, if wait is enabled, returning immediately otherwise. Concrete implementations should invoke the provided outcomeConsumer.

      Note that custom implementations of this interface might not implement this method, in which case the caller's limit outcome consumer receives an "unknown" outcome. Clearly the algorithm made a decision, but does not expose it to callers.

      If acquired, the caller must call one of the LimitAlgorithm.Token operations to release the token. If the response is empty, the limit does not have an available token.

      Specified by:
      tryAcquireOutcome in interface LimitAlgorithm
      Parameters:
      wait - whether to wait in the queue (if one is configured/available in the limit), or to return immediately
      Returns:
      acquired token, or empty if there is no available token
    • call

      public <T> LimitAlgorithm.Result<T> call(Callable<T> callable) throws Exception
      Description copied from interface: LimitAlgorithm
      Invoke a callable within the limits of this limiter, invoking the provided Consumer with the LimitAlgorithm.Outcome resulting from applying the limit algorithm.

      Note that custom implementations of this interface might not implement this method, in which case the caller's limit outcome consumer receives an "unknown" outcome. Clearly the algorithm made a decision, but does not expose it to callers.

      Limit implementor's notes:

      • Make sure to catch IgnoreTaskException from the callable, and call its IgnoreTaskException.handle() to either return the provided result, or throw the exception after ignoring the timing for future decisions.
      • Make sure the limitOutcomeConsumer is non-null, and after determining the disposition of the item of work create a suitable LimitOutcome and pass it to the consumer. Also, make sure to use an outcome-aware token internally so when the caller invokes the token's methods the outcome is updated accordingly.
      Specified by:
      call in interface LimitAlgorithm
      Type Parameters:
      T - the callable return type
      Parameters:
      callable - callable to execute within the limit
      Returns:
      result of the callable with the outcome
      Throws:
      Exception - in case the task failed with an exception
    • run

      public LimitAlgorithm.Outcome run(Runnable runnable) throws Exception
      Description copied from interface: LimitAlgorithm
      Invoke a runnable within the limits of this limiter, invoking the provided Consumer with the LimitAlgorithm.Outcome resulting from applying the limit algorithm.

      Note that custom implementations of this interface might not implement this method, in which case the caller's limit outcome consumer receives an "unknown" outcome. Clearly the algorithm made a decision, but does not expose it to callers.

      Limit implementor's notes:

      • Make sure to catch IgnoreTaskException from the runnable, and call its IgnoreTaskException.handle() to either return the provided result, or throw the exception after ignoring the timing for future decisions.
      • Make sure the limitOutcomeConsumer is non-null, and after determining the disposition of the item of work create a suitable LimitOutcome and pass it to the consumer. Also, make sure to use an outcome-aware token internally so when the caller invokes the token's methods the outcome is updated accordingly.
      Specified by:
      run in interface LimitAlgorithm
      Parameters:
      runnable - runnable to execute within the limit
      Returns:
      Outcome from the limit algorithm
      Throws:
      Exception - in case the task failed with an exception
    • semaphore

      public Semaphore semaphore()
      Description copied from interface: SemaphoreLimit
      Underlying semaphore of this limit.
      Specified by:
      semaphore in interface SemaphoreLimit
      Returns:
      the semaphore instance
    • init

      public void init(String socketName)
      Description copied from interface: Limit
      Initialization method for this limit. This method can be used for any task, including metrics initialization.
      Specified by:
      init in interface Limit
      Parameters:
      socketName - socket name for this limit such as "@default"
    • updateMetrics

      protected void updateMetrics(long startTime, long endTime)
      Updates the round-trip time (RTT) metric with the elapsed time between the specified start and end times.

      The RTT is calculated as the difference between the end time and the start time. If the timer is not null, the RTT is recorded using the Timer.record(long, TimeUnit) method with the TimeUnit.NANOSECONDS unit.

      Parameters:
      startTime - the start time of the operation in nanoseconds
      endTime - the end time of the operation in nanoseconds
    • setHandler

      protected void setHandler(io.helidon.common.concurrency.limits.LimitHandlers.LimiterHandler handler)
      Sets the LimitHandlers.LimiterHandler instance to be used by this semaphore-based limit.

      The LimiterHandler is responsible for managing the underlying semaphore and providing a way to acquire tokens.

      Parameters:
      handler - the LimitHandlers.LimiterHandler instance to be used
    • getInitialPermits

      protected int getInitialPermits()
      Returns the initial number of permits set for this semaphore-based limit.

      The initial number of permits is used to initialize the underlying semaphore.

      Returns:
      the initial number of permits
    • setInitialPermits

      protected void setInitialPermits(int initialPermits)
      Sets the initial number of permits for this semaphore-based limit.

      The initial number of permits is used to initialize the underlying semaphore.

      Parameters:
      initialPermits - the initial number of permits to be set
    • getSemaphore

      protected Semaphore getSemaphore()
      Returns the underlying semaphore instance associated with this semaphore-based limit.

      Note that direct access to the semaphore may bypass the limit calculation and is not recommended. This method is provided for backward compatibility only and is deprecated for removal.

      Returns:
      the underlying semaphore instance
    • setSemaphore

      protected void setSemaphore(Semaphore semaphore)
      Sets the underlying semaphore instance associated with this semaphore-based limit.

      The semaphore is used to manage the concurrency limit. It is recommended to use the LimitHandlers.LimiterHandler instance to acquire tokens instead of directly accessing the semaphore.

      Parameters:
      semaphore - the semaphore instance to be set
    • getConcurrentRequests

      protected AtomicInteger getConcurrentRequests()
      Returns the AtomicInteger instance tracking the current number of concurrent requests.

      The returned AtomicInteger is used to maintain a count of the concurrent requests being processed.

      Returns:
      the AtomicInteger instance tracking concurrent requests
    • getClock

      protected Supplier<Long> getClock()
      Returns the clock supplier used by this semaphore-based limit.

      The clock supplier provides a way to obtain the current time in nanoseconds.

      Returns:
      the clock supplier
    • getName

      protected String getName()
      Returns the name associated with this semaphore-based limit.

      The name is used to identify the limit and is typically used for metrics and monitoring purposes.

      Returns:
      the name of this semaphore-based limit
    • getQueueLength

      protected int getQueueLength()
      Returns the current queue length associated with this semaphore-based limit.

      The queue length represents the maximum number of requests that can be queued while waiting for a permit to be available.

      Returns:
      the current queue length
    • setQueueLength

      protected void setQueueLength(int queueLength)
      Sets the maximum number of requests that can be queued while waiting for a permit to be available.

      The queue length determines the number of requests that can be buffered when the concurrency limit is reached. If the queue is full, subsequent requests will be rejected.

      Parameters:
      queueLength - the maximum number of requests to be queued
    • invoke

      public <T> T invoke(Callable<T> callable) throws Exception
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: LimitAlgorithm
      Invoke a callable within the limits of this limiter.

      Limit implementor's note: Make sure to catch IgnoreTaskException from the callable, and call its IgnoreTaskException.handle() to either return the provided result, or throw the exception after ignoring the timing for future decisions.

      Specified by:
      invoke in interface LimitAlgorithm
      Type Parameters:
      T - the callable return type
      Parameters:
      callable - callable to execute within the limit
      Returns:
      result of the callable
      Throws:
      Exception - in case the task failed with an exception
    • invoke

      public void invoke(Runnable runnable) throws Exception
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: LimitAlgorithm
      Invoke a runnable within the limits of this limiter.

      Limit implementor's note: Make sure to catch IgnoreTaskException from the runnable, and call its IgnoreTaskException.handle() to either return the provided result, or throw the exception after ignoring the timing for future decisions.

      Specified by:
      invoke in interface LimitAlgorithm
      Parameters:
      runnable - runnable to execute within the limit
      Throws:
      Exception - in case the task failed with an exception
    • tryAcquire

      public Optional<LimitAlgorithm.Token> tryAcquire()
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: LimitAlgorithm
      Try to acquire a token, waiting for available permits for the configured amount of time, if queuing is enabled.

      If acquired, the caller must call one of the LimitAlgorithm.Token operations to release the token. If the response is empty, the limit does not have an available token.

      Specified by:
      tryAcquire in interface LimitAlgorithm
      Returns:
      acquired token, or empty if there is no available token
    • tryAcquire

      public Optional<LimitAlgorithm.Token> tryAcquire(boolean wait)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: LimitAlgorithm
      Try to acquire a token, waiting for available permits for the configured amount of time, if wait is enabled, returning immediately otherwise.

      If acquired, the caller must call one of the LimitAlgorithm.Token operations to release the token. If the response is empty, the limit does not have an available token.

      Specified by:
      tryAcquire in interface LimitAlgorithm
      Parameters:
      wait - whether to wait in the queue (if one is configured/available in the limit), or to return immediately
      Returns:
      acquired token, or empty if there is no available token