1

I have a simple SuckerPunch job, I am trying to make it so only one job runs at any given time. Struggling to work it out tried playing with Celluloid and Ruby concurrency

What I have

DataChangeJob.new.async.perform

with

class DataChangeJob
  include SuckerPunch::Job
  def perform
    value = Random.rand
    SuckerPunch.logger.info ("starting #{value}")
    sleep(5)
    SuckerPunch.logger.info ("running data change #{value}")
  end
end
dboyd68
  • 1,104
  • 15
  • 33

1 Answers1

1

If you define to have only one worker, that would achieve what you want imho. By default SuckerPunch assumes two workers. So explicitly define 1 as follows:

class DataChangeJob
  include SuckerPunch::Job
  workers 1

  def perform
    value = Random.rand
    SuckerPunch.logger.info ("starting #{value}")
    sleep(5)
    SuckerPunch.logger.info ("running data change #{value}")
  end
end

You are making me curious: why do you need this constraint?

[UPDATE] While SuckerPunch does allow 1 worker, celluloid does not. So you are back to using mutexes.

class DataChangeJob
  include SuckerPunch::Job

  def initialize
    @@mutex = Mutex.new 
  end

  def perform
    @@mutex.lock
    begin
      value = Random.rand
      SuckerPunch.logger.info ("starting #{value}")
      sleep(5)
      SuckerPunch.logger.info ("running data change #{value}")
    end
  ensure
    @@mutex.unlock
  end   
end

This is just a quick write-up. Assuming all jobs are instances of DataChangeJob, we use a mutex on class level. Locking the mutex will attempt to lock the mutex, and wait until the mutex is free. The ensure block will make sure we unlock the mutex no matter what happened.

This will make sure only one DataChangeJob can run at a time. A bit defeating the advantage celluloid gives you :)

nathanvda
  • 49,707
  • 13
  • 117
  • 139
  • Tried that, there is a validation rule to ensure you have at least two workers. I might be trying to make Suckerpunch do something it isn't intended to do. But my goal is build an api that fires off a 'job' however I need to ensure if the job is running that no other jobs run. (I don't actually care if those other jobs run again) – dboyd68 May 06 '14 at 00:25
  • Mmmmm that is weird. In the code i only see an exception if `num_workers < 1`. What error do you get? – nathanvda May 06 '14 at 01:30
  • I get ArgumentError: minimum pool size is 2 from /home/a/.rvm/gems/ruby-2.0.0-p247@my/gems/celluloid-0.15.2/lib/celluloid/pool_manager.rb:14:in `initialize' – dboyd68 May 06 '14 at 08:03
  • Ok: that error comes from celluloid, the library suckerpunch uses. I edited my answer and propose to use a mutex instead. – nathanvda May 06 '14 at 09:05