Войти Регистрация
Код-ревью

7. Массовая отправка push-уведомлений

Сложная

Go · 56 строк

SendAll отправляет пачку уведомлений через HTTP-провайдера и считает, сколько push ушло каждому клиенту. В обычный день в пачке 5–20 тысяч уведомлений, в день зарплаты — до 2 млн.

Отметьте строки с ошибками. Код собирается Go 1.22.

В работе: Уведомления о списаниях и зачислениях: клиент ждёт push через секунды после операции.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Ответ один на подход: после него показываем разбор.
горутиныканалыHTTP-клиентгонка на map

Источник: на задачах Сбера: push-уведомления о платежах. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package push
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "log"
  7. "net/http"
  8. "sync"
  9. )
  10. type Notification struct {
  11. ClientID string
  12. Phone string
  13. Text string
  14. }
  15. type Sender struct {
  16. client *http.Client
  17. url string
  18. sent map[string]int
  19. }
  20. func NewSender(url string) *Sender {
  21. return &Sender{client: &http.Client{}, url: url, sent: map[string]int{}}
  22. }
  23. func (s *Sender) SendAll(batch []Notification) error {
  24. var wg sync.WaitGroup
  25. errs := make(chan error)
  26. for _, n := range batch {
  27. wg.Add(1)
  28. go func() {
  29. defer wg.Done()
  30. body, _ := json.Marshal(n)
  31. resp, err := s.client.Post(s.url, "application/json", bytes.NewReader(body))
  32. if err != nil {
  33. log.Printf("push failed for %s: %v", n.Phone, err)
  34. errs <- err
  35. return
  36. }
  37. if resp.StatusCode != http.StatusOK {
  38. errs <- fmt.Errorf("push status %d", resp.StatusCode)
  39. return
  40. }
  41. resp.Body.Close()
  42. s.sent[n.ClientID]++
  43. }()
  44. }
  45. wg.Wait()
  46. close(errs)
  47. for err := range errs {
  48. return err
  49. }
  50. return nil
  51. }