berkshelf / ridley

A reliable Chef API client with a clean syntax
Other
231 stars 85 forks source link

Celluloid::DeadActorError after invalid search query #326

Open bmhatfield opened 8 years ago

bmhatfield commented 8 years ago
2015-12-30 15:08:39 - Ridley::Errors::HTTPBadRequest - {"error":["invalid search query: 'ipaddress: 10.78.98.12'"]}:
        /usr/lib/ruby/gems/2.1.0/gems/ridley-4.3.2/lib/ridley/middleware/chef_response.rb:24:in `on_complete'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/response.rb:9:in `block in call'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/response.rb:57:in `on_complete'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/response.rb:8:in `call'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/response.rb:8:in `call'
        /usr/lib/ruby/gems/2.1.0/gems/ridley-4.3.2/lib/ridley/middleware/chef_auth.rb:74:in `call'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/request/retry.rb:116:in `call'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:in `build_response'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in `run_request'
        /usr/lib/ruby/gems/2.1.0/gems/ridley-4.3.2/lib/ridley/connection.rb:105:in `run_request'
        /usr/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:177:in `post'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `public_send'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:26:in `dispatch'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/calls.rb:63:in `dispatch'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:60:in `block in invoke'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/cell.rb:71:in `block in task'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/actor.rb:357:in `block in task'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/tasks.rb:57:in `block in initialize'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/tasks/task_thread.rb:21:in `block in create'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/thread_handle.rb:13:in `block in initialize'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/actor_system.rb:32:in `block in get_thread'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/internal_pool.rb:130:in `call'
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/internal_pool.rb:130:in `block in create'
        (celluloid):0:in `remote procedure call'

Subsequent requests to the same process fail with:

2015-12-30 16:15:56 - Celluloid::DeadActorError - attempted to call a dead actor:
        /usr/lib/ruby/gems/2.1.0/gems/celluloid-0.16.0/lib/celluloid/proxies/sync_proxy.rb:23:in `method_missing'

I'm not really sure how I am supposed to be handling this error from my API's perspective - I don't know if a given search query is going to be valid or not.

Should I rescue the Ridley::Errors::HTTPBadRequest exception? Can I reinitialize the actor?

bmhatfield commented 8 years ago

I did some playing around with this, and it looks like Celluloid's abort method is making it up the call stack further than expected. Adding some simplistic puts to track the exception chain:

** RAISING EXCEPTION IN on_complete (chef_response.rb:24)
** In run_request (connection.rb:107) rescue block
** in raw_request (resource.rb:13) rescue block
** In partial_search (client.rb:250) rescue block: Ridley::Errors::HTTPBadRequest

Altering partial_search to handle the exception seems to help:

def partial_search(index, query = nil, attributes = [], options = {})
  @resources_registry[:search_resource].partial(index, query, Array(attributes), @resources_registry, options)
rescue Errors::HTTPError => ex
  puts "** In partial_search rescue block: #{ex.class}"
  abort(ex)
end

Looking at client.rb, however, seems that no resource is protected in this manner, which gives me pause as to the correct approach, and slows me from simply sending a PR with my changes.

What do you recommend? I don't think I can solve this problem directly by catching the relevant exceptions in my code, as they occur in a different thread, I think. I could 'open up' Ridley from my code or run a fork of this Gem, but I am not really interested in either of those workarounds.

I would be happy to submit a PR, but I don't really feel like I understand the intent of this current abort and catch exception structure, especially because it appears to fall short of what's needed to prevent the outer actors from crashing.

Thoughts?