From 84ce12a4d39abdeaa2c032619f2c7daa84745660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=93=D1=80=D0=B8=D0=B3=D0=BE=D1=80=D0=B8=D0=B9=20=D0=A1?= =?UTF-8?q?=D0=B0=D1=84=D1=80=D0=BE=D0=BD=D0=BE=D0=B2?= Date: Thu, 17 Sep 2026 21:00:31 +0000 Subject: [PATCH] Update internal/storage/collection.go --- internal/storage/collection.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/storage/collection.go b/internal/storage/collection.go index 50d79b2..5fb8798 100644 --- a/internal/storage/collection.go +++ b/internal/storage/collection.go @@ -55,6 +55,9 @@ type Collection struct { // MVCC - многоверсионность mvccManager *MVCCManager // MVCC менеджер для управления версиями mvccEnabled bool // Включен ли MVCC + + // ИСПРАВЛЕНО: Блокировка для согласованности индексов при SoftDelete + indexMu sync.Mutex // Защита атомарности операций с индексами } // CollectionMetadata содержит метаданные коллекции @@ -857,9 +860,12 @@ func (c *Collection) Update(id string, updates map[string]interface{}) error { // Выполняем триггеры BEFORE_UPDATE c.executeTriggers("BEFORE_UPDATE", id, newDoc.GetFields()) + // ИСПРАВЛЕНО: Блокируем индексы для атомарности + c.indexMu.Lock() // Сначала удаляем старые индексы, потом добавляем новые c.removeFromIndexes(oldDoc) c.addToIndexes(newDoc) + c.indexMu.Unlock() // Сохраняем обновлённый документ c.docs.Store(id, newDoc) @@ -883,6 +889,7 @@ func (c *Collection) Update(id string, updates map[string]interface{}) error { } // Delete удаляет документ по ID +// ИСПРАВЛЕНО: Атомарность SoftDelete и удаления из индексов func (c *Collection) Delete(id string) error { val, ok := c.docs.Load(id) if !ok { @@ -895,24 +902,34 @@ func (c *Collection) Delete(id string) error { c.executeTriggers("BEFORE_DELETE", id, doc.GetFields()) if c.metadata.Settings.SoftDelete { + // ИСПРАВЛЕНО: Блокируем индексы для атомарности SoftDelete и удаления из индексов + c.indexMu.Lock() + // Мягкое удаление doc.SoftDelete() c.docs.Store(id, doc) // Удаляем из индексов при мягком удалении c.removeFromIndexes(doc) + + c.indexMu.Unlock() // Аудит мягкого удаления AuditDocumentOperation("SOFT_DELETE", c.dbName, c.name, id, map[string]interface{}{ "deleted_at": doc.DeletedAt, }) } else { + // ИСПРАВЛЕНО: Блокируем индексы для атомарности физического удаления + c.indexMu.Lock() + // Физическое удаление // Удаляем из индексов c.removeFromIndexes(doc) // Удаляем документ c.docs.Delete(id) + + c.indexMu.Unlock() // Аудит физического удаления AuditDocumentOperation("DELETE", c.dbName, c.name, id, nil) @@ -944,11 +961,16 @@ func (c *Collection) PermanentDelete(id string) error { return fmt.Errorf("document is not soft deleted, use Delete() instead") } + // ИСПРАВЛЕНО: Блокируем индексы для атомарности + c.indexMu.Lock() + // Удаляем из индексов c.removeFromIndexes(doc) // Удаляем документ c.docs.Delete(id) + + c.indexMu.Unlock() // Обновляем метаданные c.docCount.Add(-1) @@ -964,6 +986,7 @@ func (c *Collection) PermanentDelete(id string) error { } // RestoreDeleted восстанавливает мягко удалённый документ +// ИСПРАВЛЕНО: Атомарность восстановления и добавления в индексы func (c *Collection) RestoreDeleted(id string) error { val, ok := c.docs.Load(id) if !ok { @@ -976,12 +999,18 @@ func (c *Collection) RestoreDeleted(id string) error { return fmt.Errorf("document is not deleted") } + // ИСПРАВЛЕНО: Блокируем индексы для атомарности + c.indexMu.Lock() + doc.Restore() // Восстанавливаем индексы c.addToIndexes(doc) c.docs.Store(id, doc) + + c.indexMu.Unlock() + c.mu.Lock() c.metadata.UpdatedAt = time.Now().UnixMilli() c.mu.Unlock() @@ -1870,4 +1899,4 @@ func toFloat64(val interface{}) (float64, bool) { default: return 0, false } -} +} \ No newline at end of file