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.