Hello,
We use sequel models extensively, including single table inheritance for
implementing different class behaviors, while sharing tables, all to
implement a server and service management and orchestration platform.
We also use a ruby pry console to interact with our app and trigger actions
in production. In an effort to avoid fat fingers and other errors from
accidentally killing our fleet, we implemented a default read only console,
which initially connects to our read replica, and on demand, allows an
operator to change to a writeable console. This runtime action disconnects
DB and reconnects to our writable leader, while preserving already loaded
Sequel::Model objects in memory. Our current method of doing this reassigns
db for all loaded Sequel::Model.descendants, so that already loaded Sequel
objects may be preserved and be able to write to the proper db, after
making the console writable.
Now we are looking to move to Sequel 5, where it seems that setting a
Model.db= is not possible. We attempted to move to using Model.dataset= to
achieve the same effect, but then found STI classes lost their custom
dataset definitions. Also, this is documented as: `You shouldn't call
set_dataset in the model after applying this plugin, otherwise subclasses
might use the wrong dataset.` in the docs.
Is it possible to somehow use Sequel's sharding support to implement this
read only console pattern, or is there a simpler solution that I am
overlooking?
Looking at the add_servers and remove_servers functions, it does not seem
clear that we could use them to reassign the backing db of an already
instantiated sequel model in a pry, which I think is our central use case.
Our reload code is excerpted below:
def reload!(fast: true)
failed_files = {}
with_silenced_logging do
with_silence_warnings do
DB.disconnect unless fast
load 'config/config.rb'
load 'config/initializers/database.rb'
Sequel::Model.db = DB unless fast
Sequel::Model.descendants.each { |m| m.db = DB } unless fast
$".grep(/\/lib\/(app|web)/e).each do |file|
maybe_load_file(file) do |failure_reason,exception|
failed_files[file] = [failure_reason, exception]
end
end
end
end
end
def writeable_app!
Shogun::AWS::AwsClient.set_credentials(Config.aws_access_key_id,
Config.aws_secret_access_key)
ENV['CONNECT_TO_FOLLOWER'] = 'false'
reload!(fast: false)
end
def read_only_app!
Shogun::AWS::AwsClient.set_credentials(Config.readonly_aws_access_key_id,
Config.readonly_aws_secret_access_key)
ENV['CONNECT_TO_FOLLOWER'] = 'true'
reload!(fast: false)
end
And config/initializers/database.rb is :
database_url = if Config.connect_to_follower
Config.follower_database_url
else
Config.database_url
end
DB = Sequel.connect(database_url,
preconnect: Config.behind_pgbouncer,
max_connections: Config.sidekiq_concurrency,
after_connect: proc do |c|
c.execute("SET application_name TO '#{Config.dyno}'")
if Config.web_statement_timeout && Config.dyno =~ /^web/i
c.execute("SET statement_timeout=#{Config.web_statement_timeout};")
end
end)
DB.extens
Thanks,
Greg
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.