Hello,
I'm working on a piece of code that uses congomongo to access mongodb. What
I want to implement is to use one collection of the DB as a queue(let's
say, it's called "task").

Using congomongo, it's easy to fetch a task that is of status :queue : (def
t (fetch-one :task :where {:status :queue})),
and also it's simple to update it: (update! :task t (assoc t :status
:running))

But how to make a safe and consistent "dequeue" operation in concurrent
context? A naive dequeue should look like this:

(let [t (fetch-one:task :where {:status :queue})]
  (update! :task t (assoc t :status :running))
  t)

But taking concurrency into consideration, this implementation is
error-prone, at least from my point of view. Consider this:

When 2 threads are fetching the task, it's very likely that the task is
fetched twice using the previous piece of code and they would be executed
twice.

Do we have something like transaction? Something that will enforce the
"fetch-one" and "update!" statement are both executed before another
“fetch-one" operation is adopted?

What I can think of is to use an agent. And my code looks like this:

(def db-agent (agent nil))
(defn dequeue []
  (letfn [(do-dequeue [da]
            (let [task (mongo/fetch-one :task :where {:status :queue})]
              (when task
                (mongo/update! :task feed (assoc task :status :running)))
              task))]
    (send db-agent do-dequeue)
    @db-agent)))

However, I still doubt the correctness of this solution. Right before the
@db-agent is called, won't another thread call "dequeue", which will
involve another "send” and change the value of db-agent?

I'm wondering if anyone can help. Thanks.

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to