Created
February 21, 2016 12:55
-
-
Save MarceloCajueiro/14a8119741634ca4c029 to your computer and use it in GitHub Desktop.
Use database follower with Sidekiq
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'delegate' | |
module SidekiqExt | |
# Use read-only database if :db option is :read_only, | |
# otherwise use the default connection. | |
# | |
# Example: | |
# | |
# class MyWorker | |
# include Sidekiq::Worker | |
# | |
# sidekiq_options db: :read_only | |
# | |
# def perform | |
# ... | |
# end | |
# end | |
class ReadOnlyMiddleware | |
# Creates a connection pool for read-only database | |
class ReadOnlyConnectionPoolOwner < ActiveRecord::Base | |
self.abstract_class = true | |
establish_connection("follower_#{Rails.env}") | |
end | |
class ReadOnlySwitcherConnectionHandler < SimpleDelegator | |
def initialize(connection_handler) | |
super | |
# Proxy the `retrieve_connection_pool` calls and return | |
# the properly pool connection | |
# IMPORTANT: This must be done here since SimpleDelegator doesn't | |
# wrap internal calls. | |
def connection_handler.retrieve_connection_pool(klass) | |
if Thread.current.thread_variable_get(:use_read_only_connection_pool) | |
super(ReadOnlyConnectionPoolOwner) | |
else | |
super | |
end | |
end | |
end | |
end | |
def initialize(*args) | |
connection_handler = ActiveRecord::Base.connection_handler | |
unless connection_handler.instance_of?(ReadOnlySwitcherConnectionHandler) | |
ActiveRecord::Base.connection_handler = | |
ReadOnlySwitcherConnectionHandler.new(connection_handler) | |
end | |
end | |
def call(worker, job, queue, &block) | |
db_option = (job['db'] || :master).to_sym | |
if db_option == :read_only | |
execute_using_read_only_connection(&block) | |
else | |
yield | |
end | |
end | |
private | |
def execute_using_read_only_connection(&block) | |
begin | |
Thread.current.thread_variable_set(:use_read_only_connection_pool, true) | |
yield | |
ensure | |
Thread.current.thread_variable_set(:use_read_only_connection_pool, false) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Kudos to @tlewin.