如何使用Rails6.1连接到主数据库和碎片多个数据库ActiveRecord::ConnectionHandling



我正在尝试构建一个应用程序,该应用程序将使用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. 我想用connects_to database: { writing: :primary }设置GlobalRecord,但因为我添加了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 => [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

来源:

  • https://guides.rubyonrails.org/active_record_multiple_databases.html
  • https://www.freshworks.com/horizontal-sharding-in-a-multi-tenant-app-with-rails-61-blog/
  • https://api.rubyonrails.org/classes/ActiveRecord/ConnectionHandling.html#method-i-connected_to_many

一般来说,使用around过滤器切换连接是完全可以的,我们在以前的公司已经做了很多年了(甚至在Rails6之前(。

顺便问一句:你看到导游提到你发布的异常了吗?

请注意,具有角色的connected_to将查找现有连接并使用连接规范名称进行切换。这意味着,如果您传递一个未知的角色,如connected_to(角色::不存在(,您将得到一个错误,上面写着ActiveRecord::ConnectionNotEstablished(对于"不存在"的角色,找不到"ActiveRecord::Base"的连接池。(

https://guides.rubyonrails.org/active_record_multiple_databases.html#using-手动连接切换

相关内容

  • 没有找到相关文章

最新更新