This little library provides a basic building block for doing optimistic locking when using GORM.
Embed the optimistic.Versioned
struct into your model struct, and you're done!
type Person struct {
gorm.Model
optimistic.Versioned // <-- the magic!
Name string
Age int
}
This library applies optimistic locking by adding a version number to your models.
- Your model starts at version 1 when created, and every subsequent change to that model increments its version number by 1.
- As a result, you can tell if a model has changed "since you read it into memory" by seeing if its version has changed since you read it.
- You can built this check into update/delete operations by having them only apply if the version number of the row matches the version you expect it to be. If it doesn't match, the operation will affect fewer rows than you expect, which you can detect and assume (in most cases) to be a concurrent modification error.
This library works using GORM hooks on the embedded optimistic.Versioned
struct. When embedded into your model it
means:
- Created instances of your model will have a default
Version
value of 1 - Using
BeforeUpdate
/BeforeDelete
GORM hooks: updates/deletions automatically:- Gain a
SET
clause, updating theVersion
previous version + 1. - Gain a
WHERE
clause, checking that the row in the database being modified is still the version we originally read into memory.
- Gain a
- Using
AfterUpdate
/AfterDelete
GORM hooks: updates/deletions check whether the number of rows affected is 0. If so, aoptimistic.ErrConcurrentModification
error is returned.