Error: entero fuera de rango

Estoy obteniendo este error con frecuencia en Sidekiq (listas de Reintentos y Muertos):

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

Los trabajos para los que he notado este error idéntico son:
Jobs::PostAlert
Jobs::ProcessPost
Jobs::NotifyCategoryChange

Esto se discutió un poco en el pasado aquí: Feedback on the new Review Queue (2019) - #250 by markersocial

2 Me gusta

¿Puedes ejecutar lo siguiente:

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 Me gusta

Gracias @Falco, acabo de ejecutarlo ahora. Aquí está el resultado:

-[ REGISTRO 1 ]--
id | 2147483496
4 Me gusta

Vale, así que es el famoso problema del máximo entero. Necesitamos pasar a bigint para solucionarlo. Lo revisaré.

6 Me gusta

Por ahora, tu solución temporal es ejecutar:

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

Esto es lo predeterminado para las instalaciones nuevas, pero las instalaciones antiguas tienen el tipo de dato incorrecto.

Ejecutar la solución temporal puede ser difícil porque bloqueará la tabla; es posible que necesites reducir primero la carga de tu servidor web.

2 Me gusta

Gracias @Falco & @sam, lo aprecio :slight_smile:

En cuanto al procedimiento alternativo, ¿crees que debería ser relativamente seguro hacerlo? No me preocupa la caída del servicio, solo romper algo.

Está utilizando el contenedor único estándar de app.yml. Para aliviar la carga web, ¿crees que usar el modo de solo lectura y ejecutar ./launcher stop app, ./launcher start app antes de aplicar el procedimiento alternativo sería suficiente?

No romperá nada; en el peor de los casos, simplemente quedará “atascado” durante mucho tiempo.

2 Me gusta

Gracias, Sam, apliqué el procedimiento alternativo. Sin embargo, no recibí ningún feedback al ejecutar:

ALTER TABLE notifications ALTER COLUMN id SET DATA TYPE bigint

No estoy seguro de si aún está procesándose. Actualmente, obtengo el mismo error (en la lista de trabajos muertos de /sidekiq, para los últimos intentos de ‘hace un momento’) para:

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

Parece que también necesitas ejecutarlo con la columna post_id.

1 me gusta

¡Gracias! :slight_smile:

Solo para asegurarnos, ¿esto se ve correcto?

ALTER TABLE notifications ALTER COLUMN post_id SET DATA TYPE bigint

Sí, eso debería ser seguro; una vez que añadamos una migración oficial, lo permitirá.

1 me gusta

Perfecto, gracias :slight_smile:

Ejecuté eso (no recibí confirmación ni retroalimentación, como con el anterior). El foro no se ralentizó, así que no estoy seguro de si funcionó. Actualmente estoy obteniendo los mismos errores.

Quizás lo mejor sea que espere a la migración oficial.

1 me gusta

Sí, parece que esto está en la tabla post_alerts; necesitamos revisar muchas tablas.

1 me gusta

¿Tienes curiosidad sobre dónde te encuentras ahora con este tema? ¿Han cesado los errores?

Originalmente, estábamos pensando en realizar alguna migración oficial aquí, pero el riesgo supera con mucho el beneficio. Encontramos extremadamente raro toparnos con bases de datos que tengan más de 2.147.483.647 publicaciones. 2,1 mil millones es un número realmente grande.

La desventaja de aumentar el tamaño en todas partes es que aumentan los requisitos de almacenamiento.

En lo que respecta a nuestra situación actual, estamos considerando agregar una tarea rake que “haga espacio” si te encuentras en un caso atípico donde tienes tablas en Discourse que contienen 2 mil millones de filas (o que tuvieron 2 mil millones de filas de cambios).

1 me gusta

Gracias por el seguimiento, @sam.

Acabo de actualizar a la versión 2.8.0.beta6 y aún tengo errores de entero fuera de rango.

Creo que se debe a que las notificaciones han alcanzado un número masivo, lo cual es más realista para llegar al límite en comparación con la cantidad de publicaciones. Muchos temas grandes con numerosas respuestas, me gusta, etc., de diferentes usuarios pueden generar una gran cantidad de notificaciones.

Una tarea de rake suena fantástica :slight_smile:

Sé que este es un hilo antiguo –

Acabamos de encontrar este problema en nuestra configuración también (devforum.roblox.com). Estamos ejecutando la v2.8.9, pero pronto actualizaremos a la 3.0.1.

Notamos que algo andaba mal cuando los usuarios comenzaron a ver 403/500 al intentar dar “me gusta” o “no me gusta” a las publicaciones.

Luego me encontré con este hilo y revisé nuestra tabla de notificaciones:

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

@sam ¿Sigue siendo la solución alternativa anterior la mejor sugerencia, o se consideró más un rake task desde septiembre de 2021?

Más información –

Después de modificar la columna notifications.id, estoy viendo un problema separado con el trabajo Jobs::PostAlert

Job exception: 2147498514 está fuera de rango para ActiveModel::Type::Integer con límite de 4 bytes

¿Quizás hay otra tabla/columna que me estoy perdiendo? ¿O algún lugar en ruby que todavía esté esperando el tipo de dato entero?

backtrace
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'

/app/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'

Sí, esta sigue siendo la única solución aquí. Me preocupa cambiarlo en el núcleo, pero supongo que esto seguirá sucediendo en foros gigantescos si no lo solucionamos.
La desventaja es el aumento del almacenamiento.

1 me gusta

¿Sabes si hay algún uso en el servicio post_actions (o en algún lugar del proceso de notificación) que todavía pueda estar esperando enteros después de ejecutar ALTER?

Estamos viendo errores 5xx en las llamadas de “me gusta”/“no me gusta” a /post_actions con la respuesta

{"errors":["No se pudo encontrar la URL o el recurso solicitado."],"error_type":"not_found"}

Además, algunas de las fallas de trabajos en torno a las notificaciones (Jobs::BookmarkReminderNotifications, Jobs::GrantAnniversaryBadges, Jobs::PostAlert).

Agregué el rastreo de pila para PostAlert en mi mensaje anterior; parece que hay un problema que se lanza por un límite de enteros en consolidate_or_create en notification.rb.

Para nuestro uso, el aumento del almacenamiento no es una gran preocupación si podemos restaurar la funcionalidad :crossed_fingers:

Quizás intenta reiniciar su contenedor, podría haber algo en caché en la memoria.