mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:17:32 +00:00
feat(eventstore): add row locking option (#8939)
# Which Problems Are Solved We need a reliable way to lock events that are being processed as part of a job queue. For example in the notification handlers. # How the Problems Are Solved Allow setting `FOR UPDATE [ NOWAIT | SKIP LOCKED ]` to the eventstore query builder using an open transaction. - NOWAIT returns an errors if the lock cannot be obtained - SKIP LOCKED only returns row which are not locked. - Default is to wait for the lock to be released. # Additional Changes - none # Additional Context - [Locking docs](https://www.postgresql.org/docs/17/sql-select.html#SQL-FOR-UPDATE-SHARE) - Related to https://github.com/zitadel/zitadel/issues/8931
This commit is contained in:
@@ -22,6 +22,8 @@ type SearchQueryBuilder struct {
|
||||
editorUser string
|
||||
queries []*SearchQuery
|
||||
tx *sql.Tx
|
||||
lockRows bool
|
||||
lockOption LockOption
|
||||
allowTimeTravel bool
|
||||
positionAfter float64
|
||||
awaitOpenTransactions bool
|
||||
@@ -94,6 +96,10 @@ func (q SearchQueryBuilder) GetCreationDateBefore() time.Time {
|
||||
return q.creationDateBefore
|
||||
}
|
||||
|
||||
func (q SearchQueryBuilder) GetLockRows() (bool, LockOption) {
|
||||
return q.lockRows, q.lockOption
|
||||
}
|
||||
|
||||
// ensureInstanceID makes sure that the instance id is always set
|
||||
func (b *SearchQueryBuilder) ensureInstanceID(ctx context.Context) {
|
||||
if b.instanceID == nil && len(b.instanceIDs) == 0 && authz.GetInstance(ctx).InstanceID() != "" {
|
||||
@@ -307,6 +313,27 @@ func (builder *SearchQueryBuilder) CreationDateBefore(creationDate time.Time) *S
|
||||
return builder
|
||||
}
|
||||
|
||||
type LockOption int
|
||||
|
||||
const (
|
||||
// Wait until the previous lock on all of the selected rows is released (default)
|
||||
LockOptionWait LockOption = iota
|
||||
// With NOWAIT, the statement reports an error, rather than waiting, if a selected row cannot be locked immediately.
|
||||
LockOptionNoWait
|
||||
// With SKIP LOCKED, any selected rows that cannot be immediately locked are skipped.
|
||||
LockOptionSkipLocked
|
||||
)
|
||||
|
||||
// LockRowsDuringTx locks the found rows for the duration of the transaction,
|
||||
// using the [`FOR UPDATE`](https://www.postgresql.org/docs/17/sql-select.html#SQL-FOR-UPDATE-SHARE) lock strength.
|
||||
// The lock is removed on transaction commit or rollback.
|
||||
func (builder *SearchQueryBuilder) LockRowsDuringTx(tx *sql.Tx, option LockOption) *SearchQueryBuilder {
|
||||
builder.tx = tx
|
||||
builder.lockRows = true
|
||||
builder.lockOption = option
|
||||
return builder
|
||||
}
|
||||
|
||||
// AddQuery creates a new sub query.
|
||||
// All fields in the sub query are AND-connected in the storage request.
|
||||
// Multiple sub queries are OR-connected in the storage request.
|
||||
|
Reference in New Issue
Block a user