Migrazione database vBulletin 5 - Errori script di importazione

Sì, lo farò se riuscirò a completare almeno l’importazione dell’utente. Attualmente sta esplodendo quando si tenta di lavorare sulle email

Rimuovi solo la prima riga dello script script/bulk_import/vbulletin5.rb
# frozen_string_literal: true

2 Mi Piace

Allora, eseguendo solo le prime tre funzioni:

 def execute
    # abilitare secondo i requisiti:
    #SiteSetting.automatic_backups_enabled = false
    #SiteSetting.disable_emails = "non-staff"
    #SiteSetting.authorized_extensions = '*'
    #SiteSetting.max_image_size_kb = 102400
    #SiteSetting.max_attachment_size_kb = 102400
    #SiteSetting.clean_up_uploads = false
    #SiteSetting.clean_orphan_uploads_grace_period_hours = 43200
    #SiteSetting.max_category_nesting = 3

    import_groups
    import_users
    import_group_users

    #import_user_emails
    #import_user_stats
    #import_user_profiles
    #import_user_account_id

    #import_categories
    #import_topics
    #import_topic_first_posts
    #import_replies

    #import_likes

    #import_private_topics
    #import_topic_allowed_users
    #import_private_first_posts
    #import_private_replies

    #create_oauth_records
    #create_permalinks
    #import_attachments
  end

Risultato:

Presumo che quel messaggio sulla garanzia di coerenza sia inteso per quando viene completata l’importazione completa? O dovrei eseguirlo ad ogni “passaggio” che eseguo e poi fare una copia della directory discourse dall’host per avere un backup?

1 Mi Piace

Rilanciarlo con le prossime 4 funzioni attive restituisce un errore per ID già esistenti

Può essere un “tutto o niente”? Forse si aspetta che tutto venga fatto in un’unica grande transazione?

Riprova. Il processo è andato avanti per un po’ di tempo, poi all’improvviso questo.

La parte frustrante è che sembra essere successo all’improvviso.
Ora avviarlo di nuovo genera questo errore.

Sono troppo stanco ora per controllare a cosa si riferisce. Soprattutto perché duplicate key value non dovrebbe davvero accadere se avessi semplicemente riavviato lo script di importazione massiva, giusto?

Mi scuso innanzitutto con chiunque si senta attaccato da questo post perché, ad essere sincero, è da lunedì che mi districo con questi problemi e a questo punto sono stanco di fare debug/hotfix per il codice di Discourse.

Dopo l’ennesimo tentativo (smetto di contare dopo il settimo) penso che mi arrenderò perché sembra che la migrazione non sia qualcosa su cui Discourse abbia investito molto tempo per supportarla.

Credo che il problema più grande sia che il charset utilizzato in questo enorme database sia utf8mb4, che non è supportato dallo script (?).

Usare utf8 (predefinito) genera semplicemente molti errori che vengono segnalati ma non è chiaro cosa stia succedendo poiché lo script va avanti comunque. La voce nel DB viene saltata? Copiata con caratteri non supportati (i classici quadratini)?

Inoltre, le tre diverse ultime esecuzioni (utilizzando gli importatori di massa), seguendo esattamente le stesse istruzioni, hanno risultati diversi. Quest’ultima esecuzione ha raggiunto l’importazione degli argomenti, ha iniziato immediatamente a segnalare errori ma è andata avanti (???):

Caricamento applicazione...
Avvio...
Precaricamento I18n...
Correzione numeri post più alti...
Caricamento ID gruppi importati...
Caricamento ID utenti importati...
Caricamento ID categorie importate...
Caricamento ID argomenti importati...
Caricamento ID post importati...
Caricamento indici gruppi...
Caricamento indici utenti...
Caricamento indici categorie...
Caricamento indici argomenti...
Caricamento indici post...
Caricamento indici azioni post...
Importazione categorie...
Importazione categorie padre...
      5 -   1104/secERRORE: violazione del vincolo di univocità della chiave "unique_index_categories_on_name"
DETTAGLIO: La chiave (COALESCE(parent_category_id, '-1'::integer), name)=(-1, Armata Brancaleone) esiste già.
CONTESTO: COPY categories, riga 69
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:204:in `get_last_result'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:204:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:720:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:361:in `create_categories'
script/bulk_import/vbulletin5.rb:291:in `import_categories'
script/bulk_import/vbulletin5.rb:69:in `execute'
/var/www/discourse/script/bulk_import/base.rb:98:in `run'
script/bulk_import/vbulletin5.rb:779:in `<main>'
Importazione argomenti...
    600 -   4073/sec
