From db16cf1c14ab0bb55613a904cd0bd447a1dfa71a Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Tue, 18 Aug 2026 06:44:48 +0000 Subject: [PATCH] test(store): a create commit then a delete commit leaves no record behind This is the shape of the corrective forward commit for a repo carrying a stranded empty MST node. Deliberately two commits, not one batch: in a single applyWrites the tree applies ops in order (create then delete, key gone) while the SQL applies every delete before every create, so a same-key create+delete in one batch leaves the record row present but absent from the MST. Co-Authored-By: Claude Opus 5 (1M context) --- src/storage/store.zig | 26 ++++++++++++++++++++++++++ 1 file(s) changed, 26 insertion(s)(+), 0 deletion(s)(-) diff --git a/src/storage/store.zig b/src/storage/store.zig --- a/src/storage/store.zig +++ b/src/storage/store.zig @@ -8578,3 +8578,29 @@ try std.testing.expect(next > previous); try std.testing.expect(std.mem.lessThan(u8, &future_tid, rev)); } + +test "a create commit followed by a delete commit leaves no record behind" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + + try init(std.Options.debug_io, ":memory:"); + defer close(); + + const account = try createAccount(allocator, "batch.test", "batch@test.com", "password", "did:plc:batchcd", true); + const doc = try std.json.parseFromSlice(std.json.Value, allocator, "{\"$type\":\"io.atcr.manifest\"}", .{}); + defer doc.deinit(); + + const rkey = "1b00000000000000000000000000000000000000000000000000000000000000"; + + _ = try applyWritesWithOptions(allocator, account, &.{ + .{ .create = .{ .collection = "io.atcr.manifest", .rkey = rkey, .value = doc.value } }, + }, .{ .validate = .skip }); + _ = try applyWritesWithOptions(allocator, account, &.{ + .{ .delete = .{ .collection = "io.atcr.manifest", .rkey = rkey } }, + }, .{ .validate = .skip }); + + db_mutex.lockUncancelable(store_io); + defer db_mutex.unlock(store_io); + try std.testing.expectEqual(@as(u64, 0), try scalarCountLocked("SELECT COUNT(*) FROM records WHERE did = ?", account.did)); +} -- tangled.sh