タケユー・ウェブ日報

Ruby on Rails や Flutter といったWeb・モバイルアプリ技術を武器にお客様のビジネス立ち上げを支援する、タケユー・ウェブ株式会社の技術ブログです。

graphql-ruby + Multiple Databases with ActiveRecord

Query では読み込み専用 、Mutation では読み書きを使うようにしたかった。

github.com

上記のコメントで動くのだが、テストでトランザクションを使ったロールバック戦略を採用していると、レプリカに変更が伝搬されずに失敗する点に注意。(関連:Rails 6.0の複数DBでリードレプリカのテストするのたぶん大変

module Tracers
  class DatabaseRoleTracer
    EVENT_NAME = 'execute_multiplex'.freeze

    def trace(event, data)
      # テストではテストケースごとにトランザクションをロールバックするためコミットされずレプリカに伝搬しない
      # ので、やむなくテストモードでは無効=プライマリに繋ぐ
      if event == EVENT_NAME && !Rails.env.test?
        multiplex = data[:multiplex]

        role = multiplex.queries.all?(&:query?) ?
          ActiveRecord::Base.reading_role :
          ActiveRecord::Base.writing_role

        Rails.logger.debug("[#{self.class.name}] ActiveRecord::Base.connected_to(role: #{role.inspect})")
        ActiveRecord::Base.connected_to(role: role) do
          yield
        end
      else
        yield
      end
    end
  end
end

class MyAppSchema < GraphQL::Schema
  mutation(Types::MutationType)
  query(Types::QueryType)

  # 省略

  # Query か Mutation かで接続先データベースを変更する
  tracer Tracers::DatabaseRoleTracer.new
end

railsguides.jp

graphql-ruby.org