Class DefaultAsyncBucketProxy

    • Method Detail

      • toListenable

        public AsyncBucketProxy toListenable​(BucketListener listener)
        Description copied from interface: AsyncBucketProxy
        Returns new copy of this bucket instance decorated by listener. The created bucket will share same tokens with source bucket and vice versa. See javadocs for BucketListener in order to understand semantic of listener.
        Specified by:
        toListenable in interface AsyncBucketProxy
        Parameters:
        listener - the listener of bucket events.
        Returns:
        new bucket instance decorated by listener
      • asScheduler

        public SchedulingBucket asScheduler()
        Description copied from interface: AsyncBucketProxy
        Returns asynchronous view of this bucket that allows to use bucket as async scheduler.
        Specified by:
        asScheduler in interface AsyncBucketProxy
        Returns:
        Asynchronous view of this bucket that allows to use bucket as async scheduler.
      • tryConsume

        public CompletableFuture<Boolean> tryConsume​(long tokensToConsume)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.tryConsume(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.tryConsume(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        tryConsume in interface AsyncBucketProxy
        Parameters:
        tokensToConsume - The number of tokens to consume from the bucket, must be a positive number.
        Returns:
        the future which eventually will be completed by true if the numTokens were consumed and completed by false otherwise.
        See Also:
        Bucket.tryConsume(long)
      • tryConsumeAndReturnRemaining

        public CompletableFuture<ConsumptionProbe> tryConsumeAndReturnRemaining​(long tokensToConsume)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.tryConsumeAndReturnRemaining(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.tryConsumeAndReturnRemaining(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        tryConsumeAndReturnRemaining in interface AsyncBucketProxy
        Parameters:
        tokensToConsume - The number of tokens to consume from the bucket, must be a positive number.
        Returns:
        the future which eventually will be completed by probe which describes both result of consumption and tokens remaining in the bucket after consumption.
        See Also:
        Bucket.tryConsumeAndReturnRemaining(long)
      • estimateAbilityToConsume

        public CompletableFuture<EstimationProbe> estimateAbilityToConsume​(long numTokens)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.estimateAbilityToConsume(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.estimateAbilityToConsume(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        estimateAbilityToConsume in interface AsyncBucketProxy
        Parameters:
        numTokens - The number of tokens to consume from the bucket, must be a positive number.
        Returns:
        the future which eventually will be completed by probe which describes the ability to consume specified amount of tokens.
        See Also:
        Bucket.estimateAbilityToConsume(long)
      • tryConsumeAsMuchAsPossible

        public CompletableFuture<Long> tryConsumeAsMuchAsPossible()
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.tryConsumeAsMuchAsPossible(), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.tryConsumeAsMuchAsPossible()
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        tryConsumeAsMuchAsPossible in interface AsyncBucketProxy
        Returns:
        the future which eventually will be completed by number of tokens which has been consumed, or completed by zero if was consumed nothing.
        See Also:
        Bucket.tryConsumeAsMuchAsPossible()
      • tryConsumeAsMuchAsPossible

        public CompletableFuture<Long> tryConsumeAsMuchAsPossible​(long limit)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.tryConsumeAsMuchAsPossible(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.tryConsumeAsMuchAsPossible(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        tryConsumeAsMuchAsPossible in interface AsyncBucketProxy
        Parameters:
        limit - maximum number of tokens to consume, should be positive.
        Returns:
        the future which eventually will be completed by number of tokens which has been consumed, or completed by zero if was consumed nothing.
        See Also:
        Bucket.tryConsumeAsMuchAsPossible(long)
      • tryConsume

        public CompletableFuture<Boolean> tryConsume​(long tokensToConsume,
                                                     long maxWaitTimeNanos,
                                                     ScheduledExecutorService scheduler)
        Description copied from interface: SchedulingBucket
        Tries to consume the specified number of tokens from the bucket.

        The algorithm for all type of buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket(for local bucket it is just a synchronous call) in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        • When back-end provides signal(through callback) that request is done(for local bucket response got immediately), then following post-processing rules will be applied:
          • If tokens were consumed then future immediately completed by true.
          • If tokens were not consumed because were not enough tokens in the bucket and maxWaitNanos nanoseconds is not enough time to refill deficit, then future immediately completed by false.
          • If tokens were reserved(effectively consumed) then task to delayed completion will be scheduled to the scheduler via ScheduledExecutorService.schedule(Runnable, long, TimeUnit), when delay equals to time required to refill the deficit of tokens. After scheduler executes task the future completed by true.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).
        Specified by:
        tryConsume in interface SchedulingBucket
        Parameters:
        tokensToConsume - The number of tokens to consume from the bucket.
        maxWaitTimeNanos - limit of time(in nanoseconds) which thread can wait.
        scheduler - used to delayed future completion
      • consume

        public CompletableFuture<Void> consume​(long tokensToConsume,
                                               ScheduledExecutorService scheduler)
        Description copied from interface: SchedulingBucket
        Consumes the specified number of tokens from the bucket.

        The algorithm for all type of buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket(for local bucket it is just a synchronous call) in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        • When back-end provides signal(through callback) that request is done(for local bucket response got immediately), then following post-processing rules will be applied:
          • If tokens were consumed then future immediately completed.
          • Else tokens reserved(effectively consumed) and task to delayed completion will be scheduled to the scheduler via ScheduledExecutorService.schedule(Runnable, long, TimeUnit), when delay equals to time required to refill the deficit of tokens. After scheduler executes task the future completed.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).
        Specified by:
        consume in interface SchedulingBucket
        Parameters:
        tokensToConsume - The number of tokens to consume from the bucket.
        scheduler - used to delayed future completion
      • addTokens

        public CompletableFuture<Void> addTokens​(long tokensToAdd)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.addTokens(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.addTokens(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        addTokens in interface AsyncBucketProxy
        Parameters:
        tokensToAdd - number of tokens to add
        Returns:
        the future which eventually will be completed by null if operation successfully completed without exception, otherwise(if any exception happen in asynchronous flow) the future will be completed exceptionally.
        See Also:
        Bucket.addTokens(long)
      • forceAddTokens

        public CompletableFuture<Void> forceAddTokens​(long tokensToAdd)
        Description copied from interface: AsyncBucketProxy
        Asynchronous version of Bucket.forceAddTokens(long), follows the same semantic.

        The algorithm for distribute buckets is following:

        • Implementation issues asynchronous request to back-end behind the bucket in way which specific for each particular back-end.
        • Then uncompleted future returned to the caller.
        • When back-end provides signal(through callback) that request is done, then future completed.
        • If back-end provides signal(through callback) that asynchronous request failed, then future completed exceptionally.
        It is strongly not recommended to do any heavy work in thread which completes the future, because typically this will be a back-end thread which handles NIO selectors, blocking this thread will take negative performance effect to back-end throughput, so you always should resume control flow in another executor via methods like CompletableFuture.thenApplyAsync(Function, Executor).

        The algorithm for local buckets is following:

        • Implementation just redirects request to synchronous version Bucket.addTokens(long)
        • Then returns feature immediately completed by results from previous step. So using this method for local buckets is useless, because there are no differences with synchronous version.
        Specified by:
        forceAddTokens in interface AsyncBucketProxy
        Parameters:
        tokensToAdd - number of tokens to add
        Returns:
        the future which eventually will be completed by null if operation successfully completed without exception, otherwise(if any exception happen in asynchronous flow) the future will be completed exceptionally.
        See Also:
        Bucket.addTokens(long)
      • getAvailableTokens

        public CompletableFuture<Long> getAvailableTokens()
        Description copied from interface: AsyncBucketProxy
        Returns amount of available tokens in this bucket.

        This method designed to be used only for monitoring and testing, you should never use this method for business cases, because available tokens can be changed by concurrent transactions for case of multithreaded/multi-process environment.

        Specified by:
        getAvailableTokens in interface AsyncBucketProxy
        Returns:
        amount of available tokens
      • syncByCondition

        public CompletableFuture<Void> syncByCondition​(long unsynchronizedTokens,
                                                       Duration timeSinceLastSync)
        Description copied from interface: AsyncOptimizationController
        Initiates immediate synchronization of local copy of bucket with remote storage in case of both conditions bellow are true:
        • Accumulated amount of locally consumed tokens without external synchronization is greater than or equal to unsynchronizedTokens
        • Time passed since last synchronization with external storage is greater than or equal to timeSinceLastSync
        Specified by:
        syncByCondition in interface AsyncOptimizationController
        Parameters:
        unsynchronizedTokens - criterion for accumulated amount of unsynchronized tokens
        timeSinceLastSync - criterion for time passed since last synchronization
        Returns:
        future that will be completed when local copy of bucket will be synchronized with remote storage, or immediately completed future in case of this synchronization is not required.