how to get a backgroundrb worker to delete itself?

Hi,

I am trying to get a worker instance to delete itself at the end of its do_work method. I have my main rails app creating these workers upon certain incoming http requests to parse some XML files, and once the parsing is complete, I would like the worker to delete itself, so that I don't need to try and manage several workers within the main rails app.

I was trying to accomplish this with the following line: ::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key. However, when I tried this, I get the following errer:

20070405-13:15:15 (19653) In do work 20070405-13:15:18 (19653) You have a nil object when you didn't expect it! The error occured while evaluating nil.shutdown - (NoMethodError)

It seems that perhaps this method of trying to access the job key of the current instance is not working. Has anybody else done something similar, or have any suggestions for a different method to accomplish this?

Thanks,

Simon

On a similar note, is there any way to monitor the number of worker instances that are running? What I am after is to ensure that worker instances are being deleted, and so I would like to be able to keep an eye on when new instances are created, and when they are deleted.

Thanks again,

Simon

Hi Simon !

Well, I'm, at the moment , trying to do the same think !! Looks like calling self.delete at the end of the do_work method of a worker is a bad idea ... In fact, a worker cannot delete itself, looks like. What I'm thinking right now would be a sort of ... worker that would act has a cleaner ...

Let say, you have a worker that do some email check.

Step1 -> an entry is created in a jobs table with job.cmd = "command to run the email check", job.key_job = " unique id for this job" and job.status = "Waiting" Step2 -> you have a schedule worker that every 30 minutes, for example, look at the jobs table, and create worker that have the waiting status .... ( so 1 row in the jobs table becomes a worker soon or later) Step3 -> every "waiting" worker that are now running can then update the "jobs" table to say "hey I'm finish" so job.status = "finished" Step4 -> the cleaner (the schedule worker that wakes up every 30 minutes) re-check for "Waiting jobs" but also look for "finished jobs" and clean them ... 'cos a woker can clean another one ...

Don't know if that make sence ... it is just an "idea" that i'm having right now ... (and it's 2h00 - not 14h00 !- over here in France :wink: )

Anyway, I might try to implement such a "job cleaner" tomorrow and have a try ...

PS : BUT IF SOMEONE'S GOT AN IDEA ON HOW A WORKER CAN KILL HIMSELF ... I WOULD RATHER TAKE IT !

Jules

Hi Jules,

In fact, a worker cannot delete itself, looks like.

It definitely can. I use the following two lines to do it. The first makes sure the database connection doesn't hang around. The second line looks just like Simon's and it works.

ActiveRecord::Base.connection.disconnect! ::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key

Hi Simon,

Simon wrote:

I was trying to accomplish this with the following line: ::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key.

That looks correct.

However, when I tried this, I get the following errer:

20070405-13:15:15 (19653) In do work 20070405-13:15:18 (19653) You have a nil object when you didn't expect it! The error occured while evaluating nil.shutdown - (NoMethodError)

The error says you're calling a 'shutdown' method on an object that doesn't exist. Maybe you could show us some code?

Bill

Hi Bill,

Thanks for the reply. I tried the "::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key " but I get the same error as Simon : "The error occured while evaluating nil.shutdown"

now here is the worker :

********* worker code starts here **************

class ProgressWorker < BackgrounDRb::Worker::RailsBase

attr_accessor :temp_key

def do_work(args)

    cmdoutput =     results[:worker_status] = false.to_s

    filefrom = "video.mov"     fileto = "video.flv"

    encode_cmd='ffmpeg -i '+filefrom+' -b 600k -r 24 -ar 22050 -ab 96 '+fileto

    IO.popen(encode_cmd).each do |line|      cmdoutput << line      results[:worker_result] = cmdoutput     end

    results[:worker_status] = true.to_s     ActiveRecord::Base.connection.disconnect!     ::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key

  end end

ProgressWorker.register

********* worker code ends here **************

control calls this worker with :

::MiddleMan.new_worker(:class => :progress_worker)

Now, I'm trying to understand what is going ... :

Is this worker properly registered ??? ( I have ProgressWorker.register after (at the end, end :wink: ) the class declaration in ProgressWorker.rb ...) @_job_key is an instance variable but ... is not defined anywhere ? is @_job_key automatically created when a worker is called ? if so .. may be I should specify a :job_key when creating it ?

Thanks for all your help !

Julien

yo !

Some improuvment ... but not yet finished ...

when I logged the @_job_key I receive ... an error complaining about nil string ... I looked in the worker.rb code and found .... @jobkey ... so I gave it a try and tada !

when i do : logger.error(@jobkey) { "Job Key called with @jobkey : "+@jobkey } I get 20070416-01:34:00 (1269) Job Key called with @jobkey : 34b21fe088389b080578fd83dc1b47ea

but when I do : logger.error(@jobkey) { "Job Key called with @jobkey : "+@_job_key } I get 20070416-01:34:00 (1269) can't convert nil into String - (TypeError)

So sounds liek @_job_key does not exists ... but @jobkey does ...

(But sorry simon, yhis does not resolve the .shutdown nil for the moment ... I keep seraching ...)

jules

Me again .... more testing going on ...

in the worker, I do : logger.error(@jobkey) { ::BackgrounDRb::MiddleMan.instance.jobs}

when I look at the log I see :

backgroundrb_logger#<Slave:0x24caef8>backgroundrb_results#<Slave: 0x24b6318>

Looks like the only workers available are the logger and the result .... where is my worker ??? I understand now why we get :

You have a nil object when you didn't expect it! The error occurred while evaluating nil.shutdown - (NoMethodError)

-> there no job with my job_key !

I'm lost ....

Hi Jules

Jules wrote:

I tried the "::BackgrounDRb::MiddleMan.instance.delete_worker @_job_key " but I get the same error as Simon : "The error occured while evaluating nil.shutdown"

now here is the worker : control calls this worker with :

::MiddleMan.new_worker(:class => :progress_worker)

Now, I'm trying to understand what is going ... :

Is this worker properly registered ??? ( I have ProgressWorker.register after (at the end, end :wink: ) the class declaration in ProgressWorker.rb ...) @_job_key is an instance variable but ... is not defined anywhere ? is @_job_key automatically created when a worker is called ? if so .. may be I should specify a :job_key when creating it ?

I start the worker with: session[:job_key] = MiddleMan.new_worker(....

Maybe that's it?

hth, Bill

Hi Bill,

I will have a try with the session[:job_key] but ...

Looks lile self.delete in the do_work method do the job ... Here is a test to confirm this :

At the end of the do_work method I put this :

results[:worker_status] = true logger.error(@jobkey) { "Worker status : "+results[:worker_status].to_s }

And, in return I've got in the log : Worker status : true Now .... if I call this instead :

results[:worker_status] = true self.delete logger.error(@jobkey) { "Worker status : "+results[:worker_status].to_s }

I've got nothing in my log ... why ? Simply because results for worker are kept until worker is deleted. So, if i cannot this "Worker status : true " in the log it is because the worker has been deleted ....

So, my conclusion is : self.delete works :wink:

PS : please let me know if you think that this test does not confirm the fact that calling self.delete, really kill the worker :wink: