Grande migrazione forum Drupal, errori e limitazioni dell'importatore

Oh… non avevo nemmeno pensato di eseguire l’importatore più di una volta sui dati di produzione. Grazie mille per quell’idea.

Quindi in pratica farei un dump del database Drupal di produzione ed eseguirei un’importazione completa per tutto il tempo necessario, lasciando il forum Drupal aperto al pubblico, poi metterei il forum Drupal in modalità offline, farei un altro dump del database e lo caricherei nell’istanza MySQL dell’importatore ed eseguirei nuovamente lo script dell’importatore?

L’unico svantaggio che vedo è che qualsiasi modifica di post Drupal, eliminazione di post o modifiche al profilo utente esistente durante quell’intervallo (chiamiamolo 3 giorni) dall’importazione iniziale fino alla seconda importazione non verrebbero importate, solo utenti e post completamente nuovi durante quell’intervallo, corretto?

Esatto. I dati modificati andranno persi. L’alternativa è mettere il forum offline per quel periodo. Potresti avvisare le persone. In pratica, nessuno si è lamentato.

1 Mi Piace

Fantastico, sembra un compromesso piuttosto ragionevole per ridurre al minimo i tempi di inattività. Grazie ancora per l’idea.

1 Mi Piace

Subito dopo essermi impegnato nell’ultima esecuzione di importazione di produzione, stavo controllando casualmente alcuni dei thread del forum importati quando ho scoperto un grosso problema. Come è stato il tema ricorrente qui, non è davvero colpa di Discourse o dello script di importazione. Ma si scopre che quando una risposta a un argomento (“commento” nel gergo di Drupal) viene modificata, a volte cambia il timestamp created. Per quanto ne so, dovrebbe invece cambiare il timestamp changed. Ma nonostante questo bug in Drupal, mantiene comunque l’ordinamento dei commenti. Ma il modo in cui lo script di importazione Drupal per Discourse funziona, apparentemente ordina le risposte in base al loro timestamp created (anche se non vedo clausole ORDER nello script drupal.rb). Dal mio test in phpMyAdmin sul database Drupal, sembra che sia sufficiente un ORDER BY c.cid ASC per mantenere il corretto ordine di concatenazione tramite l’ID del commento originale di Drupal cid, che è sequenziale e non cambia mai. Ma non sono sicuro se l’importatore Discourse consentirà a risposte sequenziali di avere date fuori ordine, e/o se procederà con il proprio ordinamento per data di pubblicazione? Vorrei avere l’opinione del creatore originale dell’importatore drupal.rb (e di chiunque altro, ovviamente), funzionerebbe e ci sarebbero conseguenze indesiderate?

Penso (ma non ne sono sicuro, il database di Drupal non ha senso per me) che tu possa modificare la query per recuperare la data di creazione dal post originale e non da quello modificato.

Penso che ci sia una tabella che contiene il post/ora originale e un’altra con le modifiche.

Penso che ordinare per cid non causerà alcun problema.

1 Mi Piace

Non ha davvero senso. Il problema è questo: le due righe evidenziate dovrebbero essere la seconda e la terza risposta nel thread, ma in Discourse si trovano da qualche parte dopo la 500esima posizione perché è lì che si trova il loro timestamp.

E naturalmente Drupal ha deciso di impostare created e changed allo stesso valore… E succede solo a volte, non riesco a riprodurlo modificando vecchi post. Ma ho lo stesso problema in più thread di lunga durata in cui l’autore del topic lo ha pubblicato e poi ha immediatamente pubblicato uno o due commenti di follow-up con “riservato” nel corpo per aggiungere informazioni in seguito, cosa che ha fatto diversi anni dopo.

Avrebbe senso, ma ecco lo stesso commento problematico modificato distribuito tra le due tabelle che utilizza:


1 Mi Piace

OK, sembra che questo funzioni, corregge i due thread confusi che ho trovato e non sembra danneggiare nient’altro.

  def import_replies

    batches(BATCH_SIZE) do |offset|
      results = mysql_query(<<-SQL
        SELECT c.cid, c.pid, c.nid, c.uid, c.created,
               f.comment_body_value body,
               f.comment_body_format format
          FROM comment c,
               field_data_comment_body f,
               node n
         WHERE c.cid = f.entity_id
           AND n.nid = c.nid
           AND c.status = 1
           AND n.type IN ('poll', 'forum')
           AND n.status = 1
           AND c.created > UNIX_TIMESTAMP(STR_TO_DATE('#{IMPORT_AFTER}', '%Y-%m-%d'))
         ORDER BY c.cid ASC  #<--- Corretto
         LIMIT #{BATCH_SIZE}
        OFFSET #{offset}
      SQL
      ).to_a
1 Mi Piace

Hmm, sembra che questo mi si sia ritorto contro. Poiché la funzione postprocess_posts sostituisce i vecchi link interni con il nuovo URL di Discourse, avevo fatto un’eccezione nel codice per i link https://web.archive.org/web/20230101093741/https://MyOldForum.com/node/98765 che il mio importer aveva creato per i vecchi sondaggi Drupal nella Wayback Machine. Ma apparentemente qualcosa è andato storto, perché ho appena notato nel sito di produzione migrato che i link sono finiti come https://web.archive.org/web/20230101093741/https://MyOldForum.com/t/-/12345.

Quindi, ora che non sono più nel contesto di un container di migrazione, il campo personalizzato con il nid originale del nodo Drupal è ancora disponibile nella tabella dei topic di Discourse? Se sì, sembrerebbe possibile eseguire una sostituzione di stringhe nella console Rails su tutti i topic con il primo post che contiene View this poll on the Wayback Machine e quindi sostituire
https://web.archive.org/web/20230101093741/https://MyOldForum.com/t/-/[01234567890]*
con
https://web.archive.org/web/20230101093741/http://MyOldForum.com/node/$original_nid

Ecco la mia funzione originale di importazione dei sondaggi:

    def import_poll_topics
    puts '', "importing poll topics"

    polls = mysql_query(<<-SQL
      SELECT n.nid nid, n.title title, n.uid uid, n.created created, n.sticky sticky, taxonomy_index.tid tid, node_counter.totalcount views
        FROM node n
        LEFT JOIN taxonomy_index ON n.nid = taxonomy_index.nid
        LEFT JOIN node_counter ON n.nid = node_counter.nid
       WHERE n.type = 'poll'
         AND n.status = 1
    SQL
    ).to_a

    create_posts(polls) do |topic|
      {
        id: "nid:#{topic['nid']}",
        user_id: user_id_from_imported_user_id(topic['uid']) || -1,
        category: category_id_from_imported_category_id(topic['tid']),
        # Use TEMPmyoldforum.com or else postprocess_posts() will try to convert the Wayback Machine /node/YYY link
        raw: "### View this poll on the Wayback Machine:\n**https://web.archive.org/web/20230101093741/http://TEMPmyoldforum.com/node/#{topic['nid']}**",
        created_at: Time.zone.at(topic['created']),
        pinned_at: topic['sticky'].to_i == 1 ? Time.zone.at(topic['created']) : nil,
        title: topic['title'].try(:strip),
        views: topic['views'],
        custom_fields: { import_id: "nid:#{topic['nid']}" }
      }
    end
  end

Sì.

t=Topic.find(1234)
t.custom_fields
t.custom_fields['import_id']
1 Mi Piace