Strano errore di migrazione nei test durante il workflow GH

Sto cercando di creare una relazione di chiave esterna con la tabella Topics.

Il problema è che fallisce nell’ambiente di test del workflow di GitHub durante i test per la ragione più strana, sta cercando di accedere a un campo della tabella padre che non esiste più ed è stato rimosso in una migrazione principale anni fa!

L’errore è PG::UndefinedColumn: ERROR: column topics.off_topic_count does not exist

beh sì, perché è stato rimosso in una migrazione principale nel 2018!

Ho confermato che questo è già stato eseguito durante il processo di test:

== 20180917024729 RemoveSuperfluousColumns: migrating =========================
== 20180917024729 RemoveSuperfluousColumns: migrated (0.0410s) ===============

Non sto in alcun modo facendo riferimento esplicitamente a questo vecchio campo della tabella padre… sembra che stia generando l’SQL da solo… ma in modo inappropriato per la definizione attuale delle cose.

== 20231119010101 CreateLocationsTopicTable: migrating ========================rake aborted!

[12035](https://github.com/paviliondev/discourse-locations/actions/runs/7039607316/job/19158951878?pr=103#step:19:12036)StandardError: An error has occurred, this and all later migrations canceled: (StandardError)

[12036](https://github.com/paviliondev/discourse-locations/actions/runs/7039607316/job/19158951878?pr=103#step:19:12037)

[12037](https://github.com/paviliondev/discourse-locations/actions/runs/7039607316/job/19158951878?pr=103#step:19:12038)PG::UndefinedColumn: ERROR: column topics.off_topic_count does not exist

[12038](https://github.com/paviliondev/discourse-locations/actions/runs/7039607316/job/19158951878?pr=103#step:19:12039)LINE 1: ...cs"."deleted_at", "topics"."highest_post_number", "topics"...

La definizione della tabella è molto semplice:

class CreateLocationsTopicTable < ActiveRecord::Migration[7.0]
  def change
    create_table :locations_topic do |t|
      t.references :topic, foreign_key: true
      t.float :latitude, null: false

SNIP

La parte ancora più strana è che questa migrazione funziona in Produzione!

Qualsiasi intuizione è molto apprezzata!

1 Mi Piace

Oh, sono stato ben “RUBOCOPPED” per questo :policeman: :police_car:

Offenses:

db/migrate/20231119010101_create_locations_topic_table.rb:6:7: C: Discourse/NoAddReferenceOrAliasesActiveRecordMigration: I metodi AR add_reference, add_belongs_to, t.references e t.belongs_to sono ad alto rischio per tabelle di grandi dimensioni e hanno troppe operazioni magiche in background.
Invece, scrivi una migrazione disable_ddl_transactions! e scrivi SQL personalizzato per aggiungere la nuova colonna e CREATE INDEX CONCURRENTLY. Usa la clausola IF NOT EXISTS per rendere la migrazione rieseguibile se fallisce a metà.

      t.references :topic, foreign_key: true
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ora quello potrebbe essere parte del problema.

Troppa :magic_wand: in corso, questo è il problema!

Si impara vivendo! :mortar_board:

1 Mi Piace

Il consiglio di Rubocop è buono, ma non credo che sia la causa di questo errore. (il ‘rischio’ a cui si riferisce riguarda i lock su tabelle ad alto traffico che influirebbero sul traffico di produzione. Quindi non qualcosa che causerebbe errori in un ambiente di test)

Probabilmente puoi riprodurre lo stesso errore localmente eseguendo RAILS_ENV=test bin/rake db:drop db:create db:migrate (cioè, migrando un database completamente da zero, con il plugin locations abilitato)

Sospetto che il problema sia che stai invocando task Rake all’interno di una migrazione. Nel core generalmente evitiamo di eseguire qualsiasi tipo di codice applicativo nelle migrazioni a causa degli strani effetti collaterali che possono verificarsi. È meglio attenersi a SQL puro.

In questo caso, la mia ipotesi è che la cache dello schema di ActiveRecord venga popolata all’inizio delle migrazioni (quando topics.off_topic_count esiste ancora). Quindi, quando il tuo task Rake viene eseguito, viene eseguito con una vecchia cache dello schema e quindi ActiveRecord tenta di caricare colonne che non esistono più.

Probabilmente puoi mitigare aggiungendo ActiveRecord::Base.clear_cache! prima di invocare i task Rake… ma non prenderlo come una raccomandazione :wink:. La cosa migliore sarebbe evitare del tutto di invocare i task Rake. Se devi manipolare qualcosa nel database, usa SQL puro all’interno della migrazione.

2 Mi Piace

Grazie David, lo sposterò in un’istruzione SQL e vedrò se questo risolve…

Ci è riuscito, grazie David!

2 Mi Piace

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.