私が正しく理解していれば、これはあなたの問題です:
- 1 つの Rails アプリが、モバイル アプリからの READ と WRITE リクエストの両方を処理します。
- 1 つの Rails アプリで異なる READ データベースと WRITE データベースを使用したい
- また、WRITE が READ DB に伝播されるタイミングをカスタム制御できるようにする必要があります。
問題を解決する最もクリーンな方法は次のとおりです。
2 つのデータベースを作成し (それらを READ DB と WRITE DB と呼びましょう)、それらの間でマスター/スレーブ レプリケーションをセットアップします。したがって、WRITE DB で作成したクエリは、READ DB にレプリケートされ、いつ、どのようにレプリケーションがトリガーされるかを制御できます。ほぼすべてのデータベースが、これをすぐに使用できるようにサポートしています。MySQLの手順は次のとおりです。マスター/スレーブ レプリケーションは標準で堅牢であるため、PostgreSQL に切り替える必要さえありません。
Rails アプリの場合、次の 2 つのデータベースを構成しますconfig/database/yml
。
production:
# configuration for your WRITE DB
adapter: mysql
database: ...
host: ...
username: ...
password: ...
production_read:
# configuration for your READ DB
adapter: mysql
database: ...
host: ...
username: ...
password: ...
そして、次の 2 つの選択肢があります。
同じインスタンスを 2 つデプロイします。RAILS_ENV=production_read
コードに変更はありませんが、READ 用のインスタンスとRAILS_ENV=production
WRITE用のインスタンスの 2 つのインスタンスをデプロイするだけです。モバイル アプリを変更して、READ が最初のインスタンス URL に移動し、WRITE が他のインスタンス URL に移動するようにします。
(また)
Rails アプリのインスタンスを 1 つだけ実行し、production
とproduction_read
データベースを切り替えるだけです。適切な Web サービスがあるので、データの読み取りに GET 要求を使用していると仮定します。他のすべての (POST/PUT/DELETE/etc) 要求は書き込み要求です。これを行っていない場合は、まずとにかくこれを行うことをお勧めします。読み取りに GET を使用している場合は、次のようにします。
# app/controllers/application_controller.rb
class ApplicationController
before_filter do
# Switch to production_read or production configurations
# based on request method
if request.get?
ActiveRecord::Base.establish_connection "production_read"
else
ActiveRecord::Base.establish_connection "production"
end
end
これは、リクエスト方法に応じて、あなたproduction_read
と構成の間で切り替わります。また、認証と承認の後にのみ切り替えが発生し、最終的にコントローラー ロジックの直前に切り替えが行われるように、 をproduction
注文することもできます。before_filter
establish_connection
また、すべてのモデル クラスに対して同じことを行う必要がある場合もあります。その場合は、ActiveRecord::Base
サブクラスをループして、同じ Establish_connection ロジックを呼び出すだけです。接続を切り替える前に、いくつかのサブクラスを省略することもできます。
ActiveRecord::Base.descendants.each do |model_class|
model_class.establish_connection (request.get? ? "production_read" : "production")
end
# Or let's say you want to switch all models *except* User/Session models to the READ DB
(ActiveRecord::Base.descendants - [User, Session]).each do ...