|
|
|
|
@ -350,16 +350,26 @@ func (sl *ServerLockService) executeFunc(ctx context.Context, actionName string, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (sl *ServerLockService) createLock(ctx context.Context, |
|
|
|
|
lockRow *serverLock, dbSession *sqlstore.DBSession) (*serverLock, error) { |
|
|
|
|
lockRow *serverLock, dbSession *sqlstore.DBSession, |
|
|
|
|
) (*serverLock, error) { |
|
|
|
|
affected := int64(1) |
|
|
|
|
rawSQL := `INSERT INTO server_lock (operation_uid, last_execution, version) VALUES (?, ?, ?)` |
|
|
|
|
if sl.SQLStore.GetDBType() == migrator.Postgres { |
|
|
|
|
rawSQL += ` RETURNING id` |
|
|
|
|
rawSQL += ` ON CONFLICT DO NOTHING RETURNING id` |
|
|
|
|
var id int64 |
|
|
|
|
_, err := dbSession.SQL(rawSQL, lockRow.OperationUID, lockRow.LastExecution, 0).Get(&id) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
if id == 0 { |
|
|
|
|
// Considering the default isolation level (READ COMMITTED), an entry could be added to the table
|
|
|
|
|
// between the SELECT and the INSERT. And inserting a row with the same operation_uid would violate the unique
|
|
|
|
|
// constraint. In this case, the ON CONFLICT DO NOTHING clause will prevent generating an error.
|
|
|
|
|
// And the returning id will be 0 which means that there wasn't any row inserted (another server has the lock),
|
|
|
|
|
// therefore we return the ServerLockExistsError.
|
|
|
|
|
// https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED
|
|
|
|
|
return nil, &ServerLockExistsError{actionName: lockRow.OperationUID} |
|
|
|
|
} |
|
|
|
|
lockRow.Id = id |
|
|
|
|
} else { |
|
|
|
|
res, err := dbSession.Exec( |
|
|
|
|
|