Backgroundrb

Backgroundrb is driving me crazy.
I am trying to schedule a simple job - extremely simple so that I can
understand how it thinks. I have gone through the the
Tutorial/Notes/Examples at:
http://backgroundrb.rubyforge.org/
carefully. Somehow things are not clicking:

Have installed backgrounddb 1.0.4 along with cronic 0.2.3 and packet
0.1.9 gems.

Here is my HelloWorker class in the lib/workers directory of Rails root:

class HelloWorker < BackgrounDRb::MetaWorker
set_worker_name :hello_worker
def create(args = nil)

end

def yml_schedule
puts “yml_schedule - Before”
Post.say_hello
puts “yml_schedule - After”
end
end

Here is my backgroundrb.yml in the config directory;


:backgroundrb:
:port: 11006
:ip: 0.0.0.0
:schedules:
:hello_worker:
:yml_schedule:
:trigger_args: */60 * * * * *

And Here is the Post model from a simple RoR rubyweblog app - this is in
app/models directory and is in post.rb file:

class Post < ActiveRecord::Base

class << self
def say_hello
logger.info ‘Hello from Post model’
end
end

end

As you can see, I am trying to coax backgroundrb to log ‘Hello from Post
model’ every minute and also hoping that “yml schedule - Before” and
“yml schedule after” is going to be printed along with it.

I am getting rather strange output:

  1. backgroundrb_debug_11006.log file contains the following:

yml_schedule - Before
yml_schedule - After

This is only once and does not repeat.

  1. The development.log file shows the following:

allow_concurrency=true
Defined connections:
{“ActiveRecord::Base”=>#<ActiveRecord::Base::ConnectionSpecification:0xb7767ea8
@config={:socket=>“/var/run/mysqld/mysqld.sock”, :encoding=>“utf8”,
:password=>nil, :adapter=>“mysql”, :username=>“root”,
:database=>“rubyweblog_dev”}, @adapter_method=“mysql_connection”>}
Active connections: {}
Active connection name: ActiveRecord::Base
SQL (0.000219) SET NAMES ‘utf8’
SQL (0.000124) SET SQL_AUTO_IS_NULL=0
SQL (0.000083) BEGIN
BdrbJobQueue Load (0.000660) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000119) COMMIT
SQL (0.000224) BEGIN
BdrbJobQueue Load (0.000802) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000176) COMMIT
Hello from Post model
SQL (0.000188) BEGIN
BdrbJobQueue Load (0.000571) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000114) COMMIT
SQL (0.000203) BEGIN
BdrbJobQueue Load (0.000639) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000106) COMMIT
SQL (0.000204) BEGIN
BdrbJobQueue Load (0.000593) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000104) COMMIT
SQL (0.000200) BEGIN
BdrbJobQueue Load (0.000610) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000103) COMMIT
SQL (0.000206) BEGIN
BdrbJobQueue Load (0.000594) SELECT * FROM bdrb_job_queues WHERE
(bdrb_job_queues.taken = 0 AND bdrb_job_queues.worker_name =
‘hello_worker’) LIMIT 1 FOR UPDATE
SQL (0.000105) COMMIT

As you can see this also contains ‘Hello from Post model’ ONCE. And the
whole BdrdJobQueue Load keeps repeating every minute, but will not print
the output message. I am not sure why the class method say_hello is not
called from within the hello_worker every minute?

Please help.

Thanks.

Bharat

Hi,

Backgroundrb is driving me crazy.
I am trying to schedule a simple job - extremely simple so that I can
understand how it thinks. I have gone through the the
Tutorial/Notes/Examples at:
http://backgroundrb.rubyforge.org/
carefully. Somehow things are not clicking:

Thats just too awful, read below to make your mind steady. :wink:

end

As you can see, I am trying to coax backgroundrb to log ‘Hello from Post
model’ every minute and also hoping that “yml schedule - Before” and
“yml schedule after” is going to be printed along with it.

There is a small problem there, logger is not initialized in the model
and hence you are unable to see the print messages. Try replacing
logger.info with puts and you can see your messages appearing on the
console (assuming you are not daemonizing backgroundrb, but letting it
run on the foreground).

I am getting rather strange output:

  1. backgroundrb_debug_11006.log file contains the following:

yml_schedule - Before
yml_schedule - After

If you are looking for log messages “backgroundrb_debug_xxx.log” is
wrong file to see, your log messages will appear in
“backgroundrb_xxx.log” file.

This is only once and does not repeat.

Yup and it should not repeat, as I said before and
backgroundrb_debug_xxx.log is for showing unhandled exceptions or
server errors and stuff like that. Messages for logger.info() won’t
end up there.

Hello Hemant,
Thanks for the quick response as always, much appreciated.
You wrote below:

There is a small problem there, logger is not initialized in the model
and hence you are unable to see the print messages. Try replacing
logger.info with puts and you can see your messages appearing on the
console.

Actually this is not true. The logger object is available in the Rails
environment practically everywhere. See Obie F.'s excellent text
“The Rails Way” page 18. You are partially correct though. If I was
using pure Ruby or IRB then I will have to “require” the logger object.
My assumption is that Backgroundrb interfaces seamlessly with a Rails
application and therefore has access to its environment. If there are
any limitations then please point those out since I may be going down
the wrong way.

I have been able to get the scheduler going both using the cron style
and using add_periodic_timer. I show the code below:

class HelloWorker < BackgrounDRb::MetaWorker
set_worker_name :hello_worker
def create(args = nil)
add_periodic_timer(10) do
Post.say_hello
end
end

def yml_schedule

logger.info “Hello from yml_schedule”

Post.say_hello

end

end

class Post < ActiveRecord::Base

