diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index c159cd1..a308863 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -12,19 +12,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Install dependencies
- run: dotnet restore
- - name: Build
- run: dotnet build --configuration Release --no-restore
- - name: Running Azurite
- run: docker run -d -p 10000:10000 -p 10001:10001 mcr.microsoft.com/azure-storage/azurite
- - name: Test
- run: dotnet test --no-restore
- - name: Create the package
- run: dotnet pack --configuration Release
- - name: Publish the package to NUGET
- env: # Set the secret as an input
- NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
- if: ${{ github.ref == 'refs/heads/main' }}
- run: dotnet nuget push AutoNumber/bin/Release/*.nupkg --source https://api.nuget.org/v3/index.json --api-key $NUGET_API_KEY
+ - uses: actions/checkout@v2
+ - uses: actions/checkout@v2
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '9.0.x'
+ - name: Install dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --configuration Release --no-restore
+ - name: Running Azurite
+ run: docker run -d -p 10000:10000 -p 10001:10001 mcr.microsoft.com/azure-storage/azurite:latest
+ - name: Test
+ run: dotnet test --no-restore
+ - name: Create the package
+ run: dotnet pack --configuration Release
+ - name: Publish the package to NUGET
+ env: # Set the secret as an input
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ if: ${{ github.ref == 'refs/heads/main' }}
+ run: dotnet nuget push AutoNumber/bin/Release/*.nupkg --source https://api.nuget.org/v3/index.json --api-key $NUGET_API_KEY
diff --git a/AutoNumber/AutoNumber.csproj b/AutoNumber/AutoNumber.csproj
index c2943c8..570b2d1 100644
--- a/AutoNumber/AutoNumber.csproj
+++ b/AutoNumber/AutoNumber.csproj
@@ -1,41 +1,43 @@
-
- net6.0;net8.0;netstandard2.0;netstandard2.1
- 8.0.30703
- ..\
- SnowMaker
- AzureAutoNumber
- High performance, distributed unique id generator for Azure environments.
- 1.4.0
- 1.5.0.0
- 1.5.0.0
- bin\$(Configuration)\
- Ali Bahraminezhad
- MS-PL
- https://github.com/0x414c49/AzureAutoNumber
- Azure
- AutoNumber
- AutoNumber
- AutoNumber
- true
- * .NET 8
-* All azure and other nuget dependencies upgraded
- AzureAutoNumber
- 1.5.0
- False
-
-
- full
-
-
- pdbonly
-
-
-
-
-
-
-
-
-
+
+ net6.0;net8.0;net9.0;netstandard2.0;netstandard2.1
+ 8.0.30703
+ ..\
+ SnowMaker
+ AzureAutoNumber
+ High performance, distributed unique id generator for Azure environments.
+ 1.5.2
+ 1.5.2.0
+ 9.0
+ 1.5.2.0
+ bin\$(Configuration)\
+ Ali Bahraminezhad
+ MS-PL
+ https://github.com/0x414c49/AzureAutoNumber
+ Azure
+ AutoNumber
+ AutoNumber
+ AutoNumber
+ true
+ * .NET 8
+ * All azure and other nuget dependencies upgraded
+
+ AzureAutoNumber
+ 1.5.0
+ False
+
+
+ full
+
+
+ pdbonly
+
+
+
+
+
+
+
+
+
diff --git a/AutoNumber/BlobOptimisticDataStore.cs b/AutoNumber/BlobOptimisticDataStore.cs
index f0e5f1e..e378f69 100644
--- a/AutoNumber/BlobOptimisticDataStore.cs
+++ b/AutoNumber/BlobOptimisticDataStore.cs
@@ -19,7 +19,7 @@ public class BlobOptimisticDataStore : IOptimisticDataStore
private const string SeedValue = "1";
private readonly BlobContainerClient blobContainer;
private readonly ConcurrentDictionary blobReferences;
- private readonly object blobReferencesLock = new object();
+ private readonly object blobReferencesLock = new();
public BlobOptimisticDataStore(BlobServiceClient blobServiceClient, string containerName)
{
@@ -36,22 +36,18 @@ public string GetData(string blockName)
{
var blobReference = GetBlobReference(blockName);
- using (var stream = new MemoryStream())
- {
- blobReference.DownloadTo(stream);
- return Encoding.UTF8.GetString(stream.ToArray());
- }
+ using var stream = new MemoryStream();
+ blobReference.DownloadTo(stream);
+ return Encoding.UTF8.GetString(stream.ToArray());
}
public async Task GetDataAsync(string blockName)
{
var blobReference = GetBlobReference(blockName);
- using (var stream = new MemoryStream())
- {
- await blobReference.DownloadToAsync(stream).ConfigureAwait(false);
- return Encoding.UTF8.GetString(stream.ToArray());
- }
+ using var stream = new MemoryStream();
+ await blobReference.DownloadToAsync(stream).ConfigureAwait(false);
+ return Encoding.UTF8.GetString(stream.ToArray());
}
public async Task InitAsync()
@@ -73,7 +69,7 @@ public bool TryOptimisticWrite(string blockName, string data)
{
var blobRequestCondition = new BlobRequestConditions
{
- IfMatch = (blobReference.GetProperties()).Value.ETag
+ IfMatch = blobReference.GetProperties().Value.ETag
};
UploadText(
blobReference,
@@ -155,10 +151,8 @@ private async Task UploadTextAsync(BlockBlobClient blob, string text, BlobReques
ContentType = "text/plain"
};
- using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
- {
- await blob.UploadAsync(stream, header, null, accessCondition, null, null).ConfigureAwait(false);
- }
+ using var stream = new MemoryStream(Encoding.UTF8.GetBytes(text));
+ await blob.UploadAsync(stream, header, null, accessCondition).ConfigureAwait(false);
}
private void UploadText(BlockBlobClient blob, string text, BlobRequestConditions accessCondition)
@@ -168,10 +162,8 @@ private void UploadText(BlockBlobClient blob, string text, BlobRequestConditions
ContentType = "text/plain"
};
- using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
- {
- blob.Upload(stream, header, null, accessCondition, null, null);
- }
+ using var stream = new MemoryStream(Encoding.UTF8.GetBytes(text));
+ blob.Upload(stream, header, null, accessCondition);
}
}
}
\ No newline at end of file
diff --git a/AutoNumber/DebugOnlyFileDataStore.cs b/AutoNumber/DebugOnlyFileDataStore.cs
index 0c93bfd..3064d55 100644
--- a/AutoNumber/DebugOnlyFileDataStore.cs
+++ b/AutoNumber/DebugOnlyFileDataStore.cs
@@ -27,10 +27,8 @@ public string GetData(string blockName)
{
var file = File.Create(blockPath);
- using (var streamWriter = new StreamWriter(file))
- {
- streamWriter.Write(SeedValue);
- }
+ using var streamWriter = new StreamWriter(file);
+ streamWriter.Write(SeedValue);
return SeedValue;
}
diff --git a/AutoNumber/Options/AutoNumberOptionsBuilder.cs b/AutoNumber/Options/AutoNumberOptionsBuilder.cs
index 9dce0e7..7fe8960 100644
--- a/AutoNumber/Options/AutoNumberOptionsBuilder.cs
+++ b/AutoNumber/Options/AutoNumberOptionsBuilder.cs
@@ -16,7 +16,7 @@ public AutoNumberOptionsBuilder(IConfiguration configuration)
configuration.GetSection(AutoNumber).Bind(Options);
}
- public AutoNumberOptions Options { get; } = new AutoNumberOptions();
+ public AutoNumberOptions Options { get; } = new();
///
/// Uses the default StorageAccount already defined in dependency injection
diff --git a/AutoNumber/ScopeState.cs b/AutoNumber/ScopeState.cs
index 7f026b8..30a18b9 100644
--- a/AutoNumber/ScopeState.cs
+++ b/AutoNumber/ScopeState.cs
@@ -2,7 +2,7 @@ namespace AutoNumber
{
internal class ScopeState
{
- public readonly object IdGenerationLock = new object();
+ public readonly object IdGenerationLock = new();
public long HighestIdAvailableInBatch;
public long LastId;
}
diff --git a/AutoNumber/UniqueIdGenerator.cs b/AutoNumber/UniqueIdGenerator.cs
index 765fa88..3a3af48 100644
--- a/AutoNumber/UniqueIdGenerator.cs
+++ b/AutoNumber/UniqueIdGenerator.cs
@@ -58,7 +58,7 @@ private void UpdateFromSyncStore(string scopeName, ScopeState state)
var firstIdInNextBatch = state.HighestIdAvailableInBatch + 1;
if (optimisticDataStore.TryOptimisticWrite(scopeName,
- firstIdInNextBatch.ToString(CultureInfo.InvariantCulture)))
+ firstIdInNextBatch.ToString(CultureInfo.InvariantCulture)))
return;
writesAttempted++;
@@ -72,7 +72,7 @@ private void UpdateFromSyncStore(string scopeName, ScopeState state)
private readonly IOptimisticDataStore optimisticDataStore;
private readonly IDictionary states = new Dictionary();
- private readonly object statesLock = new object();
+ private readonly object statesLock = new();
private int maxWriteAttempts = 25;
#endregion
diff --git a/IntegrationTests/Azure.cs b/IntegrationTests/Azure.cs
index 03d0b3d..4f3ff4b 100644
--- a/IntegrationTests/Azure.cs
+++ b/IntegrationTests/Azure.cs
@@ -7,58 +7,55 @@
using Azure.Storage.Blobs.Specialized;
using NUnit.Framework;
-namespace IntegrationTests.cs
-{
- [TestFixture]
- public class Azure : Scenarios
- {
- private readonly BlobServiceClient blobServiceClient = new BlobServiceClient("UseDevelopmentStorage=true");
+namespace IntegrationTests.cs;
- protected override TestScope BuildTestScope()
- {
- return new TestScope(new BlobServiceClient("UseDevelopmentStorage=true"));
- }
+[TestFixture]
+public class Azure : Scenarios
+{
+ private readonly BlobServiceClient blobServiceClient = new("UseDevelopmentStorage=true");
- protected override IOptimisticDataStore BuildStore(TestScope scope)
- {
- var blobOptimisticDataStore = new BlobOptimisticDataStore(blobServiceClient, scope.ContainerName);
- blobOptimisticDataStore.Init();
- return blobOptimisticDataStore;
- }
+ protected override TestScope BuildTestScope()
+ {
+ return new TestScope(new BlobServiceClient("UseDevelopmentStorage=true"));
}
- public sealed class TestScope : ITestScope
+ protected override IOptimisticDataStore BuildStore(TestScope scope)
{
- private readonly BlobServiceClient blobServiceClient;
+ var blobOptimisticDataStore = new BlobOptimisticDataStore(blobServiceClient, scope.ContainerName);
+ blobOptimisticDataStore.Init();
+ return blobOptimisticDataStore;
+ }
+}
+
+public sealed class TestScope : ITestScope
+{
+ private readonly BlobServiceClient blobServiceClient;
- public TestScope(BlobServiceClient blobServiceClient)
- {
- var ticks = DateTime.UtcNow.Ticks;
- IdScopeName = string.Format("autonumbertest{0}", ticks);
- ContainerName = string.Format("autonumbertest{0}", ticks);
+ public TestScope(BlobServiceClient blobServiceClient)
+ {
+ var ticks = DateTime.UtcNow.Ticks;
+ IdScopeName = string.Format("autonumbertest{0}", ticks);
+ ContainerName = string.Format("autonumbertest{0}", ticks);
- this.blobServiceClient = blobServiceClient;
- }
+ this.blobServiceClient = blobServiceClient;
+ }
- public string ContainerName { get; }
+ public string ContainerName { get; }
- public string IdScopeName { get; }
+ public string IdScopeName { get; }
- public string ReadCurrentPersistedValue()
- {
- var blobContainer = blobServiceClient.GetBlobContainerClient(ContainerName);
- var blob = blobContainer.GetBlockBlobClient(IdScopeName);
- using (var stream = new MemoryStream())
- {
- blob.DownloadToAsync(stream).GetAwaiter().GetResult();
- return Encoding.UTF8.GetString(stream.ToArray());
- }
- }
+ public string ReadCurrentPersistedValue()
+ {
+ var blobContainer = blobServiceClient.GetBlobContainerClient(ContainerName);
+ var blob = blobContainer.GetBlockBlobClient(IdScopeName);
+ using var stream = new MemoryStream();
+ blob.DownloadToAsync(stream).GetAwaiter().GetResult();
+ return Encoding.UTF8.GetString(stream.ToArray());
+ }
- public void Dispose()
- {
- var blobContainer = blobServiceClient.GetBlobContainerClient(ContainerName);
- blobContainer.DeleteAsync().GetAwaiter().GetResult();
- }
+ public void Dispose()
+ {
+ var blobContainer = blobServiceClient.GetBlobContainerClient(ContainerName);
+ blobContainer.DeleteAsync().GetAwaiter().GetResult();
}
}
\ No newline at end of file
diff --git a/IntegrationTests/DependencyInjectionTest.cs b/IntegrationTests/DependencyInjectionTest.cs
index cccd401..191e2e3 100644
--- a/IntegrationTests/DependencyInjectionTest.cs
+++ b/IntegrationTests/DependencyInjectionTest.cs
@@ -2,99 +2,99 @@
using AutoNumber.Interfaces;
using AutoNumber.Options;
using Azure.Storage.Blobs;
+using FluentAssertions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using NUnit.Framework;
-namespace AutoNumber.IntegrationTests
+namespace AutoNumber.IntegrationTests;
+
+[TestFixture]
+public class DependencyInjectionTest
{
- [TestFixture]
- public class DependencyInjectionTest
+ public IConfigurationRoot Configuration = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", true, true).Build();
+
+ private ServiceProvider GenerateServiceProvider()
{
- public IConfigurationRoot Configuration = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json", true, true).Build();
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(new BlobServiceClient("UseDevelopmentStorage=true"));
+ serviceCollection.AddSingleton(Configuration);
+ serviceCollection.AddAutoNumber();
+ return serviceCollection.BuildServiceProvider();
+ }
- private ServiceProvider GenerateServiceProvider()
- {
- var serviceCollection = new ServiceCollection();
- serviceCollection.AddSingleton(new BlobServiceClient("UseDevelopmentStorage=true"));
- serviceCollection.AddSingleton(Configuration);
- serviceCollection.AddAutoNumber();
- return serviceCollection.BuildServiceProvider();
- }
-
- [Test]
- public void OptionsBuilderShouldGenerateOptions()
- {
- var serviceProvider = GenerateServiceProvider();
- var optionsBuilder = new AutoNumberOptionsBuilder(serviceProvider.GetService());
+ [Test]
+ public void OptionsBuilderShouldGenerateOptions()
+ {
+ var serviceProvider = GenerateServiceProvider();
+ var optionsBuilder = new AutoNumberOptionsBuilder(serviceProvider.GetService());
- optionsBuilder.SetBatchSize(5);
- Assert.AreEqual(5, optionsBuilder.Options.BatchSize);
+ optionsBuilder.SetBatchSize(5);
+ Assert.Equals(5, optionsBuilder.Options.BatchSize);
- optionsBuilder.SetMaxWriteAttempts(10);
- Assert.AreEqual(10, optionsBuilder.Options.MaxWriteAttempts);
+ optionsBuilder.SetMaxWriteAttempts(10);
+ Assert.Equals(10, optionsBuilder.Options.MaxWriteAttempts);
- optionsBuilder.UseDefaultContainerName();
- Assert.AreEqual("unique-urls", optionsBuilder.Options.StorageContainerName);
+ optionsBuilder.UseDefaultContainerName();
+ Assert.Equals("unique-urls", optionsBuilder.Options.StorageContainerName);
- optionsBuilder.UseContainerName("test");
- Assert.AreEqual("test", optionsBuilder.Options.StorageContainerName);
+ optionsBuilder.UseContainerName("test");
+ Assert.Equals("test", optionsBuilder.Options.StorageContainerName);
- optionsBuilder.UseDefaultStorageAccount();
- Assert.AreEqual(null, optionsBuilder.Options.StorageAccountConnectionString);
+ optionsBuilder.UseDefaultStorageAccount();
+ Assert.Equals(null, optionsBuilder.Options.StorageAccountConnectionString);
- optionsBuilder.UseStorageAccount("test");
- Assert.AreEqual("test123", optionsBuilder.Options.StorageAccountConnectionString);
+ optionsBuilder.UseStorageAccount("test");
+ Assert.Equals("test123", optionsBuilder.Options.StorageAccountConnectionString);
- optionsBuilder.UseStorageAccount("test-22");
- Assert.AreEqual("test-22", optionsBuilder.Options.StorageAccountConnectionString);
- }
+ optionsBuilder.UseStorageAccount("test-22");
+ Assert.Equals("test-22", optionsBuilder.Options.StorageAccountConnectionString);
+ }
- [Test]
- public void ShouldCraeteUniqueIdGenerator()
- {
- var serviceProvider = GenerateServiceProvider();
+ [Test]
+ public void ShouldCraeteUniqueIdGenerator()
+ {
+ var serviceProvider = GenerateServiceProvider();
- var uniqueId = serviceProvider.GetService();
+ var uniqueId = serviceProvider.GetService();
- Assert.NotNull(uniqueId);
- }
+ uniqueId.Should().NotBeNull();
+ }
- [Test]
- public void ShouldOptionsContainsDefaultValues()
- {
- var serviceProvider = GenerateServiceProvider();
+ [Test]
+ public void ShouldOptionsContainsDefaultValues()
+ {
+ var serviceProvider = GenerateServiceProvider();
+
+ var options = serviceProvider.GetService>();
- var options = serviceProvider.GetService>();
+ options.Value.Should().NotBeNull();
+ Assert.Equals(25, options.Value.MaxWriteAttempts);
+ Assert.Equals(50, options.Value.BatchSize);
+ Assert.Equals("unique-urls", options.Value.StorageContainerName);
+ }
- Assert.NotNull(options.Value);
- Assert.AreEqual(25, options.Value.MaxWriteAttempts);
- Assert.AreEqual(50, options.Value.BatchSize);
- Assert.AreEqual("unique-urls", options.Value.StorageContainerName);
- }
+ [Test]
+ public void ShouldResolveUniqueIdGenerator()
+ {
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddSingleton(new BlobServiceClient("UseDevelopmentStorage=true"));
- [Test]
- public void ShouldResolveUniqueIdGenerator()
+ serviceCollection.AddAutoNumber(Configuration, x =>
{
- var serviceCollection = new ServiceCollection();
- serviceCollection.AddSingleton(new BlobServiceClient("UseDevelopmentStorage=true"));
-
- serviceCollection.AddAutoNumber(Configuration, x =>
- {
- return x.UseContainerName("ali")
- .UseDefaultStorageAccount()
- .SetBatchSize(10)
- .SetMaxWriteAttempts()
- .Options;
- });
-
- var service = serviceCollection.BuildServiceProvider()
- .GetService();
-
- Assert.NotNull(service);
- }
+ return x.UseContainerName("ali")
+ .UseDefaultStorageAccount()
+ .SetBatchSize(10)
+ .SetMaxWriteAttempts()
+ .Options;
+ });
+
+ var service = serviceCollection.BuildServiceProvider()
+ .GetService();
+
+ service.Should().NotBeNull();
}
}
\ No newline at end of file
diff --git a/IntegrationTests/File.cs b/IntegrationTests/File.cs
index 27aceae..a7dfd27 100644
--- a/IntegrationTests/File.cs
+++ b/IntegrationTests/File.cs
@@ -4,47 +4,46 @@
using AutoNumber.Interfaces;
using NUnit.Framework;
-namespace IntegrationTests.cs
+namespace IntegrationTests.cs;
+
+[TestFixture]
+public class File : Scenarios
{
- [TestFixture]
- public class File : Scenarios
+ protected override TestScope BuildTestScope()
+ {
+ return new TestScope();
+ }
+
+ protected override IOptimisticDataStore BuildStore(TestScope scope)
+ {
+ return new DebugOnlyFileDataStore(scope.DirectoryPath);
+ }
+
+ public class TestScope : ITestScope
{
- protected override TestScope BuildTestScope()
+ public TestScope()
{
- return new TestScope();
+ var ticks = DateTime.UtcNow.Ticks;
+ IdScopeName = string.Format("AutoNumbertest{0}", ticks);
+
+ DirectoryPath = Path.Combine(Path.GetTempPath(), IdScopeName);
+ Directory.CreateDirectory(DirectoryPath);
}
- protected override IOptimisticDataStore BuildStore(TestScope scope)
+ public string DirectoryPath { get; }
+
+ public string IdScopeName { get; }
+
+ public string ReadCurrentPersistedValue()
{
- return new DebugOnlyFileDataStore(scope.DirectoryPath);
+ var filePath = Path.Combine(DirectoryPath, string.Format("{0}.txt", IdScopeName));
+ return System.IO.File.ReadAllText(filePath);
}
- public class TestScope : ITestScope
+ public void Dispose()
{
- public TestScope()
- {
- var ticks = DateTime.UtcNow.Ticks;
- IdScopeName = string.Format("AutoNumbertest{0}", ticks);
-
- DirectoryPath = Path.Combine(Path.GetTempPath(), IdScopeName);
- Directory.CreateDirectory(DirectoryPath);
- }
-
- public string DirectoryPath { get; }
-
- public string IdScopeName { get; }
-
- public string ReadCurrentPersistedValue()
- {
- var filePath = Path.Combine(DirectoryPath, string.Format("{0}.txt", IdScopeName));
- return System.IO.File.ReadAllText(filePath);
- }
-
- public void Dispose()
- {
- if (Directory.Exists(DirectoryPath))
- Directory.Delete(DirectoryPath, true);
- }
+ if (Directory.Exists(DirectoryPath))
+ Directory.Delete(DirectoryPath, true);
}
}
}
\ No newline at end of file
diff --git a/IntegrationTests/ITestScope.cs b/IntegrationTests/ITestScope.cs
index 4b64b30..e678a38 100644
--- a/IntegrationTests/ITestScope.cs
+++ b/IntegrationTests/ITestScope.cs
@@ -1,11 +1,10 @@
using System;
-namespace IntegrationTests.cs
+namespace IntegrationTests.cs;
+
+public interface ITestScope : IDisposable
{
- public interface ITestScope : IDisposable
- {
- string IdScopeName { get; }
+ string IdScopeName { get; }
- string ReadCurrentPersistedValue();
- }
+ string ReadCurrentPersistedValue();
}
\ No newline at end of file
diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj
index 4187655..966bbab 100644
--- a/IntegrationTests/IntegrationTests.csproj
+++ b/IntegrationTests/IntegrationTests.csproj
@@ -1,44 +1,45 @@
-
- 8.0.30703
- IntegrationTests.cs
- IntegrationTests.cs
- ..\
- IntegrationTests.cs
- Microsoft
- IntegrationTests.cs
- Copyright © Microsoft 2011
- bin\$(Configuration)\
- net6.0;net8.0
-
-
- full
-
-
- pdbonly
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
- Always
-
-
+
+ 8.0.30703
+ IntegrationTests.cs
+ IntegrationTests.cs
+ ..\
+ IntegrationTests.cs
+ Microsoft
+ IntegrationTests.cs
+ Copyright © Microsoft 2011
+ bin\$(Configuration)\
+ net8.0;net9.0
+
+
+ full
+
+
+ pdbonly
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+ Always
+
+
\ No newline at end of file
diff --git a/IntegrationTests/Scenarios.cs b/IntegrationTests/Scenarios.cs
index f63f8c0..6e5b559 100644
--- a/IntegrationTests/Scenarios.cs
+++ b/IntegrationTests/Scenarios.cs
@@ -4,179 +4,168 @@
using System.Threading.Tasks;
using AutoNumber;
using AutoNumber.Interfaces;
+using FluentAssertions;
using NUnit.Framework;
+using NUnit.Framework.Legacy;
-namespace IntegrationTests.cs
+namespace IntegrationTests.cs;
+
+public abstract class Scenarios where TTestScope : ITestScope
{
- public abstract class Scenarios where TTestScope : ITestScope
+ protected abstract IOptimisticDataStore BuildStore(TTestScope scope);
+ protected abstract TTestScope BuildTestScope();
+
+ [Test]
+ public void ShouldReturnOneForFirstIdInNewScope()
{
- protected abstract IOptimisticDataStore BuildStore(TTestScope scope);
- protected abstract TTestScope BuildTestScope();
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store = BuildStore(testScope);
+ var generator = new UniqueIdGenerator(store) { BatchSize = 3 };
- [Test]
- public void ShouldReturnOneForFirstIdInNewScope()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store = BuildStore(testScope);
- var generator = new UniqueIdGenerator(store) {BatchSize = 3};
+ // Act
+ var generatedId = generator.NextId(testScope.IdScopeName);
- // Act
- var generatedId = generator.NextId(testScope.IdScopeName);
+ // Assert
+ Assert.Equals(1, generatedId);
+ }
- // Assert
- Assert.AreEqual(1, generatedId);
- }
- }
+ [Test]
+ public void ShouldInitializeBlobForFirstIdInNewScope()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store = BuildStore(testScope);
+ var generator = new UniqueIdGenerator(store) { BatchSize = 3 };
- [Test]
- public void ShouldInitializeBlobForFirstIdInNewScope()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store = BuildStore(testScope);
- var generator = new UniqueIdGenerator(store) {BatchSize = 3};
+ // Act
+ generator.NextId(testScope.IdScopeName); //1
- // Act
- generator.NextId(testScope.IdScopeName); //1
+ // Assert
+ Assert.Equals("4", testScope.ReadCurrentPersistedValue());
+ }
+
+ [Test]
+ public void ShouldNotUpdateBlobAtEndOfBatch()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store = BuildStore(testScope);
+ var generator = new UniqueIdGenerator(store) { BatchSize = 3 };
+
+ // Act
+ generator.NextId(testScope.IdScopeName); //1
+ generator.NextId(testScope.IdScopeName); //2
+ generator.NextId(testScope.IdScopeName); //3
+
+ // Assert
+ Assert.Equals("4", testScope.ReadCurrentPersistedValue());
+ }
+
+ [Test]
+ public void ShouldUpdateBlobWhenGeneratingNextIdAfterEndOfBatch()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store = BuildStore(testScope);
+ var generator = new UniqueIdGenerator(store) { BatchSize = 3 };
+
+ // Act
+ generator.NextId(testScope.IdScopeName); //1
+ generator.NextId(testScope.IdScopeName); //2
+ generator.NextId(testScope.IdScopeName); //3
+ generator.NextId(testScope.IdScopeName); //4
+
+ // Assert
+ Assert.Equals("7", testScope.ReadCurrentPersistedValue());
+ }
- // Assert
- Assert.AreEqual("4", testScope.ReadCurrentPersistedValue());
- }
- }
+ [Test]
+ public void ShouldReturnIdsFromThirdBatchIfSecondBatchTakenByAnotherGenerator()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store1 = BuildStore(testScope);
+ var generator1 = new UniqueIdGenerator(store1) { BatchSize = 3 };
+ var store2 = BuildStore(testScope);
+ var generator2 = new UniqueIdGenerator(store2) { BatchSize = 3 };
+
+ // Act
+ generator1.NextId(testScope.IdScopeName); //1
+ generator1.NextId(testScope.IdScopeName); //2
+ generator1.NextId(testScope.IdScopeName); //3
+ generator2.NextId(testScope.IdScopeName); //4
+ var lastId = generator1.NextId(testScope.IdScopeName); //7
+
+ // Assert
+ Assert.Equals(7, lastId);
+ }
- [Test]
- public void ShouldNotUpdateBlobAtEndOfBatch()
+ [Test]
+ public void ShouldReturnIdsAcrossMultipleGenerators()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store1 = BuildStore(testScope);
+ var generator1 = new UniqueIdGenerator(store1) { BatchSize = 3 };
+ var store2 = BuildStore(testScope);
+ var generator2 = new UniqueIdGenerator(store2) { BatchSize = 3 };
+
+ // Act
+ var generatedIds = new[]
{
- // Arrange
- using (var testScope = BuildTestScope())
+ generator1.NextId(testScope.IdScopeName), //1
+ generator1.NextId(testScope.IdScopeName), //2
+ generator1.NextId(testScope.IdScopeName), //3
+ generator2.NextId(testScope.IdScopeName), //4
+ generator1.NextId(testScope.IdScopeName), //7
+ generator2.NextId(testScope.IdScopeName), //5
+ generator2.NextId(testScope.IdScopeName), //6
+ generator2.NextId(testScope.IdScopeName), //10
+ generator1.NextId(testScope.IdScopeName), //8
+ generator1.NextId(testScope.IdScopeName) //9
+ };
+
+ // Assert
+ CollectionAssert.Equals(
+ new[] { 1, 2, 3, 4, 7, 5, 6, 10, 8, 9 },
+ generatedIds);
+ }
+
+ [Test]
+ public void ShouldSupportUsingOneGeneratorFromMultipleThreads()
+ {
+ // Arrange
+ using var testScope = BuildTestScope();
+ var store = BuildStore(testScope);
+ var generator = new UniqueIdGenerator(store) { BatchSize = 1000 };
+ const int testLength = 10000;
+
+ // Act
+ var generatedIds = new ConcurrentQueue();
+ var threadIds = new ConcurrentQueue();
+ var scopeName = testScope.IdScopeName;
+ Parallel.For(
+ 0,
+ testLength,
+ new ParallelOptions { MaxDegreeOfParallelism = 10 },
+ _ =>
{
- var store = BuildStore(testScope);
- var generator = new UniqueIdGenerator(store) {BatchSize = 3};
+ generatedIds.Enqueue(generator.NextId(scopeName));
+ threadIds.Enqueue(Thread.CurrentThread.ManagedThreadId);
+ });
- // Act
- generator.NextId(testScope.IdScopeName); //1
- generator.NextId(testScope.IdScopeName); //2
- generator.NextId(testScope.IdScopeName); //3
+ // Assert we generated the right count of ids
+ Assert.Equals(testLength, generatedIds.Count);
- // Assert
- Assert.AreEqual("4", testScope.ReadCurrentPersistedValue());
- }
- }
+ // Assert there were no duplicates
+ var duplicates = generatedIds.GroupBy(n => n).Any(g => g.Count() != 1);
+ duplicates.Should().BeFalse();
- [Test]
- public void ShouldUpdateBlobWhenGeneratingNextIdAfterEndOfBatch()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store = BuildStore(testScope);
- var generator = new UniqueIdGenerator(store) {BatchSize = 3};
-
- // Act
- generator.NextId(testScope.IdScopeName); //1
- generator.NextId(testScope.IdScopeName); //2
- generator.NextId(testScope.IdScopeName); //3
- generator.NextId(testScope.IdScopeName); //4
-
- // Assert
- Assert.AreEqual("7", testScope.ReadCurrentPersistedValue());
- }
- }
-
- [Test]
- public void ShouldReturnIdsFromThirdBatchIfSecondBatchTakenByAnotherGenerator()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store1 = BuildStore(testScope);
- var generator1 = new UniqueIdGenerator(store1) {BatchSize = 3};
- var store2 = BuildStore(testScope);
- var generator2 = new UniqueIdGenerator(store2) {BatchSize = 3};
-
- // Act
- generator1.NextId(testScope.IdScopeName); //1
- generator1.NextId(testScope.IdScopeName); //2
- generator1.NextId(testScope.IdScopeName); //3
- generator2.NextId(testScope.IdScopeName); //4
- var lastId = generator1.NextId(testScope.IdScopeName); //7
-
- // Assert
- Assert.AreEqual(7, lastId);
- }
- }
-
- [Test]
- public void ShouldReturnIdsAcrossMultipleGenerators()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store1 = BuildStore(testScope);
- var generator1 = new UniqueIdGenerator(store1) {BatchSize = 3};
- var store2 = BuildStore(testScope);
- var generator2 = new UniqueIdGenerator(store2) {BatchSize = 3};
-
- // Act
- var generatedIds = new[]
- {
- generator1.NextId(testScope.IdScopeName), //1
- generator1.NextId(testScope.IdScopeName), //2
- generator1.NextId(testScope.IdScopeName), //3
- generator2.NextId(testScope.IdScopeName), //4
- generator1.NextId(testScope.IdScopeName), //7
- generator2.NextId(testScope.IdScopeName), //5
- generator2.NextId(testScope.IdScopeName), //6
- generator2.NextId(testScope.IdScopeName), //10
- generator1.NextId(testScope.IdScopeName), //8
- generator1.NextId(testScope.IdScopeName) //9
- };
-
- // Assert
- CollectionAssert.AreEqual(
- new[] {1, 2, 3, 4, 7, 5, 6, 10, 8, 9},
- generatedIds);
- }
- }
-
- [Test]
- public void ShouldSupportUsingOneGeneratorFromMultipleThreads()
- {
- // Arrange
- using (var testScope = BuildTestScope())
- {
- var store = BuildStore(testScope);
- var generator = new UniqueIdGenerator(store) {BatchSize = 1000};
- const int testLength = 10000;
-
- // Act
- var generatedIds = new ConcurrentQueue();
- var threadIds = new ConcurrentQueue();
- var scopeName = testScope.IdScopeName;
- Parallel.For(
- 0,
- testLength,
- new ParallelOptions {MaxDegreeOfParallelism = 10},
- i =>
- {
- generatedIds.Enqueue(generator.NextId(scopeName));
- threadIds.Enqueue(Thread.CurrentThread.ManagedThreadId);
- });
-
- // Assert we generated the right count of ids
- Assert.AreEqual(testLength, generatedIds.Count);
-
- // Assert there were no duplicates
- Assert.IsFalse(generatedIds.GroupBy(n => n).Any(g => g.Count() != 1));
-
- // Assert we used multiple threads
- var uniqueThreadsUsed = threadIds.Distinct().Count();
- if (uniqueThreadsUsed == 1)
- Assert.Inconclusive("The test failed to actually utilize multiple threads");
- }
- }
+
+ // Assert we used multiple threads
+ var uniqueThreadsUsed = threadIds.Distinct().Count();
+ if (uniqueThreadsUsed == 1)
+ Assert.Inconclusive("The test failed to actually utilize multiple threads");
}
}
\ No newline at end of file
diff --git a/README.md b/README.md
index b9997c5..482c875 100644
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@ High performance, distributed unique thread-safe id generator for Azure.
## How to use
-The project is rely on Azure Blob Storage. `AutoNumber` package will generate ids by using a single text file on the Azure Blob Storage.
-
+The project is rely on Azure Blob Storage. `AutoNumber` package will generate ids by using a single text file on the
+Azure Blob Storage.
```
var blobServiceClient = new BlobServiceClient(connectionString);
@@ -32,8 +32,9 @@ var id2 = idGen.NextId("orders");
```
### With Microsoft DI
-The project has an extension method to add it and its dependencies to Microsoft ASP.NET DI. ~~The only caveat is you need to registry type of `BlobServiceClient` in DI before registring `AutoNumber`.~~
+The project has an extension method to add it and its dependencies to Microsoft ASP.NET DI. ~~The only caveat is you
+need to registry type of `BlobServiceClient` in DI before registring `AutoNumber`.~~
Use options builder to configure the service, take into account the default settings will read from `appsettings.json`.
@@ -49,10 +50,8 @@ services.AddAutoNumber(Configuration, x =>
});
```
-
#### Deprecated way to register the service:
-
```
// configure the services
// you need to register an instane of CloudStorageAccount before using this
@@ -72,7 +71,9 @@ public class Foo
```
### Configuration
-These are default configuration for `AutoNumber`. If you prefer registering AutoNumber with `AddAddNumber` method, these options can be set via `appsettings.json`.
+
+These are default configuration for `AutoNumber`. If you prefer registering AutoNumber with `AddAddNumber` method, these
+options can be set via `appsettings.json`.
```
{
@@ -83,9 +84,14 @@ These are default configuration for `AutoNumber`. If you prefer registering Auto
}
}
```
+
### Support
-Support this proejct and me via [paypal](https://paypal.me/alibahraminezhad)
+Support this proejct and me via [paypal](https://paypal.me/alibahraminezhad)
## Credits
-Most of the credits of this library goes to [Tatham Oddie](https://tatham.blog/2011/07/14/released-snowmaker-a-unique-id-generator-for-azure-or-any-other-cloud-hosting-environment/) for making SnowMaker. I forked his work and made lots of change to make it available on .NET Standard (2.0 and 2.1). SnowMaker is out-dated and is using very old version of Azure Packages.
+
+Most of the credits of this library goes
+to [Tatham Oddie](https://tatham.blog/2011/07/14/released-snowmaker-a-unique-id-generator-for-azure-or-any-other-cloud-hosting-environment/)
+for making SnowMaker. I forked his work and made lots of change to make it available on .NET Standard (2.0 and 2.1).
+SnowMaker is out-dated and is using very old version of Azure Packages.
diff --git a/UnitTests/DictionaryExtentionsTests.cs b/UnitTests/DictionaryExtentionsTests.cs
index bf9a4bc..5be25b7 100644
--- a/UnitTests/DictionaryExtentionsTests.cs
+++ b/UnitTests/DictionaryExtentionsTests.cs
@@ -3,85 +3,84 @@
using AutoNumber.Extensions;
using NUnit.Framework;
-namespace AutoNumber.UnitTests
+namespace AutoNumber.UnitTests;
+
+[TestFixture]
+public class DictionaryExtentionsTests
{
- [TestFixture]
- public class DictionaryExtentionsTests
+ private static bool IsLockedOnCurrentThread(object lockObject)
{
- private static bool IsLockedOnCurrentThread(object lockObject)
+ var reset = new ManualResetEvent(false);
+ var couldLockBeAcquiredOnOtherThread = false;
+ new Thread(() =>
{
- var reset = new ManualResetEvent(false);
- var couldLockBeAcquiredOnOtherThread = false;
- new Thread(() =>
- {
- couldLockBeAcquiredOnOtherThread = Monitor.TryEnter(lockObject, 0);
- reset.Set();
- }).Start();
- reset.WaitOne();
- return !couldLockBeAcquiredOnOtherThread;
- }
+ couldLockBeAcquiredOnOtherThread = Monitor.TryEnter(lockObject, 0);
+ reset.Set();
+ }).Start();
+ reset.WaitOne();
+ return !couldLockBeAcquiredOnOtherThread;
+ }
- [Test]
- public void GetValueShouldCallTheValueInitializerWithinTheLockIfTheKeyDoesntExist()
+ [Test]
+ public void GetValueShouldCallTheValueInitializerWithinTheLockIfTheKeyDoesntExist()
+ {
+ var dictionary = new Dictionary
{
- var dictionary = new Dictionary
- {
- {"foo", "bar"}
- };
+ { "foo", "bar" }
+ };
- var dictionaryLock = new object();
+ var dictionaryLock = new object();
- // Act
- dictionary.GetValue(
- "bar",
- dictionaryLock,
- () =>
- {
- // Assert
- Assert.That(IsLockedOnCurrentThread(dictionaryLock), Is.True);
- return "qak";
- });
- }
+ // Act
+ dictionary.GetValue(
+ "bar",
+ dictionaryLock,
+ () =>
+ {
+ // Assert
+ Assert.That(IsLockedOnCurrentThread(dictionaryLock), Is.True);
+ return "qak";
+ });
+ }
- [Test]
- public void GetValueShouldReturnExistingValueWithoutUsingTheLock()
+ [Test]
+ public void GetValueShouldReturnExistingValueWithoutUsingTheLock()
+ {
+ var dictionary = new Dictionary
{
- var dictionary = new Dictionary
- {
- {"foo", "bar"}
- };
+ { "foo", "bar" }
+ };
- // Act
- // null can't be used as a lock and will throw an exception if attempted
- var value = dictionary.GetValue("foo", null, null);
+ // Act
+ // null can't be used as a lock and will throw an exception if attempted
+ var value = dictionary.GetValue("foo", null, null);
- // Assert
- Assert.That("bar", Is.EqualTo(value));
- }
+ // Assert
+ Assert.That("bar", Is.EqualTo(value));
+ }
- [Test]
- public void GetValueShouldStoreNewValuesAfterCallingTheValueInitializerOnce()
+ [Test]
+ public void GetValueShouldStoreNewValuesAfterCallingTheValueInitializerOnce()
+ {
+ var dictionary = new Dictionary
{
- var dictionary = new Dictionary
- {
- {"foo", "bar"}
- };
+ { "foo", "bar" }
+ };
- var dictionaryLock = new object();
+ var dictionaryLock = new object();
- // Arrange
- dictionary.GetValue("bar", dictionaryLock, () => "qak");
+ // Arrange
+ dictionary.GetValue("bar", dictionaryLock, () => "qak");
- // Act
- dictionary.GetValue(
- "bar",
- dictionaryLock,
- () =>
- {
- // Assert
- Assert.Fail("Value initializer should not have been called a second time.");
- return null;
- });
- }
+ // Act
+ dictionary.GetValue(
+ "bar",
+ dictionaryLock,
+ () =>
+ {
+ // Assert
+ Assert.Fail("Value initializer should not have been called a second time.");
+ return null;
+ });
}
}
\ No newline at end of file
diff --git a/UnitTests/UniqueIdGeneratorTest.cs b/UnitTests/UniqueIdGeneratorTest.cs
index 011a4ff..9965c42 100644
--- a/UnitTests/UniqueIdGeneratorTest.cs
+++ b/UnitTests/UniqueIdGeneratorTest.cs
@@ -5,135 +5,134 @@
using NUnit.Framework;
using NUnit.Framework.Legacy;
-namespace AutoNumber.UnitTests
+namespace AutoNumber.UnitTests;
+
+[TestFixture]
+public class UniqueIdGeneratorTest
{
- [TestFixture]
- public class UniqueIdGeneratorTest
+ [Test]
+ public void ConstructorShouldNotRetrieveDataFromStore()
{
- [Test]
- public void ConstructorShouldNotRetrieveDataFromStore()
- {
- var store = Substitute.For();
- // ReSharper disable once ObjectCreationAsStatement
- new UniqueIdGenerator(store);
- store.DidNotReceiveWithAnyArgs().GetData(null);
- }
-
- [Test]
- public void MaxWriteAttemptsShouldThrowArgumentOutOfRangeExceptionWhenValueIsNegative()
- {
- var store = Substitute.For();
- Assert.That(() =>
- // ReSharper disable once ObjectCreationAsStatement
- new UniqueIdGenerator(store)
- {
- MaxWriteAttempts = -1
- }
- , Throws.TypeOf());
- }
-
- [Test]
- public void MaxWriteAttemptsShouldThrowArgumentOutOfRangeExceptionWhenValueIsZero()
- {
- var store = Substitute.For();
- Assert.That(() =>
- // ReSharper disable once ObjectCreationAsStatement
- new UniqueIdGenerator(store)
- {
- MaxWriteAttempts = 0
- }
- , Throws.TypeOf());
- }
-
- [Test]
- public void NextIdShouldReturnNumbersSequentially()
- {
- var store = Substitute.For();
- store.GetData("test").Returns("0", "250");
- store.TryOptimisticWrite("test", "3").Returns(true);
-
- var subject = new UniqueIdGenerator(store)
- {
- BatchSize = 3
- };
-
- Assert.That(subject.NextId("test"), Is.EqualTo(0));
- Assert.That(subject.NextId("test"), Is.EqualTo(1));
- Assert.That(subject.NextId("test"), Is.EqualTo(2));
- }
-
- [Test]
- public void NextIdShouldRollOverToNewBlockWhenCurrentBlockIsExhausted()
- {
- var store = Substitute.For();
- store.GetData("test").Returns("0", "250");
- store.TryOptimisticWrite("test", "3").Returns(true);
- store.TryOptimisticWrite("test", "253").Returns(true);
-
- var subject = new UniqueIdGenerator(store)
- {
- BatchSize = 3
- };
-
- Assert.That(subject.NextId("test"), Is.EqualTo(0));
- Assert.That(subject.NextId("test"), Is.EqualTo(1));
- Assert.That(subject.NextId("test"), Is.EqualTo(2) );
- Assert.That(subject.NextId("test"), Is.EqualTo(250));
- Assert.That(subject.NextId("test"), Is.EqualTo(251));
- Assert.That(subject.NextId("test"), Is.EqualTo(252));
- }
+ var store = Substitute.For();
+ // ReSharper disable once ObjectCreationAsStatement
+ new UniqueIdGenerator(store);
+ store.DidNotReceiveWithAnyArgs().GetData(null);
+ }
- [Test]
- public void NextIdShouldThrowExceptionOnCorruptData()
- {
- var store = Substitute.For();
- store.GetData("test").Returns("abc");
+ [Test]
+ public void MaxWriteAttemptsShouldThrowArgumentOutOfRangeExceptionWhenValueIsNegative()
+ {
+ var store = Substitute.For();
+ Assert.That(() =>
+ // ReSharper disable once ObjectCreationAsStatement
+ new UniqueIdGenerator(store)
+ {
+ MaxWriteAttempts = -1
+ }
+ , Throws.TypeOf());
+ }
- Assert.That(() =>
+ [Test]
+ public void MaxWriteAttemptsShouldThrowArgumentOutOfRangeExceptionWhenValueIsZero()
+ {
+ var store = Substitute.For();
+ Assert.That(() =>
+ // ReSharper disable once ObjectCreationAsStatement
+ new UniqueIdGenerator(store)
{
- var generator = new UniqueIdGenerator(store);
- generator.NextId("test");
+ MaxWriteAttempts = 0
}
- , Throws.TypeOf());
- }
+ , Throws.TypeOf());
+ }
+
+ [Test]
+ public void NextIdShouldReturnNumbersSequentially()
+ {
+ var store = Substitute.For();
+ store.GetData("test").Returns("0", "250");
+ store.TryOptimisticWrite("test", "3").Returns(true);
- [Test]
- public void NextIdShouldThrowExceptionOnNullData()
+ var subject = new UniqueIdGenerator(store)
{
- var store = Substitute.For();
- store.GetData("test").Returns((string) null);
+ BatchSize = 3
+ };
- Assert.That(() =>
- {
- var generator = new UniqueIdGenerator(store);
- generator.NextId("test");
- }
- , Throws.TypeOf());
- }
+ Assert.That(subject.NextId("test"), Is.EqualTo(0));
+ Assert.That(subject.NextId("test"), Is.EqualTo(1));
+ Assert.That(subject.NextId("test"), Is.EqualTo(2));
+ }
+
+ [Test]
+ public void NextIdShouldRollOverToNewBlockWhenCurrentBlockIsExhausted()
+ {
+ var store = Substitute.For();
+ store.GetData("test").Returns("0", "250");
+ store.TryOptimisticWrite("test", "3").Returns(true);
+ store.TryOptimisticWrite("test", "253").Returns(true);
- [Test]
- public void NextIdShouldThrowExceptionWhenRetriesAreExhausted()
+ var subject = new UniqueIdGenerator(store)
{
- var store = Substitute.For();
- store.GetData("test").Returns("0");
- store.TryOptimisticWrite("test", "3").Returns(false, false, false, true);
+ BatchSize = 3
+ };
+
+ Assert.That(subject.NextId("test"), Is.EqualTo(0));
+ Assert.That(subject.NextId("test"), Is.EqualTo(1));
+ Assert.That(subject.NextId("test"), Is.EqualTo(2));
+ Assert.That(subject.NextId("test"), Is.EqualTo(250));
+ Assert.That(subject.NextId("test"), Is.EqualTo(251));
+ Assert.That(subject.NextId("test"), Is.EqualTo(252));
+ }
- var generator = new UniqueIdGenerator(store)
- {
- MaxWriteAttempts = 3
- };
+ [Test]
+ public void NextIdShouldThrowExceptionOnCorruptData()
+ {
+ var store = Substitute.For();
+ store.GetData("test").Returns("abc");
- try
+ Assert.That(() =>
{
+ var generator = new UniqueIdGenerator(store);
generator.NextId("test");
}
- catch (Exception ex)
+ , Throws.TypeOf());
+ }
+
+ [Test]
+ public void NextIdShouldThrowExceptionOnNullData()
+ {
+ var store = Substitute.For();
+ store.GetData("test").Returns((string)null);
+
+ Assert.That(() =>
{
- StringAssert.StartsWith("Failed to update the data store after 3 attempts.", ex.Message);
- return;
+ var generator = new UniqueIdGenerator(store);
+ generator.NextId("test");
}
+ , Throws.TypeOf());
+ }
+
+ [Test]
+ public void NextIdShouldThrowExceptionWhenRetriesAreExhausted()
+ {
+ var store = Substitute.For();
+ store.GetData("test").Returns("0");
+ store.TryOptimisticWrite("test", "3").Returns(false, false, false, true);
- Assert.Fail("NextId should have thrown and been caught in the try block");
+ var generator = new UniqueIdGenerator(store)
+ {
+ MaxWriteAttempts = 3
+ };
+
+ try
+ {
+ generator.NextId("test");
}
+ catch (Exception ex)
+ {
+ StringAssert.StartsWith("Failed to update the data store after 3 attempts.", ex.Message);
+ return;
+ }
+
+ Assert.Fail("NextId should have thrown and been caught in the try block");
}
}
\ No newline at end of file
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index 4032358..8063b09 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -1,41 +1,41 @@
-
- 8.0.30703
- AutoNumber.UnitTests
- AutoNumber.UnitTests
- ..\
- UnitTests
- Microsoft
- UnitTests
- Copyright © Microsoft 2011
- bin\$(Configuration)\
- net6.0;net8.0
-
-
- full
-
-
- pdbonly
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
+
+ 8.0.30703
+ AutoNumber.UnitTests
+ AutoNumber.UnitTests
+ ..\
+ UnitTests
+ Microsoft
+ UnitTests
+ Copyright © Microsoft 2011
+ bin\$(Configuration)\
+ net8.0;net9.0
+
+
+ full
+
+
+ pdbonly
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
\ No newline at end of file