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

Часто получаю эту ошибку в Sidekiq (списки Retries и Dead):

Jobs::HandledExceptionWrapper: Wrapped ActiveRecord::RangeError: PG::NumericValueOutOfRange: ERROR: integer out of range

Я заметил эту же ошибку для следующих задач:
Jobs::PostAlert
Jobs::ProcessPost
Jobs::NotifyCategoryChange

Это уже немного обсуждалось ранее здесь: Feedback on the new Review Queue (2019) - #250 by markersocial

2 лайка

Пожалуйста, выполните:

cd /var/discourse/
./launcher enter app
su postgres
psql
\x
\connect discourse 
SELECT id FROM notifications ORDER BY 1 DESC LIMIT 1;
\q
exit
4 лайка

Спасибо, @Falco, я только что его запустил. Вот результат:

-[ RECORD 1 ]--
id | 2147483496
4 лайка

Хорошо, это известная проблема с максимальным значением целого числа. Чтобы её исправить, нужно перейти на bigint. Я разберусь с этим.

6 лайков

На данный момент ваше решение — выполнить следующие команды:

cd /var/discourse/
./launcher enter app
su postgres
psql
\x
\connect discourse 
ALTER TABLE notifications ALTER COLUMN id SET DATA TYPE bigint
\q
exit

Это значение по умолчанию для новых установок, но в старых установках используется неверный тип данных.

Выполнение этого решения может быть сложным, так как оно заблокирует таблицу. Возможно, вам потребуется сначала снизить нагрузку на веб-сервер.

2 лайка

Спасибо @Falco и @sam — очень признателен :slight_smile:

Что касается обходного пути, это должно быть относительно безопасно? Я не переживаю по поводу простоя, только чтобы ничего не сломать.

Используется стандартный app.yml с одним контейнером. Для снижения нагрузки на веб-часть, как вы думаете, достаточно включить режим только для чтения и выполнить ./launcher stop app, ./launcher start app перед применением обходного пути?

Ничего не сломается, в худшем случае процесс просто «зависнет» на очень долгое время.

2 лайка

Спасибо, Сэм, я применил обходное решение. Однако после ввода:

ALTER TABLE notifications ALTER COLUMN id SET DATA TYPE bigint

никакой обратной связи не поступило.

Не уверен, возможно, процесс всё ещё выполняется. В данный момент получаю ту же ошибку (в списке dead в /sidekiq, для задач с последней попыткой «только что») для:

Jobs::PostAlert
Jobs::ProcessPost
Jobs::NotifyCategoryChange

Похоже, вам также нужно передать столбец post_id

1 лайк

Спасибо! :slight_smile:

Только чтобы убедиться, всё ли выглядит правильно?

ALTER TABLE notifications ALTER COLUMN post_id SET DATA TYPE bigint

Да, это должно быть безопасно. Как только мы добавим официальную миграцию, это станет возможным.

1 лайк

Отлично, спасибо :slight_smile:

Я выполнил это (подтверждения/обратной связи не поступило, как и в предыдущий раз). Форум не замедлился, поэтому не уверен, что это сработало. Сейчас получаю те же ошибки.

Возможно, лучше подождать официальной миграции.

1 лайк

Да, похоже, это в таблице post_alerts, нам нужно проверить множество таблиц.

1 лайк

Интересно, как обстоят дела с этой проблемой сейчас? Ошибки прекратились?

Изначально мы думали о проведении официальной миграции, но риски значительно перевешивают выгоду. Нам крайне редко встречаются базы данных с количеством записей более 2 147 483 647. 2,1 миллиарда — это действительно огромное число.

Недостаток увеличения размера повсеместно заключается в росте требований к хранилищу.

На данный момент мы рассматриваем возможность добавления задачи rake, которая «освободит место», если вы попадаете в редкий случай, когда в Discourse есть таблицы, содержащие 2 миллиарда строк (или содержали 2 миллиарда строк с учётом изменений).

1 лайк

Спасибо за уточнение, @sam.

Я только что обновился до версии 2.8.0.beta6, но всё ещё получаю ошибки выхода за пределы диапазона целых чисел.

Думаю, дело в том, что количество уведомлений достигло огромной величины, и это гораздо более реалистичный сценарий для достижения лимита по сравнению с количеством постов. Множество крупных тем с большим количеством ответов, лайков и т. д. от разных пользователей могут привести к значительному числу уведомлений.

Запуск задачи Rake звучит отлично :slight_smile:

Я знаю, что это старая тема —

У нас только что возникла эта же проблема на нашей установке (devforum.roblox.com)! Мы используем версию 2.8.9, но скоро обновимся до 3.0.1.

Мы заметили что-то не так, когда пользователи начали получать ошибки 403/500 при попытке поставить лайк или убрать его у постов.

