GH 工作流测试中出现奇怪的迁移错误

我正在尝试创建一个与 Topics 表的外键关系。

问题是,在 GitHub 工作流测试环境中,测试因奇怪的原因而失败,它试图访问父表中一个早已不存在且在几年前的核心迁移中已被删除的字段!

错误是 PG::UndefinedColumn: ERROR: column topics.off_topic_count does not exist

是的,因为它在 2018 年的核心迁移中被删除了

我已确认这在测试过程中已经运行:

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

我并没有以任何方式显式引用这个旧的父表字段……它似乎在自己生成 SQL……但对于当前的事物定义来说是不恰当的。

== 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"...

表定义非常简单:

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

更奇怪的是,这个迁移在 Production 中是有效的!

欢迎任何见解!

1 个赞

我因为这个 :policeman: :police_car: 被 RUBOCOPPED 了。

Offenses:

db/migrate/20231119010101_create_locations_topic_table.rb:6:7: C: Discourse/NoAddReferenceOrAliasesActiveRecordMigration: AR 方法 add_reference、add_belongs_to、t.references 和 t.belongs_to 对于大表来说风险很高,并且有太多的后台魔法操作。
请改用 disable_ddl_transactions! 迁移并编写自定义 SQL 来添加新列和 CREATE INDEX CONCURRENTLY。使用 IF NOT EXISTS 子句使迁移在部分失败后可以重新运行。

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

现在,这 可能 是问题的一部分。

太多的 :magic_wand: 在起作用,这就是问题所在!

活到老,学到老! :mortar_board:

1 个赞

Rubocop 的建议是好的,但我认为它不是导致此错误的原因。(它提到的“风险”是指对高流量表的锁定,这会影响生产流量。因此,这不会在测试环境中导致错误)

您可以通过执行 RAILS_ENV=test bin/rake db:drop db:create db:migrate(即从头开始迁移数据库,并启用 locations 插件)在本地重现相同的错误。

我怀疑问题在于您在迁移中调用 Rake 任务。在核心代码中,我们通常避免在迁移中运行任何类型的应用程序代码,因为这可能会产生奇怪的副作用。最好坚持使用纯 SQL。

在这种情况下,我的假设是 ActiveRecord 模式缓存会在迁移早期被填充(当 topics.off_topic_count 仍然存在时)。然后,当您的 rake 任务运行时,它将使用旧的模式缓存运行,因此 ActiveRecord 会尝试加载已不存在的列。

您可以通过在调用 rake 任务之前添加 ActiveRecord::Base.clear_cache! 来缓解此问题……但不要将其视为建议 :wink:。最好的办法是完全避免调用 rake 任务。如果您需要在数据库中操作某些内容,请在迁移中使用纯 SQL。

2 个赞

谢谢你,大卫,我会把它移到一个 SQL 语句,看看是否能解决……

太好了,谢谢 David!

2 个赞

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