Войти Регистрация
Конкурентность

26. Этикетки для смены сортировки Ozon

Средняя

Go · 56 строк

Перед сменой на сортировочном центре кладовщик нажимает «Печать», и PrintBatch получает до 300 отправлений. Рендер одной этикетки — HTTP-запрос в сервис шаблонов, обычно 80 мс, но иногда он висит минутами.

За сутки на сервисе набирается 40 тысяч горутин, а кладовщики жалуются, что кнопка «крутится» дольше 30 секунд. Отметьте строки с ошибками.

В работе: Бэкенд терминала печати этикеток на сортировочном центре.

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

Источник: наша задача на данных Ozon: сортировочный центр и отправления. Условие пересказано своими словами.

  1. package labels
  2. import (
  3. "context"
  4. "time"
  5. )
  6. type Shipment struct{ ID, Address string }
  7. type Label struct {
  8. ShipmentID string
  9. PDF []byte
  10. }
  11. type Renderer interface {
  12. Render(ctx context.Context, s Shipment) (Label, error)
  13. }
  14. // PrintBatch готовит этикетки на смену: до 300 отправлений.
  15. func PrintBatch(ctx context.Context, r Renderer, ships []Shipment) ([]Label, error) {
  16. ctx, _ = context.WithTimeout(ctx, 30*time.Second)
  17. jobs := make(chan Shipment)
  18. results := make(chan Label)
  19. errs := make(chan error)
  20. go func() {
  21. for _, s := range ships {
  22. jobs <- s
  23. }
  24. close(jobs)
  25. }()
  26. for w := 0; w < 8; w++ {
  27. go func() {
  28. for s := range jobs {
  29. l, err := r.Render(context.Background(), s)
  30. if err != nil {
  31. errs <- err
  32. return
  33. }
  34. results <- l
  35. }
  36. }()
  37. }
  38. var labels []Label
  39. for len(labels) < len(ships) {
  40. select {
  41. case l := <-results:
  42. labels = append(labels, l)
  43. case err := <-errs:
  44. return nil, err
  45. }
  46. }
  47. return labels, nil
  48. }