require 'resque-retry' class Hook < ActiveRecord::Base attr_accessible :event, :account_id, :subscription_url, :target_url validates_presence_of :event, :account_id, :subscription_url, :target_url # Looks for an appropriate REST hook that matches the record, and triggers the hook if one exists. def self.trigger(event, record) hooks = self.hooks(event, record) return if hooks.empty? unless Rails.env.development? # Trigger each hook if there is more than one for an account, which can happen. hooks.each do |hook| # These use puts instead of Rails.logger.info because this happens from a Resque worker. puts "Triggering REST hook: #{hook.inspect}" puts "REST hook event: #{event}" encoded_record = HookEncoder.encode(record) puts "REST hook record: #{encoded_record}" RestClient.post(hook.target_url, encoded_record) do |response, request, result| if response.code.eql? 410 puts "Destroying REST hook because of 410 response: #{hook.inspect}" hook.destroy end end end end end # This method is called by a Resque worker. Resque stores the record's class and ID, and the # Resque worker provides those values as parameters to this method. def self.perform(klass, id) # puts "Performing REST hook Resque job: #{klass} #{id}" event = "new_#{klass.to_s.underscore}" record = klass.camelize.constantize.find(id) Hook.trigger(event, record) end @queue = :rest_hook extend Resque::Plugins::Retry @retry_limit = 3 @retry_delay = 5 # Returns all hooks for a given event and account. def self.hooks(event, record) Hook.find(:all, :conditions => { :event => event, :account_id => record.account_id, }) end # Tests whether any hooks exist for a given event and account, for deciding whether or not to # enqueue Resque jobs. def self.hooks_exist?(event, record) self.hooks(event, record).size > 0 end end