ERRORE: metodo non definito `[]' per nil:NilClass
/var/www/discourse/script/bulk_import/base.rb:513:in `process_topic'
/var/www/discourse/script/bulk_import/base.rb:724:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:721:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:720:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:364:in `create_topics'
script/bulk_import/vbulletin5.rb:321:in `import_topics'
script/bulk_import/vbulletin5.rb:70:in `execute'
/var/www/discourse/script/bulk_import/base.rb:98:in `run'
script/bulk_import/vbulletin5.rb:779:in `<main>'

Fino a quando finalmente non si blocca con questo:

script/bulk_import/vbulletin5.rb:779:in `<main>'
 572329 -    531/sec
Importazione risposte...
client_loop: send disconnect: Connection reset

Ma non prima di aver spammato quasi costantemente questi due errori:

ERRORE: metodo non definito `gsub!' per nil:NilClass
script/bulk_import/vbulletin5.rb:727:in `preprocess_raw'
script/bulk_import/vbulletin5.rb:369:in `block in import_topic_first_posts'
/var/www/discourse/script/bulk_import/base.rb:723:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:721:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:720:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:367:in `create_posts'
script/bulk_import/vbulletin5.rb:361:in `import_topic_first_posts'
script/bulk_import/vbulletin5.rb:71:in `execute'
/var/www/discourse/script/bulk_import/base.rb:98:in `run'
script/bulk_import/vbulletin5.rb:779:in `<main>'

e

ERRORE: sequenza di byte non valida in UTF-8
script/bulk_import/vbulletin5.rb:727:in `gsub!'
script/bulk_import/vbulletin5.rb:727:in `preprocess_raw'
script/bulk_import/vbulletin5.rb:369:in `block in import_topic_first_posts'
/var/www/discourse/script/bulk_import/base.rb:723:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:721:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:720:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:367:in `create_posts'
script/bulk_import/vbulletin5.rb:361:in `import_topic_first_posts'
script/bulk_import/vbulletin5.rb:71:in `execute'
/var/www/discourse/script/bulk_import/base.rb:98:in `run'
script/bulk_import/vbulletin5.rb:779:in `<main>'

Si noti che sono andato passo dopo passo commentando quale funzione eseguire, quindi eseguendo rake import:ensure_consistency prima di continuare commentando quelle che erano appena state eseguite e così via, perché se lasciassi semplicemente l’intero script rieseguire i passaggi precedenti, si bloccherebbe semplicemente trovando ID duplicati.

Prima che esca il solito argomento “non puoi lamentarti del software gratuito”, voglio chiarire che contribuisco ad altri progetti open source e realizzo software gratuitamente anch’io, ma per me è fondamentale che se rilascio qualcosa, quella cosa funzioni e sia ben documentata (anche solo per evitare le migliaia di messaggi che chiedono giustamente “come funziona”) o sono pronto a correggere qualsiasi bug emerga.

Mentre Discourse sembra offrire un’ottima esperienza “out-of-the-box”, dovrebbe essere chiaro che siamo nel 2022 e le comunità sono esistite molto prima di questo prodotto. L’“adozione” richiederebbe un forte supporto alla migrazione e non sembra essere lo stato attuale per Discourse.

Riconosco che un database da 20 GB sia un caso limite, ma non abbiamo problemi con la dimensione qui, piuttosto con il charset o chissà cos’altro, dato che non c’è nemmeno un errore costante e la maggior parte delle volte: non c’è documentazione oltre a dover cercare thread e post lasciati da chi ha attraversato la stessa odissea in passato, sperando che sia stata trovata una soluzione e che il codice sorgente non sia cambiato molto da allora.

A questo punto raccomanderei vivamente a chiunque provenga da vBulletin di sospendere qualsiasi migrazione fino a quando non sarà completato quello che sembra essere un rifacimento dello script di migrazione (in corso, a quanto pare?).

Mentre capisco il tuo problema (le migrazioni sono un argomento difficile), come Specialista delle Migrazioni per Discourse, lasciami chiarire le cose.

Abbiamo un framework di migrazione maturo con oltre 60 script per diverse piattaforme, un framework separato per importazioni massive con 5 script e un nuovo framework in fase di sviluppo che migliora enormemente ogni aspetto: prestazioni, organizzazione del codice, testabilità, verificabilità, documentazione e così via.

Abbiamo un team separato per le Migrazioni con un ampio supporto da parte degli sviluppatori principali e contribuiamo con miglioramenti generici al codice con ogni migrazione che completiamo. Stiamo costantemente eseguendo migrazioni per clienti che vanno da quelle banali a quelle incredibilmente complesse.

Il nostro obiettivo finale è rendere le migrazioni il più agevoli possibile sia per i clienti ospitati che per la community, ma la quantità di codice che rientra nell’ambito durante una migrazione è semplicemente troppo vasta, e la configurazione del software a livello di sistema, le modifiche al software di terze parti e la variabilità dei dati di input non fanno che aggravare il problema.

