From 6af7e181818c625e02d998bbc5090d16ee1da6f9 Mon Sep 17 00:00:00 2001 From: hulkhan22 Date: Wed, 7 May 2025 04:09:56 +0200 Subject: [PATCH] Ensure unique MongoIDs --- .../SPTarkov.Server.Core/Utils/HashUtil.cs | 2 +- .../SPTarkov.Server.Core/Utils/RandomUtil.cs | 7 ++++- UnitTests/Tests/Utils/HashUtilTests.cs | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs b/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs index eabfb8b7..7bc89fe8 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/HashUtil.cs @@ -28,7 +28,7 @@ public partial class HashUtil(RandomUtil _randomUtil) objectId[3] = (byte) timestamp; // Random value (5 bytes) - _randomUtil.Random.NextBytes(objectId.Slice(4, 5)); + _randomUtil.NextBytes(objectId.Slice(4, 5)); // Incrementing counter (3 bytes) // 24-bit counter diff --git a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs index cd0021be..d24f1142 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs @@ -35,7 +35,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) max -= 1; } - return max > min ? Random.Next(min, exclusive ? max : max + 1) : min; + return max > min ? Random.Shared.Next(min, exclusive ? max : max + 1) : min; } /// @@ -64,6 +64,11 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) return Random.Next(0, 2) == 1; } + public void NextBytes(Span bytes) + { + Random.Shared.NextBytes(bytes); + } + /// /// Calculates the percentage of a given number and returns the result. /// diff --git a/UnitTests/Tests/Utils/HashUtilTests.cs b/UnitTests/Tests/Utils/HashUtilTests.cs index 219cfcd8..faee9b11 100644 --- a/UnitTests/Tests/Utils/HashUtilTests.cs +++ b/UnitTests/Tests/Utils/HashUtilTests.cs @@ -1,3 +1,5 @@ +using System.Collections.Concurrent; +using System.Diagnostics; using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; using UnitTests.Mock; @@ -63,4 +65,30 @@ public class HashUtilTests failMessage ); } + + [TestMethod] + public void MultiThreadedMongoIDGenerationTest() + { + var concurrentBag = new ConcurrentBag(); + var random = new Random(); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + Parallel.For(0, 1000, i => + { + Thread.Sleep(random.Next(0, 10)); + var mongoId = _hashUtil.Generate(); + concurrentBag.Add(mongoId); + }); + + stopwatch.Stop(); + Console.WriteLine($"Elapsed time: {stopwatch.ElapsedMilliseconds} ms"); + var uniqueCount = concurrentBag.Distinct().Count(); + var totalCount = concurrentBag.Count; + Assert.AreEqual( + totalCount, + uniqueCount, + $"Expected all generated MongoId's to be unique, but found {totalCount - uniqueCount} duplicates." + ); + } }