Advertisement
Guest User

Untitled

a guest
Dec 15th, 2010
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 1.31 KB | None | 0 0
  1. (ns hnparser.rate-limit)
  2.  
  3. (defn now
  4.   []
  5.   (/ (System/currentTimeMillis) 1000)) ; working in seconds seems simpler
  6.  
  7. (defn rate-limit-creator
  8.   [rate per]
  9.   (let [allowed (ref rate) last-access (ref (now))]
  10.     (fn [& more]
  11.       (dosync
  12.        (let [current-time (now) time-passed (- current-time @last-access)]
  13.      (ref-set allowed
  14.           (let [allow (+ @allowed (* time-passed (/ rate per)))]
  15.             (if (> allow rate) ; make sure not to make the bucket
  16.               rate             ; larger than the allowed rate
  17.               allow)))
  18.      (ref-set last-access current-time)
  19.      (if (>= @allowed 1) ; I'm doing the rest outside the doysnc
  20.          (do             ; to avoid thunks and side effects
  21.            (ref-set allowed (dec @allowed))
  22.            [true]) ; about to estimate the time till were within capacity
  23.          [false (/ (* (- 1 @allowed) rate) per)]))))))
  24.  
  25. (defn rate-limit
  26.   [func rate per retry]
  27.   (let [rate-limiter (rate-limit-creator rate per)]
  28.     (fn [& args]
  29.       (let [throttler (rate-limiter)]
  30.     (if (first throttler)
  31.       (apply func args)
  32.       (if retry
  33.         (do ; convert from seconds to milliseconds
  34.           (. Thread sleep (* 1000 (second throttler)))
  35.           (recur args))))))))
  36.  
  37. (defmacro defrlf ; must.. hide.. complexity..
  38.   [name func rate per retry]
  39.   `(def ~name (rate-limit ~func ~rate ~per ~retry)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement