Question

With version 4 of delayed_job_active_record gem, I want to delay requests to an external API. My job is added to database, and rake jobs:work runs it and removes it from the database. However, the actual delayed code from my messages_controller.rb is never executed.

If I try to Delayed::Job.last.invoke_job in the rails console, I receive the following error:

Delayed::DeserializationError: Job failed to load: allocator undefined for Proc. Handler: "--- !ruby/object:Delayed::PerformableMethod\nobject: !ruby/object:MyApp::Zendesk\n  client: !ruby/object:ZendeskAPI::Client\n    config: !ruby/object:ZendeskAPI::Configuration\n      client_options: {}\n      cache: !ruby/object:ZendeskAPI::LRUCache\n        size: 1000\n        store: {}\n        lru: []\n      url: https://redacted.zendesk.com/api/v2\n      username: redacted\n      password: redacted\n      retry: true\n      logger: !ruby/object:Logger\n        progname: \n        level: 0\n        default_formatter: !ruby/object:Logger::Formatter\n          datetime_format: \n        formatter: \n        logdev: !ruby/object:Logger::LogDevice\n          shift_size: \n          shift_age: \n          filename: \n          dev: !ruby/object:IO {}\n          mutex: !ruby/object:Logger::LogDevice::LogDeviceMutex\n            mon_owner: \n            mon_count: 0\n            mon_mutex: !ruby/object:Mutex {}\n    callbacks:\n    - !ruby/object:Proc {}\n    resource_cache: {}\nmethod_name: :create_support_ticket\nargs:\n- !ruby/hash:ActionController::Parameters\n  name: redacted\n  email: redacted\n  reason: General\n  message: test\n"

The code trying to be run is the create_support_ticket method:

# messages_controller.rb
require 'zendesk'

class MessagesController < ApplicationController
  layout "application"

  # /suport/contact-us
  def contact_us
    zendesk = MyApp::Zendesk.new
    zendesk.delay.create_support_ticket(params[:message])

    # render page
    respond_to do |format|
      flash[:notice] = "Email sent successfully!" if @sent
      format.html { render "pages/support/contact-us" }
    end
  end
end

# zendesk.rb
require 'zendesk_api'

module MyApp
  class Zendesk
    attr_accessor :client

    def initialize(*args)
      @client = create_client
    end

    # contact-us ticket methods
    def create_support_ticket(params={})
      unless params.blank? || @client.blank?
        # get or create user_id for submitter
        params[:requester_id] = check_user_exists(params)

        begin
          ticket = @client.tickets.create(
            subject: "Support Ticket",
            comment: { value: params[:message] },
            submitter_id: params[:requester_id],
            requester_id: params[:requester_id],
            assignee_id: 201578811,
            status: "new",
            fields: [
              {id: 20887016, value: "Support"},
              {id: 20966436, value: "New"}])
          return ticket
        rescue => e
          Airbrake.notify e
        end
      else
        return false
      end
    end
  end
end
Was it helpful?

Solution

DelayedJob tries to serialize the object you are calling the method on.

In your case, that object has an IO and also a Proc object. Both of them are not compatible with serialization. Best thing you can do is writing a simple wrapper that has no dependencies and initializes all the stuff inside the method-call.

OTHER TIPS

I happened to come across the same issue as above. I had an object of Oauth::Client which failed to deserialize by delayed_job Gem.

To resolve, I have changed my approach, so that the Ouath::Client object isn't serialized/deserialized when I add a method to the delayed job.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top