Затем я наткнулся на эту тему и проверил нашу таблицу уведомлений:

=> SELECT id FROM notifications ORDER BY 1 DESC LIMIT 1;
     id     
------------
 2147483647
(1 row)

@sam, является ли указанное выше временное решение всё ещё лучшим предложением, или с сентября 2021 года было уделено больше внимания задаче rake?

Дополнительная информация —

После изменения столбца notifications.id я столкнулся с отдельной проблемой в задаче Jobs::PostAlert.

Исключение задачи: 2147498514 выходит за пределы диапазона для ActiveModel::Type::Integer с лимитом 4 байта

Возможно, я упускаю другую таблицу или столбец? Или где-то в Ruby всё ещё ожидается тип данных integer?

трассировка стека
activemodel-6.1.6.1/lib/active_model/type/integer.rb:49:in `ensure_in_range'

activemodel-6.1.6.1/lib/active_model/type/integer.rb:28:in `serialize'

activemodel-6.1.6.1/lib/active_model/attribute.rb:56:in `value_for_database'

activemodel-6.1.6.1/lib/active_model/attribute.rb:68:in `forgetting_assignment'

activemodel-6.1.6.1/lib/active_model/attribute_set.rb:90:in `transform_values'

activemodel-6.1.6.1/lib/active_model/attribute_set.rb:90:in `map'

activemodel-6.1.6.1/lib/active_model/dirty.rb:262:in `forget_attribute_assignments'

activemodel-6.1.6.1/lib/active_model/dirty.rb:154:in `changes_applied'

activerecord-6.1.6.1/lib/active_record/attribute_methods/dirty.rb:202:in `_create_record'

activerecord-6.1.6.1/lib/active_record/callbacks.rb:461:in `block in _create_record'

activesupport-6.1.6.1/lib/active_support/callbacks.rb:106:in `run_callbacks'

activesupport-6.1.6.1/lib/active_support/callbacks.rb:824:in `_run_create_callbacks'

activerecord-6.1.6.1/lib/active_record/callbacks.rb:461:in `_create_record'

activerecord-6.1.6.1/lib/active_record/timestamp.rb:108:in `_create_record'

activerecord-6.1.6.1/lib/active_record/persistence.rb:900:in `create_or_update'

activerecord-6.1.6.1/lib/active_record/callbacks.rb:457:in `block in create_or_update'

activesupport-6.1.6.1/lib/active_support/callbacks.rb:106:in `run_callbacks'

activesupport-6.1.6.1/lib/active_support/callbacks.rb:824:in `_run_save_callbacks'

activerecord-6.1.6.1/lib/active_record/callbacks.rb:457:in `create_or_update'

activerecord-6.1.6.1/lib/active_record/timestamp.rb:126:in `create_or_update'

activerecord-6.1.6.1/lib/active_record/persistence.rb:507:in `save!'

activerecord-6.1.6.1/lib/active_record/validations.rb:53:in `save!'

activerecord-6.1.6.1/lib/active_record/transactions.rb:302:in `block in save!'

activerecord-6.1.6.1/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'

activerecord-6.1.6.1/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `block in transaction'

activerecord-6.1.6.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'

activesupport-6.1.6.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'

activesupport-6.1.6.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'

activesupport-6.1.6.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'

activesupport-6.1.6.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'

activesupport-6.1.6.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'

activerecord-6.1.6.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'

activerecord-6.1.6.1/lib/active_record/connection_adapters/abstract/database_statements.rb:320:in `transaction'

activerecord-6.1.6.1/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'

activerecord-6.1.6.1/lib/active_record/transactions.rb:302:in `save!'

activerecord-6.1.6.1/lib/active_record/suppressor.rb:48:in `save!'

/app/app/models/notification.rb:40:in `tap'

/app/app/models/notification.rb:40:in `consolidate_or_create!'

activerecord-6.1.6.1/lib/active_record/relation/delegation.rb:67:in `block in consolidate_or_create!'

activerecord-6.1.6.1/lib/active_record/relation.rb:406:in `block in scoping'

activerecord-6.1.6.1/lib/active_record/relation.rb:804:in `_scoping'

activerecord-6.1.6.1/lib/active_record/relation.rb:406:in `scoping'

activerecord-6.1.6.1/lib/active_record/associations/collection_proxy.rb:1109:in `scoping'

activerecord-6.1.6.1/lib/active_record/relation/delegation.rb:67:in `consolidate_or_create!'

/app/app/services/post_alerter.rb:496:in `create_notification'

/app/app/services/post_alerter.rb:825:in `block in notify_post_users'

/app/app/services/post_alerter.rb:838:in `block (2 levels) in each_user_in_batches'

