On Thu, 25 Oct 2018 at 21:47, <brj...@gmail.com> wrote:

> It seems that I somewhat over-engineered my queue :-) I don't know any
> Java so this is very helpful!
>

When it comes to Java concurrency, ExecutorService and BlockingQueue cover
a lot of bases.


> If I want to know the result of the email send within the worker
> thread, would you recommend sending it back through a channel?
>

You can actually get back a return value directly, though it requires a
wrapper function:

(defn submit [^java.util.concurrent.ExecutorService executor, ^Callable f]
  (.submit executor f))

(let [executor (java.util.concurrent.Executors/newFixedThreadPool 32)]
      result   (submit executor #(+ 1 1))]
  (prn @result))

In the above example we're using ".submit" rather than ".execute", which
tells the executor we care about the return value from the function and
want it back. It returns it as a future, result, which we can deref as
@result. When a future is dereferenced in Clojure, the current threat
blocks until it's receives a value.

The purpose of the "submit" function is to force the executor through type
hints to treat the function as a Callable with a return value. I wasn't
able to get it working without this wrapper.

One purpose of my queue was to be able to put urgent messages at the front
> of the queue. I guess that using a threadpool with workers does not give me
> any guarantee that the email is delivered immediately, since X emails may
> already have been added but not yet sent. I guess that one one use a
> dedicated thread(pool) for urgent messages?
>

Yes, you could do that. You could also use a priority queue with the
PriorityBlockingQueue class. A priority queue is a queue with a comparator
that allows you to control ordering, shunting certain items to the front.

There's a library called Claypoole
<https://github.com/TheClimateCorporation/claypoole> that packages all
these Java classes into nice Clojure functions, and it includes a priority
queue so I'd advise looking into it. I haven't tried it myself, but it
looks like you can do something like:

(require '[com.climate.claypoole :as cp])

(let [pool    (cp/priority-threadpool 32)
      result1 (cp/future (cp/with-priority pool 1000) (send-email
important-mail))
      result2 (cp/future (cp/with-priority pool 0)    (send-email
unimportant-mail))]
  (prn @result1)
  (prn @result2))

Which is probably easier than messing around with the executor classes
directly.

-- 
James Reeves
booleanknot.com

-- 
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/d/optout.

Reply via email to