Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ns hnparser.rate-limit)
- (defn now
- []
- (/ (System/currentTimeMillis) 1000)) ; working in seconds seems simpler
- (defn rate-limit-creator
- [rate per]
- (let [allowed (ref rate) last-access (ref (now))]
- (fn [& more]
- (dosync
- (let [current-time (now) time-passed (- current-time @last-access)]
- (ref-set allowed
- (let [allow (+ @allowed (* time-passed (/ rate per)))]
- (if (> allow rate) ; make sure not to make the bucket
- rate ; larger than the allowed rate
- allow)))
- (ref-set last-access current-time)
- (if (>= @allowed 1) ; I'm doing the rest outside the doysnc
- (do ; to avoid thunks and side effects
- (ref-set allowed (dec @allowed))
- [true]) ; about to estimate the time till were within capacity
- [false (/ (* (- 1 @allowed) rate) per)]))))))
- (defn rate-limit
- [func rate per retry]
- (let [rate-limiter (rate-limit-creator rate per)]
- (fn [& args]
- (let [throttler (rate-limiter)]
- (if (first throttler)
- (apply func args)
- (if retry
- (do ; convert from seconds to milliseconds
- (. Thread sleep (* 1000 (second throttler)))
- (recur args))))))))
- (defmacro defrlf ; must.. hide.. complexity..
- [name func rate per retry]
- `(def ~name (rate-limit ~func ~rate ~per ~retry)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement