test: lock FileStore optimization boundaries
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
using NATS.Server.JetStream.Storage;
|
||||||
|
|
||||||
|
namespace NATS.Server.JetStream.Tests.JetStream.Storage;
|
||||||
|
|
||||||
|
public sealed class FileStoreOptimizationGuardTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task Snapshot_round_trip_preserves_headers_and_payload_separately()
|
||||||
|
{
|
||||||
|
var srcDir = Directory.CreateTempSubdirectory();
|
||||||
|
var dstDir = Directory.CreateTempSubdirectory();
|
||||||
|
|
||||||
|
await using var src = new FileStore(new FileStoreOptions { Directory = srcDir.FullName });
|
||||||
|
var hdr = "NATS/1.0\r\nX-Test: two\r\n\r\n"u8.ToArray();
|
||||||
|
var msg = "payload-two"u8.ToArray();
|
||||||
|
|
||||||
|
var (seq, _) = src.StoreMsg("events.a", hdr, msg, 0L);
|
||||||
|
var snapshot = await src.CreateSnapshotAsync(default);
|
||||||
|
|
||||||
|
await using var dst = new FileStore(new FileStoreOptions { Directory = dstDir.FullName });
|
||||||
|
await dst.RestoreSnapshotAsync(snapshot, default);
|
||||||
|
|
||||||
|
var loaded = dst.LoadMsg(seq, null);
|
||||||
|
loaded.Header.ShouldNotBeNull();
|
||||||
|
loaded.Header.ShouldBe(hdr);
|
||||||
|
loaded.Data.ShouldNotBeNull();
|
||||||
|
loaded.Data.ShouldBe(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PurgeEx_updates_last_by_subject_after_recovery()
|
||||||
|
{
|
||||||
|
var dir = Directory.CreateTempSubdirectory();
|
||||||
|
|
||||||
|
await using (var store = new FileStore(new FileStoreOptions { Directory = dir.FullName }))
|
||||||
|
{
|
||||||
|
store.StoreMsg("events.a", null, "one"u8.ToArray(), 0L);
|
||||||
|
store.StoreMsg("events.a", null, "two"u8.ToArray(), 0L);
|
||||||
|
store.StoreMsg("events.b", null, "other"u8.ToArray(), 0L);
|
||||||
|
store.PurgeEx("events.a", 0, 1);
|
||||||
|
await store.FlushAllPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var recovered = new FileStore(new FileStoreOptions { Directory = dir.FullName });
|
||||||
|
var last = await recovered.LoadLastBySubjectAsync("events.a", default);
|
||||||
|
|
||||||
|
last.ShouldNotBeNull();
|
||||||
|
last.Sequence.ShouldBe(2UL);
|
||||||
|
last.Payload.ToArray().ShouldBe("two"u8.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -532,4 +532,22 @@ public sealed class StoreInterfaceTests
|
|||||||
lastMsg = s.LoadLastMsg("foo", null);
|
lastMsg = s.LoadLastMsg("foo", null);
|
||||||
lastMsg.Sequence.ShouldBe(2UL);
|
lastMsg.Sequence.ShouldBe(2UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FileStore_LoadMsg_preserves_headers_separately_from_payload()
|
||||||
|
{
|
||||||
|
var dir = Directory.CreateTempSubdirectory();
|
||||||
|
using var store = new FileStore(new FileStoreOptions { Directory = dir.FullName });
|
||||||
|
|
||||||
|
var hdr = "NATS/1.0\r\nX-Test: one\r\n\r\n"u8.ToArray();
|
||||||
|
var msg = "payload"u8.ToArray();
|
||||||
|
|
||||||
|
var (seq, _) = store.StoreMsg("foo", hdr, msg, 0L);
|
||||||
|
var loaded = store.LoadMsg(seq, null);
|
||||||
|
|
||||||
|
loaded.Header.ShouldNotBeNull();
|
||||||
|
loaded.Header.ShouldBe(hdr);
|
||||||
|
loaded.Data.ShouldNotBeNull();
|
||||||
|
loaded.Data.ShouldBe(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,22 @@ public class JetStreamStoreIndexTests
|
|||||||
var last = await store.LoadLastBySubjectAsync("orders.created", default);
|
var last = await store.LoadLastBySubjectAsync("orders.created", default);
|
||||||
last!.Payload.Span.SequenceEqual("3"u8).ShouldBeTrue();
|
last!.Payload.Span.SequenceEqual("3"u8).ShouldBeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task FileStore_trim_to_zero_preserves_high_water_mark_for_empty_state()
|
||||||
|
{
|
||||||
|
var dir = Directory.CreateTempSubdirectory();
|
||||||
|
await using var store = new FileStore(new FileStoreOptions { Directory = dir.FullName });
|
||||||
|
|
||||||
|
await store.AppendAsync("orders.created", "1"u8.ToArray(), default);
|
||||||
|
await store.AppendAsync("orders.updated", "2"u8.ToArray(), default);
|
||||||
|
await store.AppendAsync("orders.created", "3"u8.ToArray(), default);
|
||||||
|
|
||||||
|
store.TrimToMaxMessages(0);
|
||||||
|
|
||||||
|
var state = await store.GetStateAsync(default);
|
||||||
|
state.Messages.ShouldBe(0UL);
|
||||||
|
state.LastSeq.ShouldBe(3UL);
|
||||||
|
state.FirstSeq.ShouldBe(4UL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user