146 lines
3.3 KiB
Go
Raw Permalink Normal View History

2026-02-23 22:48:31 +03:00
// /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()
}