Optimistic Locking Enhancements: Gem or Core?

If you will allow me my 2cents :slight_smile:

Record locking is one of the ‘not invented here’ features of most RDBMS’s and hence Rails :wink:

We added an abstract class which all models inherits from (instead of ActiveRecord::Base) and implemented a few “core” methods on this class (and made sure all migrations of new models contains a ‘locked_by int’ field)

def can_edit?(usr)

has usr permissions (with CanCan or else how)

end

def locked?(user_id)

exec “update #{table_name} set locked_by=#{user_id} where id=#{id} and locked_by=0”

end

which allowed us to do this (in the controllers)

def edit

if can_edit?(current_user) && locked?(current_user)

# render like any other day

else

# inject a flash with the error (either no edit permissions or not locked by current_user)

end

end

def update

params[:what_ever][:locked_by]=0

if resource.update_attributes(params[:what_ever])

..

end

Currently, we are looking into the “collateral damage” (users starting to editing a record and then leaving for coffee, having a stroke or just plain drifts about in there, like it was Google search - leaving a bunch of locked records in their wake) - but hey, any solution is the offspring to a new challenge, right :slight_smile:

Originally we tried with optimistic locking and we did not like it at all - too many users saving data on top of each other - but then again that may just have been us implementing it the wrong way :frowning:

Like I said - just my 2cents - and probably not what you wanted <:)

cheers

Walther

ps. the above code is part pseudo-code - part copy/paste - you’d get the drift if it suits you, and ironing the ‘small-print’ out would not be a big feast :slight_smile:

If you will allow me my 2cents :slight_smile:

Record locking is one of the ‘not invented here’ features of most RDBMS’s and hence Rails :wink:

We added an abstract class which all models inherits from (instead of ActiveRecord::Base) and implemented a few “core” methods on this class (and made sure all migrations of new models contains a ‘locked_by int’ field)

def can_edit?(usr)

has usr permissions (with CanCan or else how)

end

def locked?(user_id)

exec “update #{table_name} set locked_by=#{user_id} where id=#{id} and locked_by=0”

end

which allowed us to do this (in the controllers)

def edit

if can_edit?(current_user) && locked?(current_user)

# render like any other day

else

# inject a flash with the error (either no edit permissions or not locked by current_user)

end

end

def update

params[:what_ever][:locked_by]=0

if resource.update_attributes(params[:what_ever])

..

end

Currently, we are looking into the “collateral damage” (users starting to editing a record and then leaving for coffee, having a stroke or just plain drifts about in there, like it was Google search - leaving a bunch of locked records in their wake) - but hey, any solution is the offspring to a new challenge, right :slight_smile:

What you’ve implemented is pessimistic locking, which is completely different and comes with its own set of tradeoffs. If you expect conflicts to be rare, you should use optimistic locking (you’re ‘optimistic’ the lock isn’t needed). If you expect them to be common, you need to lock more actively.

Originally we tried with optimistic locking and we did not like it at all - too many users saving data on top of each other - but then again that may just have been us implementing it the wrong way :frowning:

This is exactly what optimistic locking is meant to prevent, users can’t save data over the top of each other if you’re using optimistic locking correctly.

Yes, to be clear I’m only talking about optimistic locking here.