cryo28 / sidekiq_status

Extension to Sidekiq to pass job execution metadata such as status and result back to the client
MIT License
152 stars 53 forks source link

total and at methods don't work with ActiveJob support #40

Open kelhusseiny opened 8 years ago

kelhusseiny commented 8 years ago

Using total and at methods with active job always returns 0. I think the problem come from trying to access @jid which is always return nil. so any idea how to fix that?

cryo28 commented 8 years ago

Sorry I don't use ActiveJob yet so I am not sure what's the problem there. Pull requests are welcome.

ACPK commented 7 years ago

@Azzurrio - Did you get it working with active job?

kelhusseiny commented 7 years ago

@ACPK Not yet. Actually I did a workaround by doing something like this in application_job

class ApplicationJob < ActiveJob::Base
  attr_accessor :jid

  before_perform do |job|
    job.jid = job.provider_job_id
  end
end

PS: This works with Sidekiq only because I had to do a PR into rails to get it working.

ACPK commented 7 years ago

@Azzurrio Thank you!

cpunion commented 7 years ago

I wrote an ActiveJob adapter, not perfectly, just works.

The adapter below is compatible with Non-SidekiqStatus jobs. When the job class doesn't include SidekiqStatus::Worker, it uses the Sidekiq adapter (its simple than SidekiqStatus, so I think it's faster), otherwise use a dummy worker to call real SidekiqStatus worker.

Within worker, should include SidekiqStatus::Worker (don't inherit from ActiveJob::Base, it's denid by Sidekiq::Worker). See below.

The adapter:

module ActiveJob
  module QueueAdapters
    # == SidekiqStatus adapter for Active Job
    #
    # Simple, efficient background processing for Ruby. Sidekiq uses threads to
    # handle many jobs at the same time in the same process. It does not
    # require Rails but will integrate tightly with it to make background
    # processing dead simple.
    #
    # Read more about Sidekiq {here}[http://sidekiq.org].
    # And SidekiqStatus {here}[https://github.com/cryo28/sidekiq_status]
    #
    # To use SidekiqStatus set the queue_adapter config to +:sidekiq_status+.
    #
    #   Rails.application.config.active_job.queue_adapter = :sidekiq_status
    class SidekiqStatusAdapter
      def enqueue(job) #:nodoc:
        #Sidekiq::Client does not support symbols as keys
        job.provider_job_id = Sidekiq::Client.push \
          "class"   => job_class(job),
          "wrapped" => job.class.to_s,
          "queue"   => job.queue_name,
          "args"    => [ job.serialize ]
      end

      def enqueue_at(job, timestamp) #:nodoc:
        job.provider_job_id = Sidekiq::Client.push \
          "class"   => job_class(job),
          "wrapped" => job.class.to_s,
          "queue"   => job.queue_name,
          "args"    => [ job.serialize ],
          "at"      => timestamp
      end

      class JobWrapper #:nodoc:
        def perform(job_data)
          Base.execute job_data.merge("provider_job_id" => jid)
        end
      end

      private
        def job_class(job)
          if job.class < SidekiqStatus::Worker
            JobWrapper
          else
            ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper
          end
        end
    end
  end
end

Config your active_job in config/application.rb:

module MyApp
  class Application < Rails::Application
    config.active_job.queue_adapter = :sidekiq_status
  end
end

Worker code:

class MyWorker
  include SidekiqStatus::Worker

  def perform(*args)
    self.total = 5
    at(0, 'init')
    # do somethine
    at(1, 'xxxx'
    # ...
  end
end

Enqueues job:

MyWorker.perform_async(user)

Only a few cases tested, maybe has problems.