All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.swirlds.common.utility.throttle.RateLimiter Maven / Gradle / Ivy

Go to download

Swirlds is a software platform designed to build fully-distributed applications that harness the power of the cloud without servers. Now you can develop applications with fairness in decision making, speed, trust and reliability, at a fraction of the cost of traditional server-based platforms.

There is a newer version: 0.56.6
Show newest version
/*
 * Copyright (C) 2022-2024 Hedera Hashgraph, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.swirlds.common.utility.throttle;

import static com.swirlds.base.units.UnitConstants.SECONDS_TO_NANOSECONDS;
import static com.swirlds.common.utility.CompareTo.isGreaterThanOrEqualTo;

import com.swirlds.base.time.Time;
import java.time.Duration;
import java.time.Instant;

/**
 * 

* A simple utility designed to limit the frequency of an event, e.g. making sure a particular log message isn't written * too often. *

* *

* This object is not thread safe. This object was designed for simplicity and ease of use. This object may not be * suitable for code pathways with extremely high performance requirements. *

*/ public class RateLimiter { /** * The minimum amount of time that must pass before this operation may happen another time. */ private final Duration minimumPeriod; /** * The time when this rate limiter last allowed an operation to happen. */ private Instant lastOperation = Instant.EPOCH; /** * The number of requests that have been denied since the last successful operation. */ private long deniedRequests; /** * Provides a view of the current time. */ private final Time time; /** * Create a new rate limiter. * * @param time provides the current time * @param minimumPeriod the minimum time that must pass between operations */ public RateLimiter(final Time time, final Duration minimumPeriod) { this.time = time; this.minimumPeriod = minimumPeriod; } /** * Create a new rate limiter. * * @param time provides the current time * @param maxFrequency the maximum frequency of the operation, in hz */ public RateLimiter(final Time time, final double maxFrequency) { this(time, Duration.ofNanos((long) (1.0 / maxFrequency * SECONDS_TO_NANOSECONDS))); } /** * Request permission to trigger an operation, and immediately trigger if permitted. Returns true if it is ok to * perform the operation, returns false if * the operation has been performed too recently in the past. Once this * method returns true, it will return false for the remainder of the time span specified by the minimum period. * * @return true if the operation can be triggered without violating rate limits, otherwise false */ public boolean requestAndTrigger() { final Instant now = time.now(); final Duration elapsed = Duration.between(lastOperation, now); if (isGreaterThanOrEqualTo(elapsed, minimumPeriod)) { lastOperation = now; deniedRequests = 0; return true; } deniedRequests++; return false; } /** * Check if it is legal to trigger the rate limited action. Unlike {@link #requestAndTrigger()}, this method can * return true over and over in a time span smaller than the desired rate limit. In order to cause this method to * return false for the remainder of the time span specified by the rate limit, call {@link #trigger()}. * * @return true if it is currently legal to trigger the rate limited action */ public boolean request() { final Instant now = time.now(); final Duration elapsed = Duration.between(lastOperation, now); if (isGreaterThanOrEqualTo(elapsed, minimumPeriod)) { deniedRequests = 0; return true; } deniedRequests++; return false; } /** * Trigger the action that is being rate limited. Calling this method will cause {@link #request()} and * {@link #requestAndTrigger()} to return false for the remainder of the desired rate limit. This method * does not actually check if enough time has passed to permit the action being triggered. Calling this method * before the end of a rate limit period will reset the rate limit period. */ public void trigger() { deniedRequests = 0; lastOperation = time.now(); } /** * Get the number of times {@link #requestAndTrigger()} and/or {@link #request()} has returned false since the last * time one of these methods returned true. Immediately after {@link #requestAndTrigger()} or {@link #request()} * returns true, this method will return 0. * * @return the number of recently denied requests */ public long getDeniedRequests() { return deniedRequests; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy