make GSI less shit

This commit is contained in:
2026-02-16 09:13:33 -05:00
parent f8b0b1c3ae
commit 29fe8a60c3
3 changed files with 209 additions and 36 deletions

View File

@@ -8,6 +8,7 @@ import "../rocksdb"
// UpdateItem — fetch existing item, apply update plan, write back
// Uses EXCLUSIVE lock (write operation)
// ATOMICITY: Uses WriteBatch to ensure base item + all GSI updates are atomic
//
// Returns:
// - old_item: the item BEFORE mutations (if it existed), for ReturnValues
@@ -59,7 +60,7 @@ update_item :: proc(
return nil, nil, .Serialization_Error
}
existing_item = decoded
// Save old item for ReturnValues
// Save old item for ReturnValues (and for GSI cleanup)
old_item = item_deep_copy(existing_item)
} else if get_err == .NotFound || existing_encoded == nil {
// Item doesn't exist yet — start with just the key attributes
@@ -109,9 +110,46 @@ update_item :: proc(
}
defer delete(encoded_item)
// Write back to RocksDB
put_err := rocksdb.db_put(&engine.db, storage_key, encoded_item)
if put_err != .None {
// --- ATOMIC WRITE BATCH: base item + all GSI updates ---
batch, batch_err := rocksdb.batch_create()
if batch_err != .None {
item_destroy(&existing_item)
if old, has := old_item.?; has {
old_copy := old
item_destroy(&old_copy)
}
return nil, nil, .RocksDB_Error
}
defer rocksdb.batch_destroy(&batch)
// Add base item write to batch
rocksdb.batch_put(&batch, storage_key, encoded_item)
// Add old GSI entry deletions to batch (if item existed before)
if old, has := old_item.?; has {
gsi_del_err := gsi_batch_delete_entries(&batch, table_name, old, &metadata)
if gsi_del_err != .None {
item_destroy(&existing_item)
old_copy := old
item_destroy(&old_copy)
return nil, nil, gsi_del_err
}
}
// Add new GSI entry writes to batch
gsi_write_err := gsi_batch_write_entries(&batch, table_name, existing_item, &metadata)
if gsi_write_err != .None {
item_destroy(&existing_item)
if old, has := old_item.?; has {
old_copy := old
item_destroy(&old_copy)
}
return nil, nil, gsi_write_err
}
// Write batch atomically - ALL or NOTHING
write_err := rocksdb.batch_write(&engine.db, &batch)
if write_err != .None {
item_destroy(&existing_item)
if old, has := old_item.?; has {
old_copy := old
@@ -120,12 +158,6 @@ update_item :: proc(
return nil, nil, .RocksDB_Error
}
// --- GSI maintenance: delete old entries, write new entries ---
if old, has := old_item.?; has {
gsi_delete_entries(engine, table_name, old, &metadata)
}
gsi_write_entries(engine, table_name, existing_item, &metadata)
new_item = existing_item
return old_item, new_item, .None
}
}