Distributed Bucket4J implementation for Datomic Database
Note: this library uses Clojure wrapper for Bucket4J, clj-bucket4j
Add the following to your project dependencies:
- CLI/deps.edn dependency information
net.clojars.fr33m0nk/clj-bucket4j-datomic {:mvn/version "0.1.2"}
- Leningen/Boot
[net.clojars.fr33m0nk/clj-bucket4j-datomic "0.1.2"]
- Maven
<dependency>
<groupId>net.clojars.fr33m0nk</groupId>
<artifactId>clj-bucket4j-datomic</artifactId>
<version>0.1.2</version>
</dependency>
- Gradle
implementation("net.clojars.fr33m0nk:clj-bucket4j-datomic:0.1.2")
Add Datomic peer dependency in you project if not present.
Prior to using below functions, it is necessary to execute these Datomic migrations
All functions are available through the fr33m0nk.clj-bucket4j-datomic
namespace
Name | Description |
---|---|
fr33m0nk.clj-bucket4j-datomic/->datomic-proxy-manager |
Returns Distributed Bucket4J Proxy Manager for Datomic |
fr33m0nk.clj-bucket4j-datomic/add-distributed-bucket |
Adds a distributed bucket to Datomic. NOOP if bucket already exists. Returns the instance of bucket |
fr33m0nk.clj-bucket4j-datomic/remove-distributed-bucket |
Removes a distributed bucket. Permanent removal is determined by the RecoveryStrategy chosen while creating the bucket. Default strategy is to always RestoreOnDelete |
Suppose you need to have a fresh exchange rate between dollars and euros. To get the rate you continuously poll the third-party provider, and by contract with the provider you should poll not often than 100 times per 1 minute, else provider will block your IP:
(require '[datomic.api :as d] '[fr33m0nk.clj-bucket4j :as b4j] '[fr33m0nk.datomic-schema :refer [b4j-schema]] '[fr33m0nk.clj-bucket4j-datomic :as b4j-datomic])
(import '(io.github.bucket4j.distributed.proxy ClientSideConfig))
(def datomic-conn (return-datomic-connection))
;; Execute Datomic migrations for supporting Distributed Bucket4J
@(d/transact datomic-conn b4j-schema)
;; Instance of datomic-proxy-manager
;; For most cases `(ClientSideConfig/getDefault)` is enough
;; Look into documentation of ClientSideConfig to figure right scenarios to customize it
(def datomic-proxy-manager (b4j-datomic/->datomic-proxy-manager datomic-conn (ClientSideConfig/getDefault)))
;; Bucket configuration allowing 100 hits in 60000 ms (1 minute)
(def bucket-configuration (-> (b4j/bucket-configuration-builder)
(b4j/add-limit (b4j/simple-bandwidth 100 60000))
(b4j/build)))
;; Adds a distributed bucket to Datomic
(def distributed-bucket (b4j-datomic/add-distributed-bucket datomic-proxy-manager "test-bucket-1" bucket-configuration))
(def exchange-rates (atom 0.0))
;; do polling in infinite loop
(while true
;; Consume a token from the token bucket.
;; Depending on the availability of Token, `b4j/try-consume` returns true or false.
(when (b4j/try-consume distributed-bucket 1)
(swap! exchange-rate #(identity %2) (poll-exchange-rate))))
More detailed usages of above functions and more can be found in tests.
Copyright © 2023 Prashant Sinha
Distributed under the MIT License.