Hola, mi grupo de locos idiotas y yo estamos muy cerca de migrar finalmente nuestro foro de Vbulletin3 a Discourse después de haber escrito un script ad-hoc que finalmente logra migrar las 21 millones de respuestas de la base de datos original a Discourse.
Ahora, tenemos el problema de los enlaces a los temas/respuestas escritos en las propias respuestas.
En la migración que hemos escrito, creamos un mapeo de los IDs de los temas/respuestas “antiguos” y a qué se mapean en Discourse.
Por ejemplo:
id | topic_id | name | value | created_at | updated_at
--------+----------+-----------+--------+----------------------------+----------------------------
581727 | 581736 | import_id | 599137 | 2023-02-08 16:30:01.600759 | 2023-02-08 16:30:01.600759
Lo que estaba pensando ahora es en un plugin que simplemente intercepte los enlaces al formato del foro antiguo y los transforme con referencia al nuevo hilo/respuesta.
Desencadenaría una búsqueda en la tabla topics_custom_field usando el valor 123456, encontraría el topic_id de Discourse, luego consultaría la tabla topic_links con ese ID y encontraría la url. Finalmente, lo reemplazaría en la publicación del lado del cliente (asumiendo JS para manipular el contenido).
Algo similar para las publicaciones.
Sin embargo, no encuentro ningún buen ejemplo de cómo empezar a crear algo así para Discourse.
¿Alguien puede darme alguna pista, ejemplo o plugins que hagan algo similar (comprobar respuestas en busca de alguna subcadena y reemplazarla, consultar la API? ¿la base de datos? para obtener un valor a partir de otro?).
Solo para confirmar, ¿debería ejecutar esta lógica después de que la migración se haya completado?
Así que recorre todas las respuestas de nuevo y cambia los permalinks.
Cuando migramos el contenido de una respuesta con, por ejemplo: https://oldforum.something.com/showthread.php?t=123456 no sabe qué id tendrá ese tema en Discourse… ¿no?
Desafortunadamente, no podemos usar ese código porque la importación tarda una eternidad en importar 20 millones de publicaciones y la importación masiva simplemente no funciona. Faltan piezas.
Es por eso que tuvimos que escribir nuestro propio script de migración. Hace todo (pm, usuarios, grupos de usuarios, categorías, temas, respuestas) en aproximadamente 6 horas con 4 núcleos y 8 GB de RAM, pero notamos que nos faltaban los permalinks
Intentamos evitar procesar de nuevo las más de 20 millones de respuestas, pero nos dimos cuenta de que las soluciones alternativas (plugin, redirección nginx, etc.) serían bastante complicadas o dependerían de factores externos que la convertirían en una solución a medias, así que simplemente volveremos a procesar las respuestas y gestionaremos los permalinks. Añadirá algo de tiempo a la migración, pero esperemos que no demasiado.
Todo lo demás está “cocinado” sobre la marcha, ya que sabemos qué “crudo” debe convertirse a HTML.
Para los permalinks no podemos hacer eso, ya que si se añade un permalink con una edición, podría hacer referencia a un tema que aún no ha sido procesado (ID de tema superior) y que no se encuentra en la tabla topics_custom_field en el momento de su procesamiento.
Los temas y todas sus respuestas se importan siguiendo los IDs de tema de menor a mayor en la base de datos de vbulletin. Eso también significa que estamos importando en orden cronológico.
Sin embargo, eso llevaría a pensar que si alguna vez encuentras una referencia a otro tema, siempre será para uno que ya existía.
Pero hay casos en los que esto no es cierto, solo un par de ejemplos:
Tema dividido con un comentario que llevó a la división. La división sería con un ID que es mayor pero existe en un tema con un ID menor.
Edición para lectores futuros en la que las publicaciones de temas antiguos hacen referencia a temas más recientes.
Así que, sí, mientras que topic_custom_field se genera y se completa a medida que avanza la importación, como se explicó en el primer tema, no es fiable hacerlo “sobre la marcha” porque no puedes estar seguro de encontrar siempre la correspondencia correcta entre los IDs.
Se necesita otro pase después de que la importación completa haya terminado.
Sobre TopicCustomField.each do |tcf|, no estoy seguro de lo que haría la parte tcf. Ruby no es un idioma que haya aprendido. Nuestro script está escrito en C# ya que la mayoría de las personas que se ofrecieron a trabajar con él, ya lo usan en el trabajo.