150 lines
3.5 KiB
Go
Raw Permalink Normal View History

2026-02-23 22:48:31 +03:00
// /futriis/internal/storage/tuple.go
// Пакет storage реализует операции с кортежами (записями)
package storage
import (
"errors"
"sync/atomic"
"futriis/pkg/types"
"futriis/pkg/utils"
)
// TupleManager управляет операциями с кортежами
type TupleManager struct {
stats struct {
created int64
updated int64
deleted int64
read int64
}
}
// NewTupleManager создаёт новый менеджер кортежей
func NewTupleManager() *TupleManager {
return &TupleManager{}
}
// CreateTuple создаёт новый кортеж в указанном слайсе
// Wait-free операция: использует атомарные операции для счётчиков
func (tm *TupleManager) CreateTuple(slice *types.Slice, id string, fields map[string]interface{}) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
// Проверяем существование кортежа
slice.RLock()
_, exists := slice.Tuples[id]
slice.RUnlock()
if exists {
return nil, errors.New("tuple already exists")
}
// Создаём новый кортеж
tuple := types.NewTuple(id)
for k, v := range fields {
tuple.Fields[k] = v
}
// Добавляем в слайс
slice.Lock()
slice.Tuples[id] = tuple
slice.Unlock()
// Атомарно увеличиваем счётчик созданных
atomic.AddInt64(&tm.stats.created, 1)
// Логируем операцию
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Created tuple: "+id)
}
return tuple, nil
}
// ReadTuple читает кортеж по ID
// Wait-free операция для чтения
func (tm *TupleManager) ReadTuple(slice *types.Slice, id string) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
slice.RLock()
tuple, exists := slice.Tuples[id]
slice.RUnlock()
if !exists {
return nil, errors.New("tuple not found")
}
atomic.AddInt64(&tm.stats.read, 1)
return tuple, nil
}
// UpdateTuple обновляет поля кортежа
func (tm *TupleManager) UpdateTuple(slice *types.Slice, id string, fields map[string]interface{}) (*types.Tuple, error) {
if slice == nil {
return nil, errors.New("slice is nil")
}
slice.Lock()
defer slice.Unlock()
tuple, exists := slice.Tuples[id]
if !exists {
return nil, errors.New("tuple not found")
}
// Обновляем поля
for k, v := range fields {
tuple.Fields[k] = v
}
atomic.AddInt64(&tm.stats.updated, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Updated tuple: "+id)
}
return tuple, nil
}
// DeleteTuple удаляет кортеж
func (tm *TupleManager) DeleteTuple(slice *types.Slice, id string) error {
if slice == nil {
return errors.New("slice is nil")
}
slice.Lock()
_, exists := slice.Tuples[id]
if !exists {
slice.Unlock()
return errors.New("tuple not found")
}
delete(slice.Tuples, id)
slice.Unlock()
atomic.AddInt64(&tm.stats.deleted, 1)
logger := utils.GetLogger()
if logger != nil {
logger.Log("INFO", "Deleted tuple: "+id)
}
return nil
}
// GetStats возвращает статистику операций
func (tm *TupleManager) GetStats() map[string]int64 {
return map[string]int64{
"created": atomic.LoadInt64(&tm.stats.created),
"updated": atomic.LoadInt64(&tm.stats.updated),
"deleted": atomic.LoadInt64(&tm.stats.deleted),
"read": atomic.LoadInt64(&tm.stats.read),
}
}