Forum: Ruby on Rails Session Based Record Locking - Solutions?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
25bbc96d9c53647354cb724e744b2222?d=identicon&s=25 Greg Freemyer (Guest)
on 2006-02-24 00:36
(Received via mailing list)
All,

I've written a simple job/opportunity tracking database app via RoR.

I have about 10 internal users.

Sometimes 2 people will want to update the same record at more or less
the same time and they collide.

In particular user 1 may edit a record, then get distracted, and
finally an hour later they click save.

During that hour user 2 may have pulled up the record, edited it, and
saved it.  The later save by user 1 undoes user 2's changes.

I can't think of any web technology that would help with this but ...

I'm hoping that a session lock could somehow be used.  Maybe a
background Java Script app or something could somehow keep a session
lock instantiated and if the browser is killed the seesion lock is
released?

Ideas welcome.

Thanks
Greg
--
Greg Freemyer
The Norcross Group
Forensics for the 21st Century
0ca6dacbed829354319d844346cbd5f3?d=identicon&s=25 Dan Sketcher (Guest)
on 2006-02-24 00:45
(Received via mailing list)
Hi Greg,

In a similar situation I have simply used the ActiveRecord::Locking
module by adding a lock_version column to the table(s) in question and
handling the ActiveRecord::StaleObjectError if/when it is thrown. It's
pretty simple really and will probalby be a lot easier to implment
than a global application mutex.

Anyway, HTH,
Dan.
013132bb011e736d6befbab3b1fb9fb7?d=identicon&s=25 Paul Ingles (Guest)
on 2006-02-24 00:54
(Received via mailing list)
Greg,

I don't really have something to add having read Dan's response --
looks like ActiveRecord already includes the approach I was going to
suggest. In case you weren't aware of this kind of system,
essentially it involves keeping a timestamp with the record that is
updated everytime the record is. Then, when performing an update, the
system checks whether the timestamp on record matches the one that
the updater has -- if not there's been an update already and you'll
need to handle it.

If you wanted to you could perhaps have something poll every 10
seconds or so (and on saving of course), then update where necessary.
Perhaps warn the user, update fields that haven't changed, that kinda
thing.

Regards,
Paul
25bbc96d9c53647354cb724e744b2222?d=identicon&s=25 Greg Freemyer (Guest)
on 2006-02-24 01:03
(Received via mailing list)
On 2/23/06, Dan Sketcher <dansketcher@gmail.com> wrote:
> Hi Greg,
>
> In a similar situation I have simply used the ActiveRecord::Locking
> module by adding a lock_version column to the table(s) in question and
> handling the ActiveRecord::StaleObjectError if/when it is thrown. It's
> pretty simple really and will probalby be a lot easier to implment
> than a global application mutex.
>
> Anyway, HTH,
> Dan.

To get an failed update (with error message?) should I have to do
anything besides have a lock_version field?  Should it work in devel
mode?

I ask because I already have a lock_version field in my table.

In my dev instance I just tried:

user 1: edit record, edit comment to say "Should Fail"
user 2: edit record, edit comment to say "Should Succeed"
user 2: click save, comment says "Should Succeed"
user 1: click save, comment says "Should Fail"

Obviously this is not what you described.  For my 2 users I was using
a single client, but one was firefox and one was IE.  I assume that
should qualify as seperate users.

Thanks
Greg
013132bb011e736d6befbab3b1fb9fb7?d=identicon&s=25 Paul Ingles (Guest)
on 2006-02-24 01:06
(Received via mailing list)
Greg,

I've only been using Ruby and Rails for a relatively short while, but
I believe what ActiveRecord does depends on how you call it's methods.

I believe you'll have to do something like

record = Record.find_by_id(1)
record.save!

Suffixing it with an exclamation mark should cause an error to be
raised should it fail.

Is that what you mean? Incidentally, it should be relatively trivial
to put together a unit test for this, probably a good way to go --
verify assumptions on how ActiveRecord deals with this stuff.

Regards,
Paul
25bbc96d9c53647354cb724e744b2222?d=identicon&s=25 Greg Freemyer (Guest)
on 2006-02-24 01:15
(Received via mailing list)
On 2/23/06, Paul Ingles <paul@engross.org> wrote:
> Suffixing it with an exclamation mark should cause an error to be
> raised should it fail.
>
> Is that what you mean? Incidentally, it should be relatively trivial
> to put together a unit test for this, probably a good way to go --
> verify assumptions on how ActiveRecord deals with this stuff.
>
> Regards,
> Paul

Thanks Paul, but I'm still having problems.

My controller's update method does not call save.

It is calling   @record.update_attributes(params[:record]).

If I try to add an ! on the end I get a syntax error.

I don't remember replaceing save with update_attributes, but maybe one
of my coworkers did that.  Do you mind looking at your update method
and seeing what call it is using to update the record?

Thanks again
Greg
--
Greg Freemyer
The Norcross Group
Forensics for the 21st Century
0ca6dacbed829354319d844346cbd5f3?d=identicon&s=25 Dan Sketcher (Guest)
on 2006-02-24 01:15
(Received via mailing list)
Ack, that's probably because on the post of the User1 comment, the
model is being reloaded, so it gets the new lock version number which
it then happily increments. By default, this will only stop the case
when 2 people press save at the same instant and the following
happens:

1. user1 loads modelA (lock version 0)
2. user2 loads modelA (lock version 0)
3. users 1&2 change data as they need to within their own models
4. user1 saves modelA to table (incrementing lock version to 1)
5. user2 saves modelA but lock version of model (0) does not match
that in table (1) so exception is thrown.

A little but more work will be needed by the looks for you.. Basically
you will need to get out the lock_version and pass it as a param to
your post, so that on the receiving action you can get the
lock_version from the DB before you update and compare to you posted
value, so you can fail fast on the action before you attempt to hit
the db.

Sorry bout that.

Dan
25bbc96d9c53647354cb724e744b2222?d=identicon&s=25 Greg Freemyer (Guest)
on 2006-02-24 01:21
(Received via mailing list)
I think I'm done for the night.  I'll look into this tomorrow with fresh
eyes.

On 2/23/06, Dan Sketcher <dansketcher@gmail.com> wrote:
> 5. user2 saves modelA but lock version of model (0) does not match
>
> >
> > Regards,
> > >> handling the ActiveRecord::StaleObjectError if/when it is thrown.
> > >
> > > a single client, but one was firefox and one was IE.  I assume that
> > Rails mailing list
> > Rails@lists.rubyonrails.org
> > http://lists.rubyonrails.org/mailman/listinfo/rails
> >
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Greg Freemyer
The Norcross Group
Forensics for the 21st Century
This topic is locked and can not be replied to.