I’m using a Clojure application to access data from a web API. I’m going to be making a lot of requests, and many of the requests will lead to more requests being made, so I want to keep the request URLs in a queue that will leave 60 seconds between subsequent downloads.
Following this blog post I put this together:
(def queue-delay (* 1000 60)) ; one minute
(defn offer!
[q x]
(.offerLast q x)
q)
(defn take!
[q]
(.takeFirst q))
(def my-queue (java.util.concurrent.LinkedBlockingDeque.))
(defn- process-queue-item
[item]
(println ">> " item) ; this would be replaced by downloading `item`
(Thread/sleep queue-delay))
If I include a (future (process-queue-item (take! my-queue)))
in my code somewhere then at the REPL I can (offer! my-queue "something")
and I see the ">> something" printed immediately. So far so good! But I need the queue to last for the entire time my program is active. The (future ...)
call I just mentioned works to pull one item out of the queue, once it’s available, but I want something that will watch the queue continually and call process-queue-item
whenever something is available.
Also, contrary to the usual Clojure love for concurrency, I want to ensure that only one request is being made at a time and that my program waits 60 seconds to make each subsequent request.
I think this Stack Overflow question is relevant, but I’m not sure how to adapt it to do what I want. How do I poll my queue continuously and ensure that only one request is being run at once?