What''s the standard way to prevent race conditions in controllers? Say user has many posts. Post controller has action add_post that receives user id, post controller find()s the user and while he is creating the post entry an administrator deletes that user in a separate session. We cannot assume the database checks foreign key integrity. How do you get that right? -- fxn
This isn''t a race condition, this is simply a data integrity issue. We can''t assume the database checks foreign key integrity, but we can program it to do so and that is a practice I recommend because it is efficient and reliable. The only other way to do this is to manage application locks yourself with table columns, RoR will do automated optimistic locking if you had a "lock_version" column to your tables. I doubt this will cover this scenario though since its a delete rather than an update you are concerned about but you''d have to do something similar in concept. On 3/19/06, Xavier Noria <fxn@hashref.com> wrote:> What''s the standard way to prevent race conditions in controllers? > Say user has many posts. > > Post controller has action add_post that receives user id, post > controller find()s the user and while he is creating the post entry > an administrator deletes that user in a separate session. We cannot > assume the database checks foreign key integrity. How do you get that > right? > > -- fxn > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On Mar 19, 2006, at 16:22, Jeremy Huffman wrote:> This isn''t a race condition, this is simply a data integrity issue.I thought of it as a race condition between add_post and delete_user because since add_post is not atomic it can find a user in one line, assume it exists in the next one, and have delete_user break that in between in a separate session. If I could get a lock somehow, I could guarantee that when add_post finishes the user is still there, which is all I am worried about, if when the lock is released delete_user gets the lock and deletes the user and his posts that''s fine (the rendered post listing in the response of add_post might be out of sync, but that''s inherent to web programming). Just for the record this user/post scenario is indeed an imaginary example that depicts the pattern.> We > can''t assume the database checks foreign key integrity, but we can > program it to do so and that is a practice I recommend because it is > efficient and reliable.I am not familiar with database programming. What do you mean? Programming it how? My application uses SQLite if that''s relevant. -- fxn
On 3/19/06, Xavier Noria <fxn@hashref.com> wrote:> On Mar 19, 2006, at 16:22, Jeremy Huffman wrote: > > > This isn''t a race condition, this is simply a data integrity issue. > > I thought of it as a race condition between add_post and delete_user > because since add_post is not atomic it can find a user in one line, > assume it exists in the next one, and have delete_user break that in > between in a separate session. >This isn''t a race condition because it doesn''t lead to a deadlock, its just an example of a stale update that leaves the database in an inconsistent state.> If I could get a lock somehow, I could guarantee that when add_post > finishes the user is still there, which is all I am worried about, if > when the lock is released delete_user gets the lock and deletes the > user and his posts that''s fine (the rendered post listing in the > response of add_post might be out of sync, but that''s inherent to web > programming). > > Just for the record this user/post scenario is indeed an imaginary > example that depicts the pattern. > > > We > > can''t assume the database checks foreign key integrity, but we can > > program it to do so and that is a practice I recommend because it is > > efficient and reliable. > > I am not familiar with database programming. What do you mean? > Programming it how? My application uses SQLite if that''s relevant. >I just mean program it with foreign key constraints. The database is in the best position to handle concerns like this and its very easy to specify declaratively in a database equipped to do so. I understand sqlite doesn''t support FK constraints but it does support triggers, so you could approach it that way. However, if your Rails app has a low enough insertion volume to allow you to use sqlite you probably do not need to worry about this question to begin with.
On Mar 19, 2006, at 21:16, Jeremy Huffman wrote:> On 3/19/06, Xavier Noria <fxn@hashref.com> wrote: >> On Mar 19, 2006, at 16:22, Jeremy Huffman wrote: >> >>> This isn''t a race condition, this is simply a data integrity issue. >> >> I thought of it as a race condition between add_post and delete_user >> because since add_post is not atomic it can find a user in one line, >> assume it exists in the next one, and have delete_user break that in >> between in a separate session. >> > This isn''t a race condition because it doesn''t lead to a deadlock, its > just an example of a stale update that leaves the database in an > inconsistent state.A deadlock is not a necessary condition of race condition as I understand it. The definition of "race condition" I have in mind coincides with the one in the Wikipedia[*]: A race hazard (or race condition) is a flaw in a system or process where the output exhibits unexpected critical dependence on the relative timing of events. The example Received()/Timeout() is analogous to add_post/delete_user in that regard.>> If I could get a lock somehow, I could guarantee that when add_post >> finishes the user is still there, which is all I am worried about, if >> when the lock is released delete_user gets the lock and deletes the >> user and his posts that''s fine (the rendered post listing in the >> response of add_post might be out of sync, but that''s inherent to web >> programming). >> >> Just for the record this user/post scenario is indeed an imaginary >> example that depicts the pattern. >> >>> We >>> can''t assume the database checks foreign key integrity, but we can >>> program it to do so and that is a practice I recommend because it is >>> efficient and reliable. >> >> I am not familiar with database programming. What do you mean? >> Programming it how? My application uses SQLite if that''s relevant. >> > > I just mean program it with foreign key constraints. The database is > in the best position to handle concerns like this and its very easy to > specify declaratively in a database equipped to do so. I understand > sqlite doesn''t support FK constraints but it does support triggers, so > you could approach it that way. However, if your Rails app has a low > enough insertion volume to allow you to use sqlite you probably do not > need to worry about this question to begin with.Yes, in this case that''s a simple application for internal use in the client. I expect it will have three users that will go to it a couple of times per month being optimistic :-), but I wanted to know the way to address that nonetheless, to know the technique and add it to my toolbox. I''ll follow your advice above next time, thank you! -- fxn [*] http://en.wikipedia.org/wiki/Race_condition