Query the DB and LIMIT to an amount which is never reached in a chosen
"responseiveness" interval - say 5s.
In the "for rows.Next() {}" cycle, check for context.Context.Done() and
also a predefined (after query) deadline:
```
rows := db.Query()
deadline := time.Now().Add(5*time.Second)
for rows.Next() {
rows.Scan(&id)
sendMail(id)
if time.Now().After(deadline) {
break
}
}
```
or combine it with context.Context:
```
timer := time.NewTimer(5*time.Second)
timer.Stop()
rows := db.Query()
timer.Reset(5*time.Second)
for rows.Next() {
rows.Scan(&id)
sendMail(id)
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}
```
2018. február 12., hétfő 19:17:59 UTC+1 időpontban yang sheng a következőt
írta:
> I am trying to design a small app to send emails (stored in MongoDB) using
> golang utilizing goroutine and channel and this is the first time i use
> golang.
>
>
> There are 2 types of worker in each server (Retriever and Sender). A
> single retriever will periodically (every few seconds) query MongoDB, fetch
> new email. Then new email will be sent to Senders via a buffered channel
> (has buffer size == number of Sender workers, this might be the issue).
> When a sigterm received, Retriever will exist using ctx.Done and close the
> email channel. Since channel closed, Senders which range over channel will
> exit as well.
>
>
> go func() {
> defer wg.Done()
> for {
> select {
> case <-ctx.Done():
> // received sigterm, close channel
> close(emailCh)
> return
> case <- time.After(5 * time.Second):
> // query DB every 5 seconds to get a single new email....
> if newEmail := dw.getNewEmail(); newEmail != nil {
> emailCh <- newEmail
> }
> }
> }
>
>
>
> I realize this is a bad design and the issues are:
>
> I am using FindAndModify to fetch email every time ( I need to update
> email status to sending when fetching so that the app running in other
> server will not fetch the same doc). That means I am actually sending a
> single email in each interval which makes it non-sense to create multiple
> Sender goroutines.
>
>
> the alternative I can think of right now is:
>
> 1. I could run FindAndModify query multiple times in each interval to get
> N emails. But If the N is larger then buffer size, it will block the select
> and blocking time depends on how many more emails I retrieved than the
> buffer size. If N is too large, then sigterm received, I am not be able to
> shutdown the app in time. If N is too small, I can only send at most
> N/interval emails per second.
>
>
> 2. use an unbuffered channel without interval, (keeps polling the DB).
> Whenever there is a new email, send to channel. the blocking time should be
> minimal (1 email). But the app will continually poll the DB, will it create
> big overhead/too many connections?
>
>
>
> go playground link:
>
> https://play.golang.org/p/LRQ-cnLiDfB
>
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.