Ancora una volta, vorrei che tutte queste cose fossero più semplici, ma renderle tali richiede innumerevoli ore di lavoro per creare e mantenere, e ce ne sono solo un numero limitato da dedicare.

Non arrenderti! :slight_smile:

5 Mi Piace

Apprezzo e capisco che l’ambito sia immenso. È solo frustrante continuare a inciampare in un’eccezione dopo l’altra e il fatto che il progetto sia scritto in ruby non aiuta a trovare aiuto se non venendo qui, il che, come dici tu, non può assolutamente soddisfare tutte le richieste di aiuto poiché alcuni hanno casi molto specifici per i quali è semplicemente impossibile aiutare senza avere accesso ai dati effettivi.

Inoltre, in gran parte, attribuisco la colpa all’assoluto caos che è la struttura di vbulletin.

Ho appena controllato stamattina e questo è un riepilogo delle dimensioni delle tabelle.

Per dare un contesto, la tabella “text” è dove si trova il contenuto effettivo.
la tabella node contiene la gerarchia e closure… lasciami citare qui perché non ci credo nemmeno:

La tabella Closure costruisce le relazioni padre-figlio tra tutti i nodi. La maggior parte del tuo database è costituita da file allegati che non dovrebbero essere archiviati nel database.

Quindi, nel complesso, per un forum con circa 8 GB di contenuto, c’è un overhead di 28 GB. Ottimo lavoro, congratulazioni vbulletin.

2 Mi Piace

È questo che intendo quando dico che è frustrante.

Di nuovo, stesso insieme di azioni (seguendo un runbook scritto da me con tutti i tentativi ed errori), in esecuzione su una nuova installazione di discourse.

Risultato:

Tired Tv Land GIF by TV Land Classic

Dove sei import_user_account_id? :expressionless:
Ma soprattutto? Come sei riuscito a non causare un errore nell’esecuzione precedente in cui si è bloccato sull’importazione dell’argomento? :confounded:

Commentando l’invocazione di quella funzione (che sembrava comunque importante) e riavviando:

Quelli errori di chiavi duplicate… lo script non dovrebbe sapere che ha già elaborato quegli ID e andare avanti?

Ogni importazione è diversa. Si potrebbe pensare che uno script che funziona per un’istanza di il-tuo-forum-preferito-in-precedenza funzioni semplicemente, ma non è così. E per un forum enorme, è davvero difficile. Semplicemente non è qualcosa che sia facile da supportare. E gli importatori di massa accedono direttamente al database piuttosto che fare affidamento su Rails per essere in grado di controllare automaticamente le cose man mano che procedono.

Questo è un problema non raro, e non è colpa dello script. Dovrai capire come spostare il tuo vecchio database in utf8.

C’è un forte supporto alla migrazione. Semplicemente non c’è supporto alla migrazione gratuito. Ho effettuato circa 100 migrazioni e scritto diversi script di importazione per sistemi non supportati o personalizzati. Probabilmente addebiterei $3000-5000 per importare il tuo database. Questa non è un’offerta, è solo per darti un’idea di quanto lavoro ci sia per qualcuno che l’ha fatto un bel po’ di volte. Sospetto che se pagassi un anno di hosting Business, CDCK lo farebbe gratuitamente, il che potrebbe essere meno di quanto addebiterei per farlo. (Oh, ma potresti non essere idoneo per l’hosting Business con un database di queste dimensioni).

1 Mi Piace

Continuo la mia esplorazione qui.

  • Lo script fa riferimento a una funzione che non esiste: import_user_account_id. Voi (sviluppatori di Discourse) potreste volerlo correggere.
  • La logica che controlla i titoli degli argomenti sta impazzendo per alcuni argomenti che per qualche motivo hanno una stringa vuota come titolo. Per quanto ciò non dovrebbe accadere, il controllo che lo valuta dovrebbe intercettarlo e restituire nil ma apparentemente ciò interrompe la logica successiva scritta nell’import (vedi qui).

Ho avuto quel problema con un’importazione che ho fatto di recente. Sarebbe meglio se restituisse qualcosa come “l’argomento XXX non ha un titolo” o estraesse la prima riga di testo dal post, ma è difficile farlo in questo contesto. Penso che sarei tentato di risolverlo modificando il tuo database e usando qualcos’altro per generare titoli dove mancano.

Sì, sto fondamentalmente “pulendo” il db quando trovo questi problemi, ma è difficile perché devo eseguire il debug dello script e poi indovinare cosa sta causando il problema ogni volta :sweat_smile:

Ancora nessuna idea sulla funzione mancante import_user_account_id :expressionless:

Soprattutto considerando che le vacanze si avvicinano molto presto, è improbabile che qualcuno risolva il problema a meno che non stia usando lo script da solo. (Di solito, quando dico questo, Richard interviene e salva la situazione.)

