Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create pull request for cancel functionality of Active Job #24

Open
oveits opened this issue Feb 5, 2016 · 1 comment
Open

Create pull request for cancel functionality of Active Job #24

oveits opened this issue Feb 5, 2016 · 1 comment

Comments

@oveits
Copy link
Owner

oveits commented Feb 5, 2016

If MyJob < ActiveJob::Base and

myjob=MyJob.perform_later(...)

Then I have added functionality to cancel a job like follows:

myjob.cancel

without the need to jandle job providers like delayed_job or resque or sidekiq.

This functionality needs to be documented and best I should make a proposal to the Rails 5 team (best: a pull request).

@oveits oveits changed the title Create pull request for active_job.cancel Create pull request for cancel functionality of Active Job Feb 5, 2016
@oveits
Copy link
Owner Author

oveits commented Feb 5, 2016

Full patch file:

module ActiveJob
  # Provides behavior for enqueuing and retrying jobs.
  module Enqueuing
    extend ActiveSupport::Concern

    # Includes the +perform_later+ method for job initialization.
    module ClassMethods

      # Dequeues the job to be performed by the queue adapter. Only supported for Delayed::Jobs yet.
      #
      # ==== Examples
      #
      #    my_job_instance.dequeue
      #
      #def dequeue(options={})
      def dequeue()
        run_callbacks :dequeue do
          self.class.queue_adapter.dequeue self
        end
        self
      end

      # returns a list of all instances of the class GeneralJob
      # inspired by: http://stackoverflow.com/questions/6365638/how-to-get-class-instances-in-ruby
      # 
      # ==== Examples
      #
      #    GeneralJob.all
      #
      def all
        listall = []
        ObjectSpace.each_object GeneralJob do |thisjob|
          listall << thisjob
        end
        listall
      end # end def all
    end # module ClassMethods
  end # module Enqueuing

  module Execution

    # is removing the backend job (e.g. Delayed::Job), if it exists and sets the proper status
    #
    # * *Args*    : none
    # * *Returns* :
    #   - +true+ -> the provider_job was found and removed successfully
    #   - +false+ -> provider_job was not found 
    # * *Raises* :
    #   - +ArgumentError+ -> if number of arguments is not 0
    #
    def cancel
      self.class.queue_adapter.dequeue self
    end 
  end # module ExecutionOld

  module Core
    # ID optionally provided by adapter
    attr_accessor :provider_job_id
  end

  module QueueAdapters
    class DelayedJobAdapter
      class << self
        def enqueue(job) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name)
          job.provider_job_id = delayed_job.id
          delayed_job
        end

        def enqueue_at(job, timestamp) #:nodoc:
          delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp))
          job.provider_job_id = delayed_job.id
          delayed_job
        end

        # is removing the backend job (e.g. Delayed::Job), if it exists and sets the proper status
        #
        # * *Args*    : none
        # * *Returns* :
        #   - +true+ -> the provider_job was found and removed successfully
        #   - +false+ -> provider_job was not found 
        # * *Raises* :
        #   - +ArgumentError+ -> if number of arguments is not 0
        #   - +Abort+ -> in case there were more than 1 delayed jobs found for this ActiveJob (points to a bug, if it happens)
        #
        def dequeue(job)
          provider_jobs = Delayed::Job.where(id: job.provider_job_id)
          case provider_jobs.count
          when 1
            provider_jobs[0].delete
            true
          when 0
            false
          else
            abort "There are more than one Delayed::Job.where(id: #{job.provider_job_id}). This should never happen and it looks like a bug."
          end
        end
      end

      class JobWrapper #:nodoc:
        attr_accessor :job_data

        def initialize(job_data)
          @job_data = job_data
        end

        def perform
          Base.execute(job_data)
        end
      end
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant