Could a BackgrounDrb worker do this?

When a user explicitly logs out of my app (by clicking a button that invokes the ‘logout’ action), all the DB records and files they’ve created during their session get deleted. I’m trying to figure out how to do that same thing when users just abandon the site (either by closing the browser or entering a new URL.).

One thought is to use BackgroundDrb for my session store (currently using the default PStore) and have the worker process somehow invoke the logout action (it’s done explicitly via a form_remote_tag submission) on behalf of / masquerading as the user. Could this work?

Thanks,

Bill

Hey Bill-

I don't think backgroundrb is the right tool or this job. Backgroundrb is not a session container so it won't work like you want. The best way to do what you want would be to use the ActiveRecord session store to store your sessions in the db. Then make a cron job that wakes up ever 10 minutes or so and deletes the session and objects that folks abandoned. You would need some sort of heuristic to decide how long to wait before you call a session 'abandoned' and delete it.

-Ezra

Hi Ezra,

Ezra Zygmuntowicz wrote:

Backgroundrb is not a session container
so it won't work like you want.

I don't understand what you mean by 'not a session container,' It's listed as an alternative to PStore and ActiveRecord session stores. I really don't know much of anything about session management mechanisms and I have a feeling you're telling me something I need to understand. Could you say more about this please?

The best way to do what you want would be
to use the ActiveRecord session store to store
your sessions in the db. Then make a cron job
that wakes up ever 10 minutes or so and deletes
the session and objects that folks abandoned.

The documentation on the wiki (I think) says that cron jobs are very high cost compared to Backgroundrb and gives the impression that Backgroundrb is a lightweight alternative that combines the session store mechanism with cron-like worker processes. I misunderstood?

The main issue I'm trying to get my arms around is how to get at the data the user entered during their session so it can be deleted. Is it possible for the cron job to access the application data? Do you know of any online examples of how that would be done? The following happens when the user explicitly logs out of the app.

def cleanup
    emrec = find_emrec # get the parent record; its id is stored in a session variable
    files = Tempfilerec.find(:all, :conditions => ["emrec_id = ?", emrec.id]) # get the names of all the files the visitor has created
    files.each {|file| FileUtils.rm "public/#{file.filename}" } # delete the files
    emrec.destroy # delete all the db records the visitor has created
    reset_session
  end

I need to do the same processing when the user abandons a session. Can I do this from a script run as a cron job?

Thanks very much for any help understanding how to go about this.

Best regards,
Bill

Hi~

Hi Ezra,

Ezra Zygmuntowicz wrote:

Backgroundrb is not a session container
so it won't work like you want.

I don't understand what you mean by 'not a session container,' It's listed
as an alternative to PStore and ActiveRecord session stores. I really don't
know much of anything about session management mechanisms and I have a
feeling you're telling me something I need to understand. Could you say
more about this please?

  I think there is some confusion n the wiki. There is a DRb session container that you can use that comes with rails. BackgrounDRb is a rails plugin that I wrote for running long background tasks with hook for ajax progress bars or status updates in the browser. BackgrounDRb has nothing to do with sessions and will not work as a session container. For session containers here are your main options:

Pstore: filesystm storage, slowest of all the session containers.

ActiveRecord session store: stores sessions in a database table. Fast

DRb session store: similar speed to ActiveRecord store but not as robust and has less features. I have never used this one for production and i dont think that many people use this one.

Memcached: fastest session container but requires running extra daemons. Use this if you need to scale to the moon.

Stefan Kaeys Mysql session store: Faster then AR session store because its direct sql access. worth lookin at.

Out of all these the one I usualy use most is ActiveRecord store. Its very easy to set up and is pretty fast. This is the one I recommend. You can always change it later if it becomes necessary but it will handle all but the hugest sites fast.

The best way to do what you want would be
to use the ActiveRecord session store to store
your sessions in the db. Then make a cron job
that wakes up ever 10 minutes or so and deletes
the session and objects that folks abandoned.

The documentation on the wiki (I think) says that cron jobs are very high
cost compared to Backgroundrb and gives the impression that Backgroundrb is
a lightweight alternative that combines the session store mechanism with
cron-like worker processes. I misunderstood?

  Backgroundrb does have cron like workers. And you can manage them from your rails app. But it is not a session container. So I think it can work for what you want to do.

The main issue I'm trying to get my arms around is how to get at the data
the user entered during their session so it can be deleted. Is it possible
for the cron job to access the application data? Do you know of any online
examples of how that would be done? The following happens when the user
explicitly logs out of the app.

  Are you marking your records with some kind of identifier so you can delete everything someone created? Or how will you know which objects to delete when you clean up after them?

def cleanup
    emrec = find_emrec # get the parent record; its id is stored in a
session variable
    files = Tempfilerec.find(:all, :conditions => ["emrec_id = ?",
emrec.id]) # get the names of all the files the visitor has created
    files.each {|file| FileUtils.rm "public/#{file.filename}" } # delete
the files
    emrec.destroy # delete all the db records the visitor has created
    reset_session
  end

I need to do the same processing when the user abandons a session. Can I do
this from a script run as a cron job?

Thanks very much for any help understanding how to go about this.

Best regards,
Bill

  If you store your sessions in the ActiveRecord session container you can query it like any other db table. So you can do a query for all the sessions that have no activity for 15 minutes or however long you want. Then use that info to delete the correct records.

  BackgrounDRb can be used to do what you want. But you may want to keep it simple and use script/runner and cron.

-Ezra

Hi Ezra,

Thanks for responding.

Ezra Zygmuntowicz wrote:

I think there is some confusion n the wiki. There is a DRb session
container that you can use that comes with rails. BackgrounDRb is a
rails plugin that I wrote for running long background tasks with hook
for ajax progress bars or status updates in the browser.

The confusion may just be me. I am looking for a way to run a background task that will 'run' for a specified amount of time and then invoke a specified action in a specified controller in my Rails app. The invoked action would be the same one that's invoked when a visitor clicks the 'logout' button.

BackgrounDRb has nothing to do with sessions and will not work
as a session container.

Cool.

Backgroundrb does have cron like workers. And you
can manage them from your rails app.

I think that's all I need.

Are you marking your records with some kind of
identifier so you can delete everything someone
created? Or how will you know which objects
to delete when you clean up after them?

The id of the session's parent record is stored in the session. Each child record is marked in the sense of having a foreign-key field. Is that what you mean?

If you store your sessions in the ActiveRecord session container you
can query it like any other db table. So you can do a query for all
the sessions that have no activity for 15 minutes or however long you
want. Then use that info to delete the correct records.

Do you know of any resources available (online or print) that could help get me started here?

BackgrounDRb can be used to do what you want.

I was just reading (and rereading) the DRb section in AWD, the archives at http://rubyforge.org/pipermail/backgroundrb-devel, and the documentation at http://backgroundrb.rubyforge.org/. I'm hoping I'm not just confusing myself, but could it work like....

1) from the rails app, start a worker for a session with a timeout setting and a controller/action argument
2) every time the visitor interacts with the rails app, reset the worker's timeout
3) when the timeout occurs, the worker invokes the controller/action in the rails app that was passed in at startup.

But you may want to keep it simple and use
script/runner and cron.

Right now it feels simpler, at least conceptually, to just start an external process that's specific to that session and have it 'logout' for the visitor if the visitor doesn't do it themselves. What do you think? Is what I want to do possible?

Thank much for your advice!
Bill

Hi Ezra,

Thanks for responding.

Ezra Zygmuntowicz wrote:

I think there is some confusion n the wiki. There is a DRb session

container that you can use that comes with rails. BackgrounDRb is a

rails plugin that I wrote for running long background tasks with hook

for ajax progress bars or status updates in the browser.

The confusion may just be me. I am looking for a way to run a background

task that will ‘run’ for a specified amount of time and then invoke a

specified action in a specified controller in my Rails app. The invoked

action would be the same one that’s invoked when a visitor clicks the

‘logout’ button.

Gotcha

BackgrounDRb has nothing to do with sessions and will not work

as a session container.

Cool.

Backgroundrb does have cron like workers. And you

can manage them from your rails app.

I think that’s all I need.

Could be for sure.

Are you marking your records with some kind of

identifier so you can delete everything someone

created? Or how will you know which objects

to delete when you clean up after them?

The id of the session’s parent record is stored in the session. Each child

record is marked in the sense of having a foreign-key field. Is that what

you mean?

Yup this is what I meant. Good.

If you store your sessions in the ActiveRecord session container you

can query it like any other db table. So you can do a query for all

the sessions that have no activity for 15 minutes or however long you

want. Then use that info to delete the correct records.

Do you know of any resources available (online or print) that could help get

me started here?

http://wiki.rubyonrails.org/rails/pages/HowtoChangeSessionStore

BackgrounDRb can be used to do what you want.

I was just reading (and rereading) the DRb section in AWD, the archives at

http://rubyforge.org/pipermail/backgroundrb-devel, and the documentation at

http://backgroundrb.rubyforge.org/. I’m hoping I’m not just confusing

myself, but could it work like…

  1. from the rails app, start a worker for a session with a timeout setting

and a controller/action argument

  1. every time the visitor interacts with the rails app, reset the worker’s

timeout

  1. when the timeout occurs, the worker invokes the controller/action in the

rails app that was passed in at startup.

Something like this could work. The main issue is that backgroundrb doesn’t use http so it can’t really call a controller method in your app for you. You could just put a similar action in your worker class and call it there. But I think the best way for what you want to do would be to just stick with script/runner and a cron job. Lets assume that you want to log someone out if they haven’t had any activity on their session in 15 minutes or more.

  1. Setup a method in your User model that will do a find on the updated_at column in the session table and return all sessions that were last updated more then 15 minutes ago. Then iterate over these records and delete them from the sessions table. Lets call this method ‘session_sweep’

  2. You setup a cron job that runs every 15.

  3. Use this as the command for cron to run:

  4. /usr/local/bin/ruby /full/path/to/yourapp/script/runner ‘User.session_sweep’

But you may want to keep it simple and use

script/runner and cron.

Right now it feels simpler, at least conceptually, to just start an external

process that’s specific to that session and have it ‘logout’ for the visitor

if the visitor doesn’t do it themselves. What do you think? Is what I want

to do possible?

Thank much for your advice!

Bill

Ok all that being said, BackgrounDRb can do the same thing for you. But it does add another daemon you have to run all the time. So for a simple wake up every 15 minutes and call script/runner then quite, you will save cpu and memory. Also cron has been in use for many many years and has much more precise control over how you can specify timing rules. If you decide to go the BackgrounDRb route then please join the mailing list for it and I'll do my best to help you along.

*Mailing list: http://rubyforge.org/mailman/listinfo/backgroundrb-devel

Cheers-

-Ezra

Hi Ezra,

Ezra Zygmuntowicz wrote:

Ok all that being said, BackgrounDRb can do
the same thing for you. [...] If you decide to go
the BackgrounDRb route then please join the
mailing list for it and I'll do my best to help you along.

I've joined the BackgrounDRb mailing list and have responded there. Thanks!

Bill

Hey Joe -

But I think the best way for what you want to do
would be to just stick with script/runner and a cron job. Lets assume
that you want to log someone out if they haven't had any activity on
their session in 15 minutes or more.

1. Setup a method in your User model that will do a find on the
updated_at column in the session table and return all sessions that
were last updated more then 15 minutes ago. Then iterate over these
records and delete them from the sessions table. Lets call this
method 'session_sweep'

2. You setup a cron job that runs every 15.

3. Use this as the command for cron to run:

4. /usr/local/bin/ruby /full/path/to/yourapp/script/runner
'User.session_sweep'

I'm thinking about using BackgrounDRb too. I would probably need it to
run once every 5 minutes (to send out email and to check for records
older than 5 minutes).

Do you think it'd be better to use a cron job for this, or would
backgrounDRb be good for this? The background tasks I want to run are
not long-running tasks, so would it be better to just use a cron job?

First I want to say that I'm a big fan of Ezra & brb, but of late it isn't getting much attention - so if you run into problems/bugs you may not get much support.

Additionally I've had a terrible time getting a brb deploy stable - be that application of brb issues I'm not sure - but my test coverage is quite good and brb is reporting that it can't find worker tasks and will die. Monit has been deployed to keep brb up, but there also seems to be a bug where the ppid written isn't always the actual running brb process id - so monit launches another instance (and well, eventually I'll have a few running...)

Having said the above, many people are running brb it quite nicely...

Myself I may be turning to cron as I don't need the app_server to deliver or communicate with workers.

hopefully the above arms you with more info for your decision making.

I would suggest you read over the traffic on the brb mailing list[1].

cheers,
Jodi

[1] http://rubyforge.org/pipermail/backgroundrb-devel/