feat(batch14): complete filestore write lifecycle features and tests
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Shouldly;
|
||||
using ZB.MOM.NatsNet.Server;
|
||||
@@ -122,6 +123,74 @@ public sealed partial class ConcurrencyTests2
|
||||
}, cfg);
|
||||
}
|
||||
|
||||
[Fact] // T:2494
|
||||
public void NoRaceFileStoreWriteFullStateUniqueSubjects_ShouldSucceed()
|
||||
{
|
||||
var cfg = new StreamConfig
|
||||
{
|
||||
Name = "TEST",
|
||||
Storage = StorageType.FileStorage,
|
||||
Subjects = ["records.>"],
|
||||
MaxMsgs = -1,
|
||||
MaxBytes = 15L * 1024 * 1024 * 1024,
|
||||
MaxAge = TimeSpan.Zero,
|
||||
MaxMsgsPer = 1,
|
||||
Discard = DiscardPolicy.DiscardOld,
|
||||
Retention = RetentionPolicy.LimitsPolicy,
|
||||
};
|
||||
|
||||
WithStore((fs, root) =>
|
||||
{
|
||||
var payload = Enumerable.Repeat((byte)'Z', 128).ToArray();
|
||||
var errors = new ConcurrentQueue<Exception>();
|
||||
using var cts = new CancellationTokenSource();
|
||||
|
||||
var writer = Task.Run(async () =>
|
||||
{
|
||||
while (!cts.Token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var err = InvokePrivate<Exception?>(fs, "WriteFullState");
|
||||
if (err != null)
|
||||
errors.Enqueue(err);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errors.Enqueue(ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(10, cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (var i = 0; i < 2_000; i++)
|
||||
{
|
||||
var subject = $"records.{Guid.NewGuid():N}.{i % 5}";
|
||||
var sw = Stopwatch.StartNew();
|
||||
fs.StoreMsg(subject, null, payload, 0).Seq.ShouldBeGreaterThan(0UL);
|
||||
sw.Stop();
|
||||
sw.Elapsed.ShouldBeLessThan(TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
|
||||
cts.Cancel();
|
||||
Should.NotThrow(() => writer.Wait(TimeSpan.FromSeconds(2)));
|
||||
errors.ShouldBeEmpty();
|
||||
|
||||
fs.Stop();
|
||||
var stateFile = Path.Combine(root, FileStoreDefaults.MsgDir, FileStoreDefaults.StreamStateFile);
|
||||
File.Exists(stateFile).ShouldBeTrue();
|
||||
new FileInfo(stateFile).Length.ShouldBeGreaterThan(0L);
|
||||
}, cfg);
|
||||
}
|
||||
|
||||
private static void WithStore(Action<JetStreamFileStore, string> action, StreamConfig? cfg = null)
|
||||
{
|
||||
var root = NewRoot();
|
||||
|
||||
Reference in New Issue
Block a user