{"id":15827321,"url":"https://github.com/pythonista7/doorman-kotlin-client","last_synced_at":"2025-08-31T15:23:42.132Z","repository":{"id":252611208,"uuid":"839523620","full_name":"Pythonista7/doorman-kotlin-client","owner":"Pythonista7","description":"A client for the distributed client side rate limiter \"doorman\"","archived":false,"fork":false,"pushed_at":"2024-08-31T18:03:17.000Z","size":192,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-12T10:14:18.047Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Pythonista7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-07T19:34:39.000Z","updated_at":"2024-08-31T18:03:20.000Z","dependencies_parsed_at":"2024-10-26T14:59:37.203Z","dependency_job_id":"874f86d5-71fc-42c4-87f6-b71530d050a6","html_url":"https://github.com/Pythonista7/doorman-kotlin-client","commit_stats":{"total_commits":24,"total_committers":1,"mean_commits":24.0,"dds":0.0,"last_synced_commit":"cfeb5ac77394d212f279b983d745cb1c72987d46"},"previous_names":["pythonista7/doorman-kotlin-client"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pythonista7%2Fdoorman-kotlin-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pythonista7%2Fdoorman-kotlin-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pythonista7%2Fdoorman-kotlin-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pythonista7%2Fdoorman-kotlin-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Pythonista7","download_url":"https://codeload.github.com/Pythonista7/doorman-kotlin-client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246627325,"owners_count":20808101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-05T10:03:59.216Z","updated_at":"2025-04-01T10:35:11.091Z","avatar_url":"https://github.com/Pythonista7.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kotlin Doorman Client\n\nThis is a Kotlin client for the [Doorman](https://github.com/Pythonista7/doorman) service which allows voluntary client-side rate limiting. The big idea can be captured in this image and this repo represents the `client` part of the implementation.\n\n![Doorman](https://github.com/Pythonista7/doorman/blob/master/doc/loadtest/overview.png)\n\nThis implementation is based on the [Go Client](https://github.com/Pythonista7/doorman/blob/master/go/client/doorman/client.go) from the Doorman project, hence the bugs/limitation of the Go client are also present in this implementation at the moment.\n\n\nCheck out the tests and the [Doorman Readme](https://github.com/Pythonista7/doorman/blob/master/README.md) for more.\n\n## Overview\n\n### Client\nA client for the Doorman service which allows voluntary client-side rate limiting. It keeps track of resources and runs a background goroutine to periodically update the server with the current state of the client based on refresh intervals.\n\n### Resource\nA resource is a unique identifier for a rate-limited entity. It is used to track the rate limit for a specific entity and the applied rate limit for the resource is dynamically updated by the client based on the server's response.\n\n### RateLimit\nA wrapper class that accepts a resource and applies the rate limit to it. It is used to control the rate limit for accessing a specific resource , by calling the `wait()` method before accessing the resource.\n\n## Example\n\n#### Basic Usage\n```kotlin\nrunBlocking {\n    val client = DoormanClient.create(\"example-client\")\n    val resourceApples = client.requestResource(\"apples\",10.0)\n    val rateLimit = RateLimiter(resourceApples)\n\n    val endTime = System.currentTimeMillis() + 7000\n\n    var count = 0\n\n    // Tracker coroutine to keep track of the requests made every second\n    val scope = CoroutineScope(this.coroutineContext).launch {\n        while (true) {\n            delay(1000)\n            println(\"[Tracker] Total requests made: $count at ${ZonedDateTime.now()}\")\n        }\n    }\n\n    while(System.currentTimeMillis() \u003c endTime) {\n        rateLimit.wait()\n        count ++\n        // current time in human-readable form\n        println(\"Accessing resource `Apples` at ${ZonedDateTime.now()}\")\n    }\n\n    scope.cancelAndJoin() // close the tracker coroutine.\n}\n```\n\n#### Where it shines\n```kotlin\n\nrunBlocking {\n        /*\n        This assumes that there is a resource as defined below in the doorman server\n          - identifier_glob: fair\n            capacity: 1000\n            safe_capacity: 10\n            description: fair share example\n            algorithm:\n              kind: FAIR_SHARE\n              lease_length: 60\n              refresh_interval: 5 // keeping this small for testing purposes.\n         */\n        val small1Client = DoormanClient.create(\"small1Client-client\")\n        val small1Resource = small1Client.requestResource(\"fair\",100.0)\n\n        val small2Client = DoormanClient.create(\"small2Client-client\")\n        val small2Resource = small2Client.requestResource(\"fair\",100.0)\n\n        val small3Client = DoormanClient.create(\"small3Client-client\")\n        val small3Resource = small3Client.requestResource(\"fair\",100.0)\n\n        val small4Client = DoormanClient.create(\"small4Client-client\")\n        val small4Resource = small4Client.requestResource(\"fair\",100.0)\n\n        val bigClient = DoormanClient.create(\"bigClient-client\")\n        val bigResource = bigClient.requestResource(\"fair\",1000.0)\n\n        delay(5000)\n\n        val biggerClient = DoormanClient.create(\"biggerClient-client\")\n        val biggerResource = biggerClient.requestResource(\"fair\",2000.0)\n\n        println(\"Initially...\")\n        println(\"New Capacity of small1: ${small1Resource.lease?.capacity}\")\n        println(\"New Capacity of small2: ${small2Resource.lease?.capacity}\")\n        println(\"New Capacity of small3: ${small3Resource.lease?.capacity}\")\n        println(\"New Capacity of small4: ${small4Resource.lease?.capacity}\")\n        println(\"New Capacity of big: ${bigResource.lease?.capacity}\")\n        println(\"New Capacity of bigger: ${biggerResource.lease?.capacity}\")\n\n        delay(8000)\n\n        println(\"After 8 seconds...\")\n        println(\"New Capacity of small1: ${small1Resource.lease?.capacity}\")\n        println(\"New Capacity of small2: ${small2Resource.lease?.capacity}\")\n        println(\"New Capacity of small3: ${small3Resource.lease?.capacity}\")\n        println(\"New Capacity of small4: ${small4Resource.lease?.capacity}\")\n        println(\"New Capacity of big: ${bigResource.lease?.capacity}\")\n        println(\"New Capacity of bigger: ${biggerResource.lease?.capacity}\")\n\n    }\n```\n\n#### Output\n```text\nInitially...\nNew Capacity of small1: 100.0\nNew Capacity of small2: 100.0\nNew Capacity of small3: 100.0\nNew Capacity of small4: 100.0\nNew Capacity of big: 600.0\nNew Capacity of bigger: 0.0\n\n...\n...\n\nAfter 8 seconds...\nNew Capacity of small1: 100.0\nNew Capacity of small2: 100.0\nNew Capacity of small3: 100.0\nNew Capacity of small4: 100.0\nNew Capacity of big: 300.0\nNew Capacity of bigger: 300.0\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpythonista7%2Fdoorman-kotlin-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpythonista7%2Fdoorman-kotlin-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpythonista7%2Fdoorman-kotlin-client/lists"}