If I was building a system like the one you describe for real, then the
first tool I'd reach for would be a email sending service, like Mailgun,
Sendgrid, or AWS SES. These sorts of services take care of queuing mail,
retrying on failure, and keeping track of mail bounces. They also all have
free tiers: Mailgun is free for the first 10,000 emails per month, Sendgrid
is free for around 3,000 emails a month, and SES is free for 62,000 emails
per month. They also save me the trouble of maintaining and configuring my
own email sending system.

If I was building something myself, for whatever reason, then I'd make it
as simple as possible.

(defn send-queued-mail [db mail]
  (let [sent-successfully? (send-mail mail)]
    (if sent-succesfully?
      (remove-mail-from-queue db mail))))

(defn send-queued-mail [db]
  (doseq [mail (fetch-queued-mail-in-priority-order db)]
    (send-queued-mail db mail)))

(defn init-scheduler [db]
  (doto (Executors/newScheduledThreadPool 32)
    (.scheduleAtFixedRate #(send-queued-mail db) 30 30 TimeUnit/SECONDS)))

I wouldn't have an application-specific queue, as I'd want it to be robust
against the process ending.

But I don't think there's any situation where I'd want to do it myself if I
could avoid it, not when there are solutions out there that already do all
of the heavy lifting for me.


On Sat, 27 Oct 2018 at 12:59, <brj...@gmail.com> wrote:

> Thanks for pointing out the submit function and explaining the wrapper.
>>> Would you specifically advise against sending the result back through a
>>> channel?
>>>
>>
>> It depends what you're trying to do. What are you doing with the result,
>> and what's your reasoning for not handling it in your "send-email!"
>> function?
>>
>
> That is a very good question. I currently believe that the there will be
> three different scenarios of sending emails.
>
> 1. Fire and (almost) forget - where delivery is not guaranteed but the app
> user will be notified if delivery was unsuccessful as soon as that status
> is available.
> 2. First send of a guaranteed delivery message - where all messages are
> stored in the DB but the send is attempted immediately.
> 3. Retry of sending a guaranteed delivery message - i.e., a failed send is
> picked up from the DB by some scheduled task.
>
> I would like the send-mail function to be agnostic of which of these
> scenarios a particular message is sent in (and not have to include any DB
> logic). Rather, it would just return the status whenever it's available and
> let the caller decide what to do with it (scenario 1 or 2). If the status
> is returned as a future, the caller would have wait until the future is
> realized to avoid blocking - and do this wait in a non-blocking manner. It
> seems that returning using a channel and receiving the status in a go block
> would achieve precisely this with very little code. Also, if there is a
> chain of function between the sender and the worker thread, the channel
> would bypass the caller chain and each chained caller doesn't need know the
> nature of the status. Also, if some reason there are multiple parties who
> are interested in the status (no use case yet), it would be easy to just
> add more return channels to the email. Does this also seem over-enginereed
> compared to just returning the future from the worker and letting it bubble
> up to however is interested?
>
> Thanks,
> Brjánn
>
>
>>
>> --
>> 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.
>>
> --
> 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.
>


-- 
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