Solución al error “Record is too big” que aborta el reindexado de publicaciones en Algolia
Me encontré con un problema en el que Algolia solo contenía una pequeña parte de las publicaciones de mi foro. Al ejecutar el reindexado de publicaciones, se reveló la causa:
Algolia::AlgoliaHttpError:
Record at the position 258 objectID=1006 is too big:
size: 108426 byte(s), maximum allowed: 10000 byte(s).
En la versión del plugin que tengo instalada, PostIndexer#to_object envía todo el texto plano de la publicación como un único registro sin comprobar el tamaño de este una vez serializado. Un registro de tamaño excesivo provocaba que la tarea de reindexado se abortara.
La siguiente solución temporal local permitió que el reindexado se completara.
Qué hace este parche
El parche limita cada registro de publicación serializado completo a 9.500 bytes, dejando un margen por debajo del límite de 10.000 bytes reportado por Algolia.
Esto:
-
Incluye los metadatos y el escapado JSON en el cálculo del tamaño.
-
Trunca solo el content enviado a Algolia.
-
Deja la publicación original de Discourse intacta.
-
Mantiene los IDs de objeto existentes y la estructura de un registro por publicación.
El compromiso es que el texto omitido al final de una publicación larga no será buscable a través de Algolia. Esto es truncamiento, no fragmentación del documento.
Parche
En:
plugins/discourse-algolia/lib/discourse_algolia/post_indexer.rb
Busca el return final en to_object, inmediatamente después de que se añadan los metadatos de categoría opcionales:
object
end
Reemplaza esa sección con:
# Limitar el registro serializado completo, no solo su contenido.
algolia_record_budget = 9_500
if object.to_json.bytesize > algolia_record_budget
full_content = object[:content]
object[:content] = ""
if object.to_json.bytesize > algolia_record_budget
raise "Algolia metadata alone exceeds the record budget for post #{post.id}"
end
low = 0
high = full_content.length
best_content = ""
while low <= high
midpoint = (low + high) / 2
object[:content] = full_content[0, midpoint]
if object.to_json.bytesize <= algolia_record_budget
best_content = object[:content]
low = midpoint + 1
else
high = midpoint - 1
end
end
object[:content] = best_content
end
object
end
La búsqueda binaria encuentra un prefijo del contenido que se ajusta al límite de bytes tras la serialización JSON. Si los metadatos por sí solos superan el límite, el parche lanza un error explícito en lugar de descartar los metadatos silenciosamente.
Haz una copia de seguridad del archivo antes de editarlo. Este parche está destinado a la versión donde to_object devuelve un único hash que contiene content; revísalo contra tu versión instalada antes de aplicarlo.
Validar y reindexar
Para una instalación estándar de Docker, entra en el contenedor desde el host:
cd /var/discourse
./launcher enter app
Cambia al usuario Discourse:
su - discourse
Una vez que aparezca el prompt del usuario discourse, ejecuta:
cd /var/www/discourse
ruby -c plugins/discourse-algolia/lib/discourse_algolia/post_indexer.rb
Si esto reporta Syntax OK, ejecuta:
RAILS_ENV=production LOAD_PLUGINS=1 bundle exec rails algolia:reindex_posts
Esta tarea borra y repuebla el índice de publicaciones. En mi caso, se completó con éxito tras aplicar el parche.
Los procesos de la aplicación/trabajadores en segundo plano ya en ejecución también necesitan reiniciarse para utilizar el código parcheado en el indexado continuo.
Otro detalle a tener en cuenta: el recuento de publicaciones informado
La tarea informó:
Successfully pushed 723 posts to Algolia
But Algolia contained 272 records.
Pero Algolia contenía 272 registros.
En mi versión instalada, la tarea incrementa su contador antes de llamar al filtro de visibilidad del indexador. Un diagnóstico utilizando el mismo indexador confirmó:
Posts examined: 723
Eligible for indexing: 272
Excluded by visibility: 451
Por lo tanto, el mensaje de éxito cuenta las publicaciones examinadas, no necesariamente los registros subidos. Esta discrepancia era independiente del error de registro de tamaño excesivo.