2 Mi Piace

LOL, beh, immagino che oggi ti deluderò. Ci ho provato, ma sospetto che il commit di questo importatore fosse incompleto e non includesse alcune modifiche a base.rb. @justin ci ha lavorato, forse lo sa lui. Sospetto che questa potesse essere una cosa specifica del cliente che può essere commentata senza ulteriori conseguenze.

Non ho mai usato nemmeno io gli importatori di massa.

Sì, gli script di importazione possono essere complessi e dipendere dalle specificità del database, ma alcuni script semplicemente non sono in uno stato funzionante. Questo vale anche per questo, e ci sono altri script con, ad esempio, # frozen_string_literal: true che semplicemente non funzionano subito.

2 Mi Piace

Ah!

Questo è (almeno)

parte del motivo per cui trovo così difficile inviare PR per le modifiche che apporto. Quando ho finito, c’è così tanto materiale specifico per il caso che temo che qualsiasi cosa invii sarà in qualche modo rotta.

Sì. Penso che qualcosa sia passato e abbia aggiunto frozen_string_literal a ogni file. La maggior parte dei file è stata corretta perché aveva test, ma non ci sono test per gli script di importazione.

2 Mi Piace

Ehi, giusto per chiarire, non mi aspetto che qualcuno risolva questo problema ora (stile Karen). Sto solo segnalando alcune cose che chiaramente presentano dei problemi nel codebase stesso e probabilmente sono solo “ops, ho dimenticato di aggiungere questa modifica al commit! :sweat_smile:”.

Ho già accettato che questa migrazione non avverrà prima di gennaio, almeno, a questo punto.

Tutti dovrebbero semplicemente godersi le vacanze :slight_smile:
Solleverò la questione o aprirò un nuovo thread dopo le vacanze, anche se avrò decisamente meno tempo da dedicare a questa migrazione :frowning:

2 Mi Piace

Sí, totalmente cierto: para las importaciones, normalmente no envío una PR antes de haber realizado dos importaciones de diferentes clientes.

1 Mi Piace

Sto solo tenendo aggiornato questo.

Ho apportato alcune modifiche a base.rb dopo averne discusso con altri ingegneri della nostra community. Molti errori erano causati da gsub! che generava errori perché apparentemente avevamo alcuni argomenti con '' come titolo.

Abbiamo aggiunto una funzione che imita la funzione normalize_text che restituisce semplicemente l’imported_id del thread se non c’è contenuto, convertito in stringa.

  def normalize_text_thread(text, imported_id)
    return imported_id.to_s unless text.present?
    @html_entities.decode(normalize_charset(text.presence || "").scrub)
  end

Quindi in vbulletin5.rb ho modificato la riga in create_topic in:

create_topics(topics) do |row|
      created_at = Time.zone.at(row[5])

      title = normalize_text_thread(row[1], row[0])

Questo ha eliminato il problema. Fondamentalmente gsub! non gestisce bene l’input nil.

Tuttavia, questo ha fatto proseguire lo script ma quando ha raggiunto import_private_topics si è bloccato lì. Ci sono 253.427 argomenti privati (pm) nel nostro DB che sono diversi ordini di grandezza inferiori alle risposte. Dopo 9 ore ho interrotto lo script per vedere cosa stava succedendo.

Avviando l’interfaccia ho notato un paio di cose.

  1. Il mio account non è stato importato perché l’utente admin creato utilizzava la stessa email, suppongo. Ovvio ma qualcosa che dovrebbe essere scritto da qualche parte forse?
  2. Solo alcune delle categorie (sottoforum vbulletin) sono state importate
  3. Sono stati importati solo gli argomenti e la loro prima risposta (non sono sicuro se davvero tutti) e sono stati importati tutti senza essere nelle categorie corrette, anche quelli che avevano una categoria che sarebbe stata creata. Tutto viene importato “senza categoria”.
  4. Il “contatore delle risposte” mostra -1, probabilmente perché le risposte non sono state importate affatto.

Aggiungerò nel complesso, MOLTI problemi con questo importatore di massa sparirebbero se implementasse un approccio di paginazione. Penso che le risposte siano andate perse perché lo script ha cercato di passarle tutte in una volta e con 7 GB di dati era impossibile. Mi stupisce che un importatore di massa non approcci l’importazione con un approccio di paginazione, ad essere onesti. Anche solo prendere 1000 record alla volta, scriverli e memorizzare l’ultimo ID del record scritto e ripetere il ciclo risolverebbe qualsiasi problema con i database di grandi dimensioni.

1 Mi Piace

FWIW, sto seguendo con interesse e apprezzo molto gli aggiornamenti. :pray: Non so molto sulle migrazioni finora, ma trovo questo molto informativo.

4 Mi Piace