【问题标题】:How to connect to primary database and shards using Rails 6.1 multiple databases ActiveRecord::ConnectionHandling?如何使用 Rails 6.1 多数据库 ActiveRecord::ConnectionHandling 连接到主数据库和分片?
【发布时间】:2021-08-31 19:41:38
【问题描述】:

我正在尝试构建一个应用程序,它将使用最新的 Rails 6.1 功能之一:multiple databases - 您可以阅读底部的源代码。

我想通过能够根据请求域在数据库之间切换来实现多租户。

每个俱乐部都有自己的数据库,一个主数据库将存储应用程序特定的数据,例如用户、俱乐部。

我创建了两种类型的记录:GlobalRecord 使用 primary 数据库和 ShardRecord 使用水平分片数据库。

并且还尝试使用around_action 选择当前俱乐部数据库。

# config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode

development:
  primary:
    <<: *default
    database: primary
    migrations_paths: db/migrate
  club_1:
    <<: *default
    database: club_1
    migrations_paths: db/shard_migrate
  club_2:
    <<: *default
    database: club_2
    host: 1.1.1.1
    username: deploy
    password: pass
    migrations_paths: db/shard_migrate
class Club < GlobalRecord; end
class GlobalRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to shards: {
    club_1: { writing: :primary, reading: :primary },
    club_2: { writing: :primary, reading: :primary }
  }
end
class MemberRecord < ShardRecord; end
class ShardRecord < ActiveRecord::Base
  self.abstract_class = true

  connects_to shards: {
    club_1: { writing: :club_1, reading: :club_1 },
    club_2: { writing: :club_2, reading: :club_2 }
  }
end
class ApplicationController < ActionController::API
  before_action :set_club
  around_action :connect_to_shard

  private

  def set_club
    @club = SelectClubByDomain.new(request).slug
  end

  def connect_to_shard
    ActiveRecord::Base.connected_to(role: :writing, shard: @club.slug) do
      yield
    end
  end
end

我有几个设计问题/问题想问你:

  1. 我想设置GlobalRecordconnects_to database: { writing: :primary } 但因为我添加了around_action 我必须像上面那样设置它。 是不好的设计吗? 我可以重构它,以便在没有 ActiveRecord::Base.connected_to(role: :writing, shard: :club_1) 块的情况下始终调用 GlobalRecord 吗?

尝试在around_action 中使用ActiveRecord::Base.connected_to_many(GlobalRecord, ShardRecord, role: :writing, shard: @club_slug.to_sym),但应请求(clubs#index =&gt; [Club.all]) 出现错误:

ActiveRecord::ConnectionNotEstablished (No connection pool for 'GlobalRecord' found for the 'club_1' shard.)
  1. 在生产服务器上启动时我看到此警告,如何解决?
=> Run `bin/rails server --help` for more startup options
Failed to define attribute methods because of ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished

来源:

【问题讨论】:

    标签: ruby-on-rails activerecord multi-tenant multiple-databases


    【解决方案1】:

    一般来说,使用环绕过滤器切换连接绝对没问题,在我以前的公司中,我们已经这样做了多年(甚至在 Rails 6 之前)。

    顺便说一句:您是否看到指南提到了您发布的异常?

    请注意,具有角色的 connected_to 将查找现有连接并使用连接规范名称进行切换。这意味着如果您传递一个未知角色,例如 connected_to(role: :nonexistent),您将收到一条错误消息,提示 ActiveRecord::ConnectionNotEstablished (No connection pool for 'ActiveRecord::Base' found for the 'nonexistent' role.)

    https://guides.rubyonrails.org/active_record_multiple_databases.html#using-manual-connection-switching

    【讨论】:

      猜你喜欢
      • 2014-07-04
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多