Skip to content

Latest commit

 

History

History
65 lines (52 loc) · 2.55 KB

README.md

File metadata and controls

65 lines (52 loc) · 2.55 KB

Bucket4k

build GitHub license Maven Central

A Kotlin wrapper around Bucket4j which suspends and plays nicely with coroutines.

See the changelog.

Features

  • Not another token bucket implementation: Uses Bucket4k's tried and true token bucket implementation.
  • No locks: Wraps Bucket4j's LockFreeBucket.
  • Suspendable functions: None of the included functionality blocks the calling thread, instead suspending coroutine execution while waiting for available tokens. No locks means no blocked threads waiting for said locks.

Using Bucket4k

Add Bucket4k as a project dependency:

build.gradle.kts:

dependencies {
    implementation("com.sletmoe.bucket4k:bucket4k:<version>")
}

Create a SuspendingBucket, configuring token limits as desired:

val tokenBucket = SuspendingBucket.build {
    addLimit(Bandwidth.simple(5, 1.seconds.toJavaDuration()))
    addLimit(Bandwidth.simple(30, 1.minutes.toJavaDuration()))
}

We can then use the token bucket. For example, to limit transactions per second on an API operation within a Ktor web application:

fun Route.widgetRouting() {
    route("/widget") {
        get {
            if (tokenBucket.tryConsume(1)) {
                call.respond(listWidgets())
            } else {
                call.respondText("Too many requests! Slow your roll.", status = HttpStatusCode.TooManyRequests)
            }
        }
    }
}

Or we could use it to rate-limit asynchronous calls to some API:

val webPagesToGet = listOf("https://my.web.page/foo", ...)

val results = webPagesToGet.map { webPageUri ->
    async(Dispatchers.IO) { 
        tokenBucket.consume(1)
        httpClient.get(webPageUri)
    }
}.map { it.await() }

Read the API documentation for more information.