activerecord-6.1.6.1/lib/active_record/relation/delegation.rb:88:in `each'

activerecord-6.1.6.1/lib/active_record/relation/delegation.rb:88:in `each'

/app/app/services/post_alerter.rb:838:in `block in each_user_in_batches'

/app/app/services/post_alerter.rb:837:in `each'

/app/app/services/post_alerter.rb:837:in `each_slice'

/app/app/services/post_alerter.rb:837:in `each_user_in_batches'

/app/app/services/post_alerter.rb:821:in `notify_post_users'

/app/app/services/post_alerter.rb:162:in `after_save_post'

/app/app/jobs/regular/post_alert.rb:11:in `execute'

/app/app/jobs/base.rb:232:in `block (2 levels) in perform'

rails_multisite-4.0.0/lib/rails_multisite/connection_management.rb:80:in `with_connection'

/app/app/jobs/base.rb:221:in `block in perform'

/app/app/jobs/base.rb:217:in `each'

/app/app/jobs/base.rb:217:in `perform'

sidekiq-6.3.1/lib/sidekiq/processor.rb:196:in `execute_job'

sidekiq-6.3.1/lib/sidekiq/processor.rb:164:in `block (2 levels) in process'

sidekiq-6.3.1/lib/sidekiq/middleware/chain.rb:138:in `block in invoke'

/app/lib/sidekiq/pausable.rb:138:in `call'

sidekiq-6.3.1/lib/sidekiq/middleware/chain.rb:140:in `block in invoke'

sidekiq-6.3.1/lib/sidekiq/middleware/chain.rb:143:in `invoke'

sidekiq-6.3.1/lib/sidekiq/processor.rb:163:in `block in process'

sidekiq-6.3.1/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch'

sidekiq-6.3.1/lib/sidekiq/job_retry.rb:112:in `local'

sidekiq-6.3.1/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch'

sidekiq-6.3.1/lib/sidekiq/rails.rb:14:in `block in call'

activesupport-6.1.6.1/lib/active_support/execution_wrapper.rb:91:in `wrap'

activesupport-6.1.6.1/lib/active_support/reloader.rb:72:in `block in wrap'

activesupport-6.1.6.1/lib/active_support/execution_wrapper.rb:91:in `wrap'

activesupport-6.1.6.1/lib/active_support/reloader.rb:71:in `wrap'

sidekiq-6.3.1/lib/sidekiq/rails.rb:13:in `call'

sidekiq-6.3.1/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch'

sidekiq-6.3.1/lib/sidekiq/processor.rb:257:in `stats'

sidekiq-6.3.1/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch'

sidekiq-6.3.1/lib/sidekiq/job_logger.rb:13:in `call'

sidekiq-6.3.1/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch'

sidekiq-6.3.1/lib/sidekiq/job_retry.rb:79:in `global'

sidekiq-6.3.1/lib/sidekiq/processor.rb:124:in `block in dispatch'

sidekiq-6.3.1/lib/sidekiq/logger.rb:11:in `with'

sidekiq-6.3.1/lib/sidekiq/job_logger.rb:33:in `prepare'

sidekiq-6.3.1/lib/sidekiq/processor.rb:123:in `dispatch'

sidekiq-6.3.1/lib/sidekiq/processor.rb:162:in `process'

sidekiq-6.3.1/lib/sidekiq/processor.rb:78:in `process_one'

sidekiq-6.3.1/lib/sidekiq/processor.rb:68:in `run'

sidekiq-6.3.1/lib/sidekiq/util.rb:43:in `watchdog'

sidekiq-6.3.1/lib/sidekiq/util.rb:52:in `block in safe_thread'

Да, это пока остаётся единственным обходным путём. Я беспокоюсь о внесении изменений в ядро, но, полагаю, если мы не исправим это, проблема будет продолжаться на гигантских форумах.

Недостаток — увеличение объёма хранилища.

1 лайк

Вы знаете, есть ли в сервисе post_actions (или где-то в процессе уведомлений) места, которые всё ещё ожидают целые числа после выполнения ALTER?

Мы наблюдаем ошибки 5xx при вызовах like/unlike для /post_actions с ответом:

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

Кроме того, есть сбои задач, связанных с уведомлениями (Jobs::BookmarkReminderNotifications, Jobs::GrantAnniversaryBadges, Jobs::PostAlert).

В моём предыдущем сообщении я добавил трассировку стека для PostAlert; похоже, что возникает ошибка, связанная с пределом целого числа, в методе consolidate_or_create в файле notification.rb.

Для нашего случая увеличение объёма хранилища не является большой проблемой, если мы сможем восстановить функциональность :crossed_fingers:

Попробуйте перезапустить контейнер — возможно, в памяти остались какие-то кэшированные данные.