Ошибка: целое число выходит за допустимый диапазон

Это сработало для post_actions, спасибо за предложение!

Сейчас мы всё ещё наблюдаем две ошибки:

  1. GET https://devforum.roblox.com/notifications возвращает 404 для пользователей, у которых есть уведомления с идентификаторами типа bigInt.

  2. Запланированная задача Jobs::GrantAnniversaryBadges завершается ошибкой.

Возможно ли, что модель/контроллер/сервис уведомлений всё ещё жёстко задан так, что поле notifications.id определяется как целое число (integer)?

Очень маловероятно… Ошибка 404 звучит неправильно. Есть ли что-то в /logs, что описывает проблему?

К сожалению, в самом /logs я не нашёл ничего особо полезного, но при локальном воспроизведении проблемы вижу, что запрос приходит и возвращается 404. Это происходит только тогда, когда я задаю ID последнего уведомления как bigint (в диапазоне int32 всё работает отлично):

Просматривая код, я заметил, что при вызове http://localhost/notifications.json?limit=30 получаю корректный ответ:

{
  "notifications": [
    {
      "id": 2148935910,
      "user_id": 2,
      "notification_type": 5,
      "read": true,
      "high_priority": false,
      "created_at": "2023-02-16T00:50:53.135Z",
      "post_number": 2,
      "topic_id": 8,
      "fancy_title": "Welcome to the Lounge",
      "slug": "welcome-to-the-lounge",
      "data": {
        "topic_title": "Welcome to the Lounge",
        "original_post_id": 13,
        "original_post_type": 1,
        "original_username": "blarouche",
        "revision_number": null,
        "display_username": "blarouche"
      }
    }
  ],
  "total_rows_notifications": 1,
  "seen_notification_id": 1001,
  "load_more_notifications": "/notifications?offset=60&username=bjlarouche"
}

Однако, как только я передаю параметр запроса recent, например http://localhost/notifications.json?recent=true&limit=30 (именно так вызывается меню уведомлений), получаю следующее:

{
  "errors": [
    "The requested URL or resource could not be found."
  ],
  "error_type": "not_found"
}

редактирование: мы предполагаем, что проблема в том, что current_user.seen_notification_id всё ещё имеет тип integer :thinking:

Я думаю, что мы теперь в безопасности!

Мы заметили, что нам нужно было мигрировать столбцы в других таблицах, которые ссылаются на notification_id, а не только на notifications.id. В противном случае services/notifications.rb или services/badge_granter.rb вызывали бы ошибки.


Для любых других крупных форумов, которые в будущем столкнутся с этой проблемой в уведомлениях, вот что мы сделали…

Всего нам пришлось мигрировать четыре столбца в четырех таблицах:

  1. notifications.id
  2. user.seen_notification_id
  3. user_badges.notification_id
  4. shelved_notifications.notification_id

Изначально мы использовали команду ALTER для пункта #1, предложенную выше, но затем, как упоминалось, решили использовать миграции ActiveRecord, чтобы файлы миграций добавлялись в схему.

20230215070319_change_notifications_id_to_bigint.rb
# frozen_string_literal: true

class ChangeNotificationsIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :notifications, :id, :bigint
    end
end
20230215070320_change_user_seen_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeUserSeenNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :users, :seen_notification_id, :bigint
    end
end
20230215070321_change_user_badges_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeUserBadgesNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :user_badges, :notification_id, :bigint
    end
end
20230215070322_change_shelved_notifications_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeShelvedNotificationsNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :shelved_notifications, :notification_id, :bigint
    end
end

В нашей настройке используется кастомный Dockerfile (мы собираем образы, чтобы запускать Discourse и Sidekiq на отдельных ресурсах в Kubernetes), поэтому копирование этих файлов в /db/migrate в рамках нашего Dockerfile было straightforward.

Затем мы просто позволили rake db:migrate обработать остальное. После того как мы выполнили rolling restart всех наших подов Discourse и Sidekiq, всё заработало как ожидалось :crossed_fingers:.

3 лайка

Отличные данные. Мы просто решимся и выполним миграцию в ядре Discourse на тип bigint. Это дорогостоящее решение, но на крупных форумах эта проблема наверняка возникнет снова, поэтому лучше исправить её сейчас.

Обратите внимание… исходный пост касается post_id. Переполнение этого поля будет гораздо сложнее, чем в случае с уведомлениями. 2,1 миллиарда постов обязательно произойдёт, но стоимость перехода post_id на bigint намного выше, чем для notification_id. Мы можем пока подождать с этой «бомбой замедленного действия».

4 лайка

Брэндон,

Думаю, мы в итоге выберем:

Сложность здесь в том, что я не хочу «наказывать» 40 000 инстансов Discourse из-за одного или двух форумов-аутсайдеров, которым удалось достичь невероятного показателя в 2,5 миллиарда уведомлений.

Что ты думаешь?

(Примечание: это также зацепит хотя бы одну упущенную таблицу — есть ещё и таблица чата)

3 лайка

Это было бы здорово и выглядит как разумное решение :slight_smile:

Вернусь к этому вопросу — это уже объединено. :partying_face:

5 лайков

Эта тема была автоматически закрыта через 4 дня. Новые ответы больше не допускаются.