octopus icon indicating copy to clipboard operation
octopus copied to clipboard

Default shard for a specific model

Open andresberrios opened this issue 9 years ago • 9 comments

Hi! I'm using a main database for most of my models, and a separate one for some of them, which I configured in shards.yml. It works really well when I use it like SomeModel.using(:secondary_db).all but since these models don't exist in the main database, I want them to always use the secondary one by default. I tried this:

class SomeModel < ActiveRecord::Base
  default_scope { using :secondary_db }
end

But it throws some errors. When I run SomeModel.all I get:

NoMethodError: undefined method `values' for #<Class:0x007fc2dbd76f18>
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/scope_proxy.rb:36:in `block in method_missing'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:223:in `block (2 levels) in run_queries_on_shard'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:429:in `using_shard'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:222:in `block in run_queries_on_shard'
...

When I run it like this SomeModel.unscoped.all I get the expected result: It tries to run the query on the main database but the table is not there. After that, if I run SomeModel.all again in the same rails console session, I get a slightly different error message:

NoMethodError: undefined method `values' for SomeModel(Table doesn't exist):Class
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/scope_proxy.rb:36:in `block in method_missing'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:223:in `block (2 levels) in run_queries_on_shard'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:429:in `using_shard'
    from /Users/jorde/.rbenv/versions/2.0.0-p481/lib/ruby/gems/2.0.0/gems/ar-octopus-0.8.4/lib/octopus/proxy.rb:222:in `block in run_queries_on_shard'
...

Any ideas on how to achieve this? Thanks!

andresberrios avatar Mar 12 '15 12:03 andresberrios

HI @andresberrios ,

I don't think you need Octopus for that. Since your model only lives in your shard database, you can use the #establish_connection method from Rails: http://stackoverflow.com/a/6126706

Thiago

thiagopradi avatar Mar 12 '15 12:03 thiagopradi

Hi @tchandy , Thanks for your reply. I tried that approach before trying Octopus, but as I read online and I tried some stuff, it seems to create problems with migrations (schema_migrations sync and other stuff) and I think Octopus solves this wonderfully. Also I would like to use replication with Octopus eventually. I just think that supporting this use case in Octopus should be really simple, if only default_scope would work! Do you know if there is an alternative that would do the trick? Or a way of implementing it by overriding something of the model class? If I had more experience with Ruby I would try to make a pull request, but I checked the code and I have to admit it's a bit beyond my scope for the moment.

Andrés

andresberrios avatar Mar 12 '15 15:03 andresberrios

@tchandy Is there a way to disable Octopus for a model? I would like to use Rails' built-in establish_connection for a specific set of models, but it does not seem to have an effect with Octopus installed.

britg avatar Apr 30 '15 18:04 britg

Running into the same issue as @britg. I have two models out of a couple dozen that live in a separate sharded database. Would love to use Octopus to manage that database, but so far I haven't found a way to prevent it from instrumenting the other models. Makes sense as a default, but it'd be great if there was a way to instrument only specific models with Octopus, e.g. by extending a specialized ActiveRecord::Base subclass.

pauljm avatar Oct 31 '15 21:10 pauljm

I read though the codebase and noticed that model instances will run the callback after_initialize here https://github.com/thiagopradi/octopus/blob/master/lib%2Foctopus%2Fmodel.rb#L107, so maybe just override set_current_shard method in your model class as following:

def set_current_shard
  self.current_shard = :your_shard
end

Does it work for you guys?

anhkind avatar Feb 19 '16 15:02 anhkind

Does that work? This has been a question for a little over a year without a clear confirmation...

tibbon avatar Nov 17 '16 22:11 tibbon

any news?

heberuriegas avatar Jun 01 '17 17:06 heberuriegas

Didn't work with version 0.8.3

chenhoward avatar Aug 18 '17 01:08 chenhoward

same issue here. any update?

fertobar avatar Jan 16 '18 00:01 fertobar