OpisDescription
Moduł RateLimit kontroluje częstotliwość wykonywania akcji w aplikacji. Obsługuje różne strategie limitowania (sliding window, token bucket) i integruje sięThe RateLimit module controls action execution frequency in the app. Supports various rate limiting strategies (sliding window, token bucket) and integrates z Timer.cooldown oraz SecureStorage dla persystencji.
Podstawowe użycieBasic Usage
// Sprawdź i wykonaj
if (ADict.RateLimit.tryAcquire("api_call")) {
makeApiCall()
} else {
showRateLimitedMessage()
}
// Z automatyczną akcją
ADict.RateLimit.tryAcquire("share_button", cooldownMs = 5000L) {
shareContent()
}
// Z fallbackiem
val result = ADict.RateLimit.withLimit("search", fallback = emptyList()) {
api.search(query)
}
KonfiguracjaConfiguration limitów
// Sliding window - 60 req/min
ADict.RateLimit.configure("api_call") {
maxRequests = 60
windowMinutes(1)
strategy = Strategy.SLIDING_WINDOW
}
// Token bucket - burst + sustained rate
ADict.RateLimit.configure("ad_request") {
maxRequests = 10
windowMs = 60_000L
strategy = Strategy.TOKEN_BUCKET
burstSize = 3
refillRatePerSecond = 0.5
}
// Z blokowaniem po przekroczeniu
ADict.RateLimit.configure("login_attempt") {
maxRequests = 5
windowMinutes(15)
blockDurationMs = 30_000L // Zablokuj na 30s
}
StrategieStrategies
| Strategia | OpisDescription | UżycieUsage |
|---|---|---|
FIXED_WINDOW |
Stałe okno czasoweFixed time window | Proste limity, np. 100/godz |
SLIDING_WINDOW |
Przesuwne okno (domyślna)Sliding window (default) | Płynne limity bez spike'ówSmooth limits without spikes |
TOKEN_BUCKET |
Burst + sustained rate | API z burstami, reklamyAPIs with bursts, ads |
LEAKY_BUCKET |
Stały output rateConstant output rate | Równomierny przepływUniform flow |
PresetyPresets
// Użyj gotowych presetów
ADict.RateLimit.applyPreset(RateLimit.Presets.API_STANDARD) // 60/min
ADict.RateLimit.applyPreset(RateLimit.Presets.API_STRICT) // 10/min + block
ADict.RateLimit.applyPreset(RateLimit.Presets.BUTTON_ANTISPAM) // 5/10s
ADict.RateLimit.applyPreset(RateLimit.Presets.AD_REQUEST) // Token bucket
ADict.RateLimit.applyPreset(RateLimit.Presets.SHARE) // 10/5min
StatystykiStatistics
val stats = ADict.RateLimit.getStats("api_call")
println("Użyto: ${stats?.currentCount}/${stats?.maxRequests}")
println("Pozostało: ${stats?.remainingRequests}")
println("Reset za: ${stats?.resetInMs}ms")
println("Zablokowano: ${stats?.blockedCount} razy")
// Quick checks
val remaining = ADict.RateLimit.getRemaining("api_call")
val isLimited = ADict.RateLimit.isLimited("api_call")
val resetTime = ADict.RateLimit.getResetTime("api_call")
CallbackiCallbacks
ADict.RateLimit.onLimitReached { id, stats ->
analytics.log("rate_limited", mapOf(
"action" to id,
"blocked_count" to stats.blockedCount
))
if (id == "api_call") {
showApiLimitWarning()
}
}
Remote Config
// Dynamiczne limity z Remote Config
// Format w RC: "maxRequests,windowMs,strategy"
// np. "100,60000,SLIDING_WINDOW"
ADict.RateLimit.configureFromRemote(
id = "api_call",
remoteKey = "rate_limit_api",
defaultConfig = RateLimit.Presets.API_STANDARD
)
Reset
// Reset pojedynczego limitu
ADict.RateLimit.reset("api_call")
// Reset wszystkich
ADict.RateLimit.resetAll()
DebounceDebounce
Executes action only after delay with no new calls. Each new call resets the timer.Wykonuje akcję tylko po opóźnieniu bez nowych wywołań. Każde nowe wywołanie resetuje timer.
// In search field - wait for user to stop typing
searchField.addTextChangedListener { text ->
ADict.RateLimit.debounce("search", 300L) {
performSearch(text.toString())
}
}
// Cancel pending debounce
ADict.RateLimit.cancelDebounce("search")
ThrottleThrottle
Executes action at most once per interval. First call executes immediately.Wykonuje akcję co najwyżej raz na interwał. Pierwsze wywołanie wykonywane natychmiast.
// Button throttle - max once per second
button.setOnClickListener {
ADict.RateLimit.throttle("save_button", 1000L) {
saveData()
}
}
// Throttle with trailing edge - executes last call after interval
scrollView.setOnScrollChangeListener { _, _, _, _, _ ->
ADict.RateLimit.throttleTrailing("scroll_analytics", 500L) {
logScrollPosition()
}
}
// Reset throttle (allow immediate execution)
ADict.RateLimit.resetThrottle("save_button")
View ExtensionsRozszerzenia widoków
import rip.nerd.adictlibrary.modules.setOnClickDebounced
import rip.nerd.adictlibrary.modules.setOnClickThrottled
import rip.nerd.adictlibrary.modules.setOnClickRateLimited
// Debounced click - prevents double clicks
button.setOnClickDebounced(500L) {
navigateToNextScreen()
}
// Throttled click - max once per interval
likeButton.setOnClickThrottled(1000L) {
toggleLike()
}
// Rate limited click with callback
shareButton.setOnClickRateLimited(
limitId = "share_action",
maxClicks = 3,
windowMs = 10_000L,
onLimitReached = { showTooManySharesMessage() }
) {
shareContent()
}