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
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. On 2/24/06, Greg Freemyer <greg.freemyer@gmail.com> wrote:> 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 > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
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 On 23 Feb 2006, at 23:33, Greg Freemyer wrote:> 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 > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
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
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 On 24 Feb 2006, at 00:00, Greg Freemyer wrote:> 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 > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
On 2/23/06, Paul Ingles <paul@engross.org> wrote:> 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, > PaulThanks 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
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 On 2/24/06, Paul Ingles <paul@engross.org> wrote:> 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 > > On 24 Feb 2006, at 00:00, Greg Freemyer wrote: > > > 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 > > _______________________________________________ > > 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 >
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:> 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 > > > On 2/24/06, Paul Ingles <paul@engross.org> wrote: > > 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 > > > > On 24 Feb 2006, at 00:00, Greg Freemyer wrote: > > > > > 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 > > > _______________________________________________ > > > 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 > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Greg Freemyer The Norcross Group Forensics for the 21st Century