package main import ( "strings" "sync" "time" ) type GenericMessage struct { chat_id int64 msg string } type Sender interface { Send(msg GenericMessage) error } func tg_sender_worker(tg_events <-chan GenericMessage, s Sender, wg *sync.WaitGroup, messageNotMoreOftenThan time.Duration) { wg.Add(1) defer wg.Done() messagesToSend := make(map[int64]*strings.Builder) waitingStarted := false timeoutEvents := make(chan interface{}) for { select { case ev, ok := <-tg_events: if !ok { return } // Collect all messages to send them at once _, messageBuilderExists := messagesToSend[ev.chat_id] if !messageBuilderExists { messagesToSend[ev.chat_id] = &strings.Builder{} } messagesToSend[ev.chat_id].WriteString(ev.msg) messagesToSend[ev.chat_id].WriteRune('\n') if !waitingStarted { waitingStarted = true go func() { time.Sleep(messageNotMoreOftenThan) timeoutEvents <- nil }() } case <-timeoutEvents: waitingStarted = false for chat_id, msgBuilder := range messagesToSend { err := s.Send(GenericMessage{chat_id, msgBuilder.String()}) if err != nil { // TODO: handle it better panic(err) } delete(messagesToSend, chat_id) } if tg_events == nil { close(timeoutEvents) } } if tg_events == nil && timeoutEvents == nil { return } } }