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 golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to