Commit commits the transaction using a two-phase commit protocol. Phase 1: Apply all operations to the database Phase 2: Apply changes to the in-memory model and rebuild role links.
()
| 25 | // Phase 1: Apply all operations to the database |
| 26 | // Phase 2: Apply changes to the in-memory model and rebuild role links. |
| 27 | func (tx *Transaction) Commit() error { |
| 28 | // Try to acquire the commit lock with timeout. |
| 29 | if !tryLockWithTimeout(&tx.enforcer.commitLock, tx.startTime, defaultLockTimeout) { |
| 30 | _ = tx.txContext.Rollback() |
| 31 | tx.enforcer.activeTransactions.Delete(tx.id) |
| 32 | return errors.New("transaction timeout: failed to acquire lock") |
| 33 | } |
| 34 | defer tx.enforcer.commitLock.Unlock() |
| 35 | |
| 36 | tx.mutex.Lock() |
| 37 | defer tx.mutex.Unlock() |
| 38 | |
| 39 | if tx.committed { |
| 40 | return errors.New("transaction already committed") |
| 41 | } |
| 42 | if tx.rolledBack { |
| 43 | return errors.New("transaction already rolled back") |
| 44 | } |
| 45 | |
| 46 | // First check if model version has changed. |
| 47 | currentVersion := atomic.LoadInt64(&tx.enforcer.modelVersion) |
| 48 | if currentVersion != tx.baseVersion { |
| 49 | // Model has been modified, need to check for conflicts. |
| 50 | detector := NewConflictDetector( |
| 51 | tx.buffer.GetModelSnapshot(), |
| 52 | tx.enforcer.model, |
| 53 | tx.buffer.GetOperations(), |
| 54 | ) |
| 55 | if err := detector.DetectConflicts(); err != nil { |
| 56 | _ = tx.txContext.Rollback() |
| 57 | tx.enforcer.activeTransactions.Delete(tx.id) |
| 58 | return err |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | // If no operations, just commit the database transaction and clear state. |
| 63 | if !tx.buffer.HasOperations() { |
| 64 | if err := tx.txContext.Commit(); err != nil { |
| 65 | return err |
| 66 | } |
| 67 | tx.committed = true |
| 68 | tx.enforcer.activeTransactions.Delete(tx.id) |
| 69 | return nil |
| 70 | } |
| 71 | |
| 72 | // Phase 1: Apply all buffered operations to the database |
| 73 | if err := tx.applyOperationsToDatabase(); err != nil { |
| 74 | // Rollback database transaction on failure. |
| 75 | _ = tx.txContext.Rollback() |
| 76 | tx.enforcer.activeTransactions.Delete(tx.id) |
| 77 | return err |
| 78 | } |
| 79 | |
| 80 | // Commit database transaction. |
| 81 | if err := tx.txContext.Commit(); err != nil { |
| 82 | tx.enforcer.activeTransactions.Delete(tx.id) |
| 83 | return err |
| 84 | } |
nothing calls this directly
no test coverage detected