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

27. Ежедневное списание абонентской платы

Средняя

Go · 41 строк

Каждую ночь задача списывает дневную часть абонентской платы: месячная плата делится на число дней в месяце. Если на балансе не хватает, номер блокируется. Абонентов — 10 млн, пополнения идут круглосуточно.

Задачу иногда перезапускают после падения. Отметьте строки с ошибками.

В работе: Биллинг: ночная задача, после которой абоненты утром видят списание в приложении.

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

Источник: на задачах МТС: биллинг тарифов. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package billing
  2. import (
  3. "context"
  4. "database/sql"
  5. "log"
  6. "time"
  7. )
  8. type Subscriber struct {
  9. ID int64
  10. Phone string
  11. Balance float64
  12. MonthFee float64
  13. }
  14. func DailyCharge(ctx context.Context, db *sql.DB, now time.Time) error {
  15. rows, err := db.QueryContext(ctx, "SELECT id, phone, balance, month_fee FROM subscribers WHERE active")
  16. if err != nil {
  17. return err
  18. }
  19. defer rows.Close()
  20. daysInMonth := 30
  21. for rows.Next() {
  22. var s Subscriber
  23. if err := rows.Scan(&s.ID, &s.Phone, &s.Balance, &s.MonthFee); err != nil {
  24. return err
  25. }
  26. fee := s.MonthFee / float64(daysInMonth)
  27. if s.Balance < fee {
  28. log.Printf("блокировка %s: баланс %.2f", s.Phone, s.Balance)
  29. db.ExecContext(ctx, "UPDATE subscribers SET active = false WHERE id = $1", s.ID)
  30. continue
  31. }
  32. _, err := db.ExecContext(ctx, "UPDATE subscribers SET balance = $1 WHERE id = $2", s.Balance-fee, s.ID)
  33. if err != nil {
  34. return err
  35. }
  36. }
  37. return nil
  38. }