Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support departure when using it in environments together with apartment and octopus #37

Open
w32-blaster opened this issue Aug 31, 2018 · 4 comments

Comments

@w32-blaster
Copy link

Apartment gem is used for handling multi tenancy on database level. This means, having multiple databases which should have the same schema.
Octopus can be used to take care of master / slave mysql structure and route the queires to the right node (shard)
When using departure in an environment together with apartment and octopus, we are getting the following error:

ActiveRecord::RecordNotUnique: Mysql2::Error: Duplicate entry '20180109094356' for key 'unique_schema_migrations': INSERT INTO `schema_migrations` (`version`) VALUES ('20180109094356'): INSERT INTO `schema_migrations` (`version`) VALUES ('20180109094356')

Doing some investigation, it looks like we are always trying to connect to the same database (the main database which is set in the config file) and not to the one, which was selected by apartment

@sauloperez
Copy link

sauloperez commented Aug 31, 2018

Hi @w32-blaster! welcome to Departure!

I'm not familiar with Apartment myself but sounds like something reasonable to be implemented by providing a strategy config key to Departure as in https://github.com/departurerb/departure#with-global-configuration. Feel free to open a PR.

@jamesmacwilliam
Copy link

@w32-blaster is there an associated code sample that you have handy to demonstrate this? Does the issue only occur if both apartment and octopus are used, or can it be reproduced only using apartment?

@robbwagoner
Copy link

@jamesmacwilliam and @w32-blaster - I can confirm that with just Octopus (ar-octopus) (we don't use Apartment) that Departure fails when RAILS_ENV=production. It's fine when RAILS_ENV=development

Failure: RAILS_ENV=production

Octopus::Exception: No slaves available

$ RAILS_ENV=production bundle exec rake db:migrate
rake aborted!
Octopus::Exception: No slaves available
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/load_balancing/round_robin.rb:9:in `initialize'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/proxy_config.rb:210:in `new'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/proxy_config.rb:210:in `initialize_replication'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/proxy_config.rb:17:in `initialize'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/proxy.rb:20:in `new'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/proxy.rb:20:in `initialize'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/model.rb:142:in `new'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/model.rb:142:in `connection_proxy'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/ar-octopus-0.9.2/lib/octopus/model.rb:174:in `connection_pool_with_octopus'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activerecord-import-0.25.0/lib/activerecord-import/import.rb:219:in `establish_connection_with_activerecord_import'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activerecord-5.1.4/lib/active_record/railtie.rb:124:in `block (2 levels) in <class:Railtie>'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:69:in `instance_eval'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:69:in `block in execute_hook'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:60:in `with_execution_control'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:65:in `execute_hook'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:41:in `block in on_load'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:40:in `each'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/lazy_load_hooks.rb:40:in `on_load'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activerecord-5.1.4/lib/active_record/railtie.rb:120:in `block in <class:Railtie>'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/initializable.rb:30:in `instance_exec'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/initializable.rb:30:in `run'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/initializable.rb:59:in `block in run_initializers'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/initializable.rb:58:in `run_initializers'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/application.rb:353:in `initialize!'
/home/rwagoner/activities/config/environment.rb:5:in `<top (required)>'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:292:in `require'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:292:in `block in require'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:258:in `load_dependency'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:292:in `require'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/application.rb:329:in `require_environment!'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/railties-5.1.4/lib/rails/application.rb:445:in `block in run_tasks_blocks'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/bugsnag-6.8.0/lib/bugsnag/integrations/rake.rb:18:in `execute_with_bugsnag'
/home/rwagoner/activities/vendor/bundle/ruby/2.5.0/gems/rake-12.3.0/exe/rake:27:in `<top (required)>'
Tasks: TOP => db:migrate => environment

@dil-steti
Copy link

Hey @w32-blaster, where did you end up with this? I assume that you're using config.use_schemas = true in your Apartment initializer - I am, and I was seeing the same behavior as you

As far as I can tell, the issue is that Apartment, when configured with use_schemas = true (the default), switches databases by executing a use <db_name> command directly against the database adapter. This has no effect on Departure, since Departure uses the database name from the AR config to construct its CLI commands.

I was able to work around it by setting config.use_schemas = false in my app's Rakefile. This causes Apartment to use its Mysql2Adapter rather than its Mysql2SchemaAdapter when running migrations. The Mysql2Adapter actually connects ActiveRecord to the new database directly instead of just switching with a use command. With this adapter, Departure seems to be picking up the correct database name, and my migrations are running correctly both on the main database and on individual tenant databases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants