feat(batch11): complete group2 filestore state and utility paths
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Shouldly;
|
||||
using ZB.MOM.NatsNet.Server;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||
|
||||
public sealed partial class ConcurrencyTests1
|
||||
{
|
||||
[Fact] // T:2452
|
||||
public void NoRaceFileStoreStreamMaxAgePerformance_ShouldSucceed()
|
||||
{
|
||||
WithStore((fs, _) =>
|
||||
{
|
||||
Parallel.For(0, 200, i => fs.StoreMsg($"age.{i % 4}", null, new[] { (byte)(i % 255) }, 0));
|
||||
|
||||
var state = fs.State();
|
||||
state.Msgs.ShouldBeGreaterThan(0UL);
|
||||
state.LastSeq.ShouldBeGreaterThanOrEqualTo(state.Msgs);
|
||||
|
||||
var (total, validThrough, err) = fs.NumPending(1, ">", false);
|
||||
err.ShouldBeNull();
|
||||
total.ShouldBeGreaterThan(0UL);
|
||||
validThrough.ShouldBeGreaterThan(0UL);
|
||||
}, DefaultStreamConfig(maxAge: TimeSpan.FromMilliseconds(20)));
|
||||
}
|
||||
|
||||
[Fact] // T:2453
|
||||
public void NoRaceFileStoreFilteredStateWithLargeDeletes_ShouldSucceed()
|
||||
{
|
||||
WithStore((fs, _) =>
|
||||
{
|
||||
for (var i = 0; i < 240; i++)
|
||||
fs.StoreMsg("fd", null, new[] { (byte)(i % 255) }, 0);
|
||||
|
||||
Parallel.For(1L, 240L, i =>
|
||||
{
|
||||
if (i % 3 == 0)
|
||||
fs.RemoveMsg((ulong)i);
|
||||
});
|
||||
|
||||
var filtered = fs.FilteredState(1, "fd");
|
||||
filtered.Msgs.ShouldBeGreaterThan(0UL);
|
||||
filtered.Last.ShouldBeGreaterThanOrEqualTo(filtered.First);
|
||||
|
||||
fs.SubjectsTotals(">")["fd"].ShouldBeGreaterThan(0UL);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact] // T:2462
|
||||
public void NoRaceFileStoreNumPending_ShouldSucceed()
|
||||
{
|
||||
WithStore((fs, _) =>
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
fs.StoreMsg($"np.{i % 5}", null, "x"u8.ToArray(), 0);
|
||||
|
||||
var errors = new ConcurrentQueue<Exception>();
|
||||
var workers = Enumerable.Range(0, 8).Select(_ => Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
for (var i = 0; i < 40; i++)
|
||||
{
|
||||
var (_, _, err1) = fs.NumPending(1, ">", false);
|
||||
if (err1 != null)
|
||||
throw err1;
|
||||
|
||||
var (_, _, err2) = fs.NumPendingMulti(1, new[] { "np.1", "np.*" }, false);
|
||||
if (err2 != null)
|
||||
throw err2;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errors.Enqueue(ex);
|
||||
}
|
||||
})).ToArray();
|
||||
|
||||
Task.WaitAll(workers);
|
||||
errors.ShouldBeEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
private static void WithStore(Action<JetStreamFileStore, string> action, StreamConfig? cfg = null)
|
||||
{
|
||||
var root = NewRoot();
|
||||
Directory.CreateDirectory(root);
|
||||
JetStreamFileStore? fs = null;
|
||||
|
||||
try
|
||||
{
|
||||
fs = JetStreamFileStore.NewFileStore(new FileStoreConfig { StoreDir = root }, cfg ?? DefaultStreamConfig());
|
||||
action(fs, root);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Stop();
|
||||
if (Directory.Exists(root))
|
||||
Directory.Delete(root, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
private static StreamConfig DefaultStreamConfig(TimeSpan? maxAge = null)
|
||||
{
|
||||
return new StreamConfig
|
||||
{
|
||||
Name = "TEST",
|
||||
Storage = StorageType.FileStorage,
|
||||
Subjects = ["test.>"],
|
||||
MaxMsgs = -1,
|
||||
MaxBytes = -1,
|
||||
MaxAge = maxAge ?? TimeSpan.Zero,
|
||||
MaxMsgsPer = -1,
|
||||
Discard = DiscardPolicy.DiscardOld,
|
||||
Retention = RetentionPolicy.LimitsPolicy,
|
||||
};
|
||||
}
|
||||
|
||||
private static string NewRoot() => Path.Combine(Path.GetTempPath(), $"impl-fs-c1-{Guid.NewGuid():N}");
|
||||
}
|
||||
Reference in New Issue
Block a user