// /futriis/internal/transaction/tx.go // Пакет transaction реализует простые транзакции (не ACID) package transaction import ( "errors" "sync" "futriis/pkg/types" ) // TxState состояние транзакции type TxState int const ( TxStateActive TxState = iota TxStateCommited TxStateRolledBack ) // Operation представляет операцию в транзакции type Operation struct { Type string // create, update, delete Tapple string Slice string Key string Value interface{} OldValue interface{} } // Transaction представляет транзакцию type Transaction struct { ID string State TxState Operations []Operation mu sync.RWMutex } // TransactionManager управляет транзакциями type TransactionManager struct { transactions map[string]*Transaction currentTx *Transaction mu sync.RWMutex } // NewTransactionManager создаёт новый менеджер транзакций func NewTransactionManager() *TransactionManager { return &TransactionManager{ transactions: make(map[string]*Transaction), } } // Begin начинает новую транзакцию func (tm *TransactionManager) Begin() (string, error) { tm.mu.Lock() defer tm.mu.Unlock() if tm.currentTx != nil && tm.currentTx.State == TxStateActive { return "", errors.New("транзакция уже активна") } id := generateTxID() tx := &Transaction{ ID: id, State: TxStateActive, Operations: make([]Operation, 0), } tm.transactions[id] = tx tm.currentTx = tx return id, nil } // Commit фиксирует текущую транзакцию func (tm *TransactionManager) Commit() error { tm.mu.Lock() defer tm.mu.Unlock() if tm.currentTx == nil { return errors.New("нет активной транзакции") } if tm.currentTx.State != TxStateActive { return errors.New("транзакция не активна") } tm.currentTx.State = TxStateCommited tm.currentTx = nil return nil } // Rollback откатывает текущую транзакцию func (tm *TransactionManager) Rollback() error { tm.mu.Lock() defer tm.mu.Unlock() if tm.currentTx == nil { return errors.New("нет активной транзакции") } if tm.currentTx.State != TxStateActive { return errors.New("транзакция не активна") } tm.currentTx.State = TxStateRolledBack tm.currentTx = nil return nil } // AddOperation добавляет операцию в текущую транзакцию func (tm *TransactionManager) AddOperation(op Operation) error { tm.mu.RLock() tx := tm.currentTx tm.mu.RUnlock() if tx == nil { return errors.New("нет активной транзакции") } tx.mu.Lock() defer tx.mu.Unlock() if tx.State != TxStateActive { return errors.New("транзакция не активна") } tx.Operations = append(tx.Operations, op) return nil } // GetCurrentTx возвращает текущую транзакцию func (tm *TransactionManager) GetCurrentTx() *Transaction { tm.mu.RLock() defer tm.mu.RUnlock() return tm.currentTx } // generateTxID генерирует ID транзакции func generateTxID() string { return "tx-" + types.GenerateID() }