class << self
def say_hello
logger.info ‘Hello from Post model’
end
end

end

One thing that I learned the hard way is that the key to make sure that
the scheduled workers work correctly in Backgroundrb is that the
backgroundrb debug log file is empty! That is, if there are any errors
anywhere including other workers that are loaded then the scheduler
stops working! I was following the tutorial in the Advanced Rails
Recipes book that you wrote with Greg Pollock and the BillingWorker was
creating problems. I deleted it and everything started to work right.

I have one request. Since an end-to-end tutorial in Backgroundrb
current release is not available, it would be great if you can publish
one. I own the Advanced Rails Recipes book and was using your recipe
that I mention above, but since the Backgroundrb API has changed, it is
creating problems. Do you think that you can publish the updated recipe
code for the current version of Backgroundrb at the book’s website so
that we can use it in its entirety and not get tripped up? I can help
you verify it and test it.

I am upgrading a Rails 1.2.6 application to Rails 2.1.0. It uses
Backgroundrb and therefore I have to upgrade to the latest release
right?

You wrote:
(assuming you are not daemonizing backgroundrb, but letting it

run on the foreground).

I don’t understand this. Can you please clarify.

You wrote:

Yup and it should not repeat, as I said before and
backgroundrb_debug_xxx.log is for showing unhandled exceptions or
server errors and stuff like that. Messages for logger.info() won’t
end up there.

So following up with this. If the scheduler is working right, should we
not see these logger messages in the backgroundrb_xxx file (not the
debug file)?

Regards,

Bharat

Hi,

Actually this is not true. The logger object is available in the Rails
environment practically everywhere. See Obie F.'s excellent text
“The Rails Way” page 18.
You are partially correct though. If I was
using pure Ruby or IRB then I will have to “require” the logger object.
My assumption is that Backgroundrb interfaces seamlessly with a Rails
application and therefore has access to its environment. If there are
any limitations then please point those out since I may be going down
the wrong way.

Well, put following code in root directory of your rails app and run it:

require File.join(File.dirname(FILE),“config”,“environment”)
t_user = User.find_by_id(1)
logger.info(“Hello World : user is : #{t_user.login}”)

You will find that, even though AR is logging the query, next line
throws error:

undefined local variable or method `logger’ for main:Object (NameError)
zsh: exit 1 ruby lib/foo.rb

BackgrounDRb does exactly that for loading rails environment and
hence, you don’t have access to logger object thats defined in
rails(although, you do have access to logger which is specifically for
backgroundrb).

end
def say_hello
stops working! I was following the tutorial in the Advanced Rails
you verify it and test it.
I am sorry about that and I am working with Mike for updating the
recipe. At least, pdf version should be released with updated text.

I am upgrading a Rails 1.2.6 application to Rails 2.1.0. It uses
Backgroundrb and therefore I have to upgrade to the latest release
right?

Not necessarily, but I do recommend to upgrade anyways. Just keep
two things in mind:

  1. Do not use inbuilt cache object, its a toy (i hate myself for
    writing it). But thankfully, backgroundrb comes with mechanism to
    replace that cache with memcache(refer the docs, its really trivial).
    Stability should increase by leap and bounds.
  2. Avoid spawning workers, unless you must.

I don’t understand this. Can you please clarify.

I meant, if you run bdrb with “./script/backgroundrb start” bdrb
server gets daemonized and all the puts statements will be gobbled up.

Hello Hemant,
Thanks for the quick response. You wrote:

“I meant, if you run bdrb with “./script/backgroundrb start” bdrb
server gets daemonized and all the puts statements will be gobbled up.”

That is how I have been starting it! You mean there is an alternate
way? Please let me know. Where on the Backgroundrb site do you mention
that? I may not be paying enough attention while reading it.

Bharat

BackgrounDRb does exactly that for loading rails environment and
hence, you don’t have access to logger object thats defined in
rails(although, you do have access to logger which is specifically for
backgroundrb).

I figure this out, by logging in both Rails and Backgroundrb. Thanks
for the info.

I am sorry about that and I am working with Mike for updating the
recipe. At least, pdf version should be released with updated text.

I have the printed book, so any way that you can get this to those of us
who bought the printed copy only?

  1. Avoid spawning workers, unless you must.

Can yo give an example of this in code so that I know what not to do?

Thanks.

Even the deploy.rb file for Capistrano has the following code:

desc “Start backgroundrb service”
task :backgroundrb_start, :roles => :app do
run “RAILS_ENV=#{rails_env} nohup #{current_path}/script/backgroundrb
start 2>&1 1>/dev/null”
end

desc “Stop backgroundrb service”
task :backgroundrb_stop, :roles => :app do

echo at end makes the return code always 0

run “test -f #{current_path}/log/backgroundrb.pid &&
#{current_path}/script/backgroundrb stop; echo”
end

desc “Restart backgroundrb service”
task :backgroundrb_restart, :roles => :app do
backgroundrb_stop
backgroundrb_start
end

Is that a bad idea? Is there a better way?

On Thu, Aug 14, 2008 at 1:03 AM, Bharat R.
[email protected] wrote:

Hello Hemant,
Thanks for the quick response. You wrote:

“I meant, if you run bdrb with “./script/backgroundrb start” bdrb
server gets daemonized and all the puts statements will be gobbled up.”

That is how I have been starting it! You mean there is an alternate
way? Please let me know. Where on the Backgroundrb site do you mention
that? I may not be paying enough attention while reading it.

Nothing much, just:

./script/backgroundrb start

It will daemonize the process in background and redirect STDOUT,STDERR
and stuff.

Also, about the book, I don’t really know, If it will be possible to
give away pdf version to those who bought printed copy, I will see
what can be done. If possible, we can just distribute that chapter.