diff options
author | Eileen Uchitelle <eileencodes@gmail.com> | 2019-01-17 13:33:48 -0500 |
---|---|---|
committer | Eileen Uchitelle <eileencodes@gmail.com> | 2019-01-30 13:37:25 -0500 |
commit | 0abcec416b6ec11faffa03d40e5661c0a4a8b092 (patch) | |
tree | 01a366cdae0fd4f536efbbe73360a27506cfdbc1 /activesupport/test/log_subscriber_test.rb | |
parent | 3d22069c6355dc60be65e01958cf32917bc53142 (diff) | |
download | rails-0abcec416b6ec11faffa03d40e5661c0a4a8b092.tar.gz rails-0abcec416b6ec11faffa03d40e5661c0a4a8b092.tar.bz2 rails-0abcec416b6ec11faffa03d40e5661c0a4a8b092.zip |
Adds basic automatic database switching to Rails
The following PR adds behavior to Rails to allow an application to
automatically switch it's connection from the primary to the replica.
A request will be sent to the replica if:
* The request is a read request (`GET` or `HEAD`)
* AND It's been 2 seconds since the last write to the database (because
we don't want to send a user to a replica if the write hasn't made it
to the replica yet)
A request will be sent to the primary if:
* It's not a GET/HEAD request (ie is a POST, PATCH, etc)
* Has been less than 2 seconds since the last write to the database
The implementation that decides when to switch reads (the 2 seconds) is
"safe" to use in production but not recommended without adequate testing
with your infrastructure. At GitHub in addition to the a 5 second delay
we have a curcuit breaker that checks the replication delay
and will send the query to a replica before the 5 seconds has passed.
This is specific to our application and therefore not something Rails
should be doing for you. You'll need to test and implement more robust
handling of when to switch based on your infrastructure. The auto
switcher in Rails is meant to be a basic implementation / API that acts
as a guide for how to implement autoswitching.
The impementation here is meant to be strict enough that you know how to
implement your own resolver and operations classes but flexible enough
that we're not telling you how to do it.
The middleware is not included automatically and can be installed in
your application with the classes you want to use for the resolver and
operations passed in. If you don't pass any classes into the middleware
the Rails default Resolver and Session classes will be used.
The Resolver decides what parameters define when to
switch, Operations sets timestamps for the Resolver to read from. For
example you may want to use cookies instead of a session so you'd
implement a Resolver::Cookies class and pass that into the middleware
via configuration options.
```
config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = MyResolver
config.active_record.database_operations = MyResolver::MyCookies
```
Your classes can inherit from the existing classes and reimplment the
methods (or implement more methods) that you need to do the switching.
You only need to implement methods that you want to change. For example
if you wanted to set the session token for the last read from a replica
you would reimplement the `read_from_replica` method in your resolver
class and implement a method that updates a new timestamp in your
operations class.
Diffstat (limited to 'activesupport/test/log_subscriber_test.rb')
0 files changed, 0 insertions, 0 deletions