petergoldstein / dalli

High performance memcached client for Ruby
MIT License
3.1k stars 450 forks source link

Fallback to actual block if server down #252

Closed International closed 11 years ago

International commented 12 years ago

Imagine I have something like this:

Rails.cache.fetch("my_model_1") { MyModel.find(1) }

On Heroku, the memcachier server seems to die pretty randomly, and thus, it causes errors ( because of data being nil ). Is it possible to failover to actually perform a block's action if a server's not alive? I'd gladly trade performance to being able to run without such failures.

viniciusnz commented 11 years ago

Hi there! I was having the same issue here. It works fine on my local machine (with memcached turned on), but in production when I try

Raills.cache.fetch("recs_count") do
  1 # some code here
end

The response is:

LocalJumpError: no block given (yield)
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/gelf-1.3.2/lib/gelf/logger.rb:16:in `add'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/gelf-1.3.2/lib/gelf/logger.rb:33:in `debug'
from /mnt/myapp/releases/20121207003816/config/initializers/graylog.rb:13:in `block in method_missing'
from /mnt/myapp/releases/20121207003816/config/initializers/graylog.rb:13:in `each'
from /mnt/myapp/releases/20121207003816/config/initializers/graylog.rb:13:in `method_missing'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/server.rb:431:in `connect'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/server.rb:79:in `alive?'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/options.rb:24:in `block in alive?'
from /usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/options.rb:23:in `alive?'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/ring.rb:36:in `block in server_for_key'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/ring.rb:33:in `times'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/ring.rb:33:in `server_for_key'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/client.rb:272:in `perform'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/dalli/client.rb:51:in `get'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/active_support/cache/dalli_store.rb:204:in `read_entry'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.8/lib/active_support/cache/strategy/local_cache.rb:134:in `read_entry'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/active_support/cache/dalli_store.rb:60:in `block in fetch'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/active_support/cache/dalli_store.rb:265:in `block in instrument'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.8/lib/active_support/notifications.rb:125:in `instrument'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/active_support/cache/dalli_store.rb:265:in `instrument'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/dalli-2.5.0/lib/active_support/cache/dalli_store.rb:58:in `fetch'
from (irb):3
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
from /mnt/myapp/shared/bundle/ruby/1.9.1/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'

Note that this was supposed to be a simple change from

config.cache_store = :mem_cache_store, "app01.myapp.com.br", "app02.myapp.com.br"

to

config.cache_store = :dalli_store, "app01.myapp.com.br", "app02.myapp.com.br", { :expires_in => 1.day, :compress => true }

I noticed that the method missing was captured by graylog,

Maybe I forgot to change something else, sorry for the long post...

drale2k commented 11 years ago

The Memcachier Europe Region server today was corrupt again and caused my app on heroku to crash because of that. Is there a way to fallback to no cache or to the Rails default cache?

mperham commented 11 years ago

Use :raise_errors => false. This is an undocumented flag to the cache_store.

config.cache_store = :dalli_store, "app01.myapp.com.br", "app02.myapp.com.br", { :expires_in => 1.day, :compress => true, :raise_errors => false }
drale2k commented 11 years ago

Thank you! What will :raise_errors => false do? Use the default Rails cache or no cache?

mperham commented 11 years ago

no cache.

On Mon, May 27, 2013 at 1:38 PM, Drazen Mokic notifications@github.comwrote:

Thank you! What will :raise_errors => false do? Use the default Rails cache or no cache?

— Reply to this email directly or view it on GitHubhttps://github.com/mperham/dalli/issues/252#issuecomment-18513931 .

drale2k commented 11 years ago

Will it use the cache again when the server gets available? Or does it need a server restart for that to use the cache again?

mperham commented 11 years ago

Yes. No. Dalli is self-healing.

drale2k commented 11 years ago

Really nice, thanks a lot. Cheers

viniciusnz commented 11 years ago

Hi there!

For what is worth, I tried again with the :raise_errors => false flag and it still gave me the same exception:


irb(main):014:0> require 'dalli'
=> false
irb(main):015:0> options = { :namespace => "app_v1", :compress => true, :raise_errors => false } 
=> {:namespace=>"app_v1", :compress=>true, :raise_errors=>false}
irb(main):016:0> dc = Dalli::Client.new('localhost:11211', options)
=> #<Dalli::Client:0x00000006e142a8 @servers=["localhost:11211"], @options={:namespace=>"app_v1", :compress=>true, :raise_errors=>false}, @ring=nil>
irb(main):017:0> dc.set('abc', 123)
LocalJumpError: no block given (yield)
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/gelf-1.3.2/lib/gelf/logger.rb:16:in `add'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/gelf-1.3.2/lib/gelf/logger.rb:33:in `debug'
    from /mnt/Gympass-production/releases/20130527205759/config/initializers/graylog.rb:13:in `block in method_missing'
    from /mnt/Gympass-production/releases/20130527205759/config/initializers/graylog.rb:13:in `each'
    from /mnt/Gympass-production/releases/20130527205759/config/initializers/graylog.rb:13:in `method_missing'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:535:in `connect'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:87:in `alive?'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/options.rb:24:in `block in alive?'
    from /usr/local/rubies/1.9.3-p385/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/options.rb:23:in `alive?'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/ring.rb:42:in `server_for_key'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/client.rb:347:in `perform'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/client.rb:199:in `set'
    from (irb):17
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
    from /mnt/Gympass-production/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'irb(main):018:0>

Although this same code works fine under development:


1.9.3p194 :001 > require 'dalli'
 => false 
1.9.3p194 :002 > options = { :namespace => "app_v1", :compress => true, :raise_errors => false } 
 => {:namespace=>"app_v1", :compress=>true, :raise_errors=>false} 
1.9.3p194 :003 > dc = Dalli::Client.new('localhost:11211', options)
 => #<Dalli::Client:0xda14c00 @servers=["localhost:11211"], @options={:namespace=>"app_v1", :compress=>true, :raise_errors=>false}, @ring=nil> 
1.9.3p194 :004 > dc.set('abc', 123)
 => true 
1.9.3p194 :005 > value = dc.get('abc')
 => 123 
1.9.3p194 :006 >

Once again I'm sorry for the long post... I know the server is working on production because I'm using memcached-client pointing to it and it's working fine... I wonder if there's any incompatibility between Gelf and Dalli, do you know? I know Gelf is not working on development...

Thanks a lot, best,

viniciusnz commented 11 years ago

Btw I also updated my dalli version from 2.6.0 to 2.6.4, which I assume is the latest... thanks!

mperham commented 11 years ago

@viniciusnz You've got a bug in gelf that has nothing to do with dalli.

viniciusnz commented 11 years ago

It turns out you were right, gelf did not accept the block dalli was throwing at it on the debug line in server connect

Is there any way to turn off all logging for dalli? Thanks

ksheurs commented 9 years ago

Hi there. We are finding Dalli::RingError is still raised even with :raise_errors => false. Is it possible to include this exception in the ignored exception list?

petergoldstein commented 9 years ago

@ksheurs Please open a new issue with your request/concern rather than commenting on a closed, only somewhat related issue from 1.5 years ago. Thanks.

ksheurs commented 9 years ago

will do!