Switching database connection between readonly one and writable one.
Add this line to your application's Gemfile:
gem 'switch_point'
And then execute:
$ bundle
Or install it yourself as:
$ gem install switch_point
See spec/models.
auto_writable
is disabled by default.
When auto_writable
is enabled, destructive queries is sent to writable connection even in readonly mode.
But it does NOT work well on transactions.
Suppose after_save
callback is set to User model. When User.create
is called, it proceeds as follows.
- BEGIN TRANSACTION is sent to READONLY connection.
- switch_point switches the connection to WRITABLE.
- CREATE statement is sent to WRITABLE connection.
- switch_point reset the connection to READONLY.
- after_save callback is called.
- At this point, the connection is READONLY and in a transaction.
- COMMIT TRANSACTION is sent to READONLY connection.
There's a proxy which holds two connections: readonly one and writable one. A proxy has a thread-local state indicating the current mode: readonly or writable.
Each ActiveRecord model refers to a proxy.
ActiveRecord::Base.connection
is hooked and delegated to the referred proxy.
When the writable connection is requested to execute destructive query, the readonly connection clears its query cache.
Basically, each connection managed by a proxy isn't shared between proxies. But there's one exception: ActiveRecord::Base.
If :writable
key is omitted (e.g., Nanika1 model in spec/models), it uses ActiveRecord::Base.connection
as writable one.
When ActiveRecord::Base.connection
is requested to execute destructive query, all readonly connections managed by a proxy which uses ActiveRecord::Base.connection
as a writable connection clear query cache.
- Fork it ( https://github.com/eagletmt/switch_point/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request