Home

Awesome

fr33m0nk/clj-bucket4j-datomic Clojars Project

Distributed Bucket4J implementation for Datomic Database <br/> Note: this library uses Clojure wrapper for Bucket4J, clj-bucket4j

How to find this library?

Add the following to your project dependencies:

net.clojars.fr33m0nk/clj-bucket4j-datomic {:mvn/version "0.1.2"}
[net.clojars.fr33m0nk/clj-bucket4j-datomic "0.1.2"]
<dependency>
  <groupId>net.clojars.fr33m0nk</groupId>
  <artifactId>clj-bucket4j-datomic</artifactId>
  <version>0.1.2</version>
</dependency>
implementation("net.clojars.fr33m0nk:clj-bucket4j-datomic:0.1.2")

Usage

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

Important Functions:
NameDescription
fr33m0nk.clj-bucket4j-datomic/->datomic-proxy-managerReturns Distributed Bucket4J Proxy Manager for Datomic
fr33m0nk.clj-bucket4j-datomic/add-distributed-bucketAdds a distributed bucket to Datomic. NOOP if bucket already exists.<br/> Returns the instance of bucket
fr33m0nk.clj-bucket4j-datomic/remove-distributed-bucketRemoves a distributed bucket. <br/> Permanent removal is determined by the RecoveryStrategy chosen while creating the bucket.<br/> Default strategy is to always RestoreOnDelete

Example:

as a distributed throttler

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.

License

Copyright © 2023 Prashant Sinha

Distributed under the MIT License.