-
-
Notifications
You must be signed in to change notification settings - Fork 13
Fixes #49: Upgrade to new Azure Storage New SDK #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
834f570
Upgrade to new Azure Storage New SDKS
niemyjski b5fd493
PR Feedback
niemyjski a789d51
PR Feedback
niemyjski 071bf23
Adds compatibility mode for Azure Storage Queue
niemyjski cdae238
Added Sample apps
niemyjski 48941ff
Merge remote-tracking branch 'origin/main' into feature/upgrade-stora…
niemyjski 78710a7
Updates Azure Storage SDK and MinVer
niemyjski cdae687
Updates Azure Storage SDKs
niemyjski 762dac2
Potential fix for pull request finding 'Dereferenced variable may be …
niemyjski 705c3fe
Updates Azure Blob Storage SDK usage
niemyjski 1666c2e
Adds healthcheck to azurite and improves ready condition
niemyjski 29e6aed
Improves Azure Storage Queue and File Storage
niemyjski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <Project> | ||
| <Import Project="..\build\common.props" /> | ||
| <PropertyGroup> | ||
| <TargetFrameworks>net8.0</TargetFrameworks> | ||
| <OutputType>Exe</OutputType> | ||
| <IsPackable>False</IsPackable> | ||
| </PropertyGroup> | ||
| </Project> |
9 changes: 9 additions & 0 deletions
9
samples/Foundatio.AzureStorage.Dequeue/Foundatio.AzureStorage.Dequeue.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\Foundatio.AzureStorage\Foundatio.AzureStorage.csproj" /> | ||
| <ProjectReference Include="..\Foundatio.AzureStorage.Enqueue\Foundatio.AzureStorage.Enqueue.csproj" /> | ||
| <PackageReference Include="System.CommandLine" Version="2.0.1" /> | ||
| <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" /> | ||
| </ItemGroup> | ||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| using System; | ||
| using System.CommandLine; | ||
| using System.Linq; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Foundatio.AzureStorage.Samples; | ||
| using Foundatio.Queues; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| // Azure Storage Emulator connection string | ||
| const string EmulatorConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;QueueEndpoint=http://localhost:10001/devstoreaccount1;"; | ||
|
|
||
| // Define options | ||
| var connectionStringOption = new Option<string>("--connection-string", "-c") | ||
| { | ||
| Description = "Azure Storage connection string (defaults to emulator)" | ||
| }; | ||
|
|
||
| var queueOption = new Option<string>("--queue", "-q") | ||
| { | ||
| Description = "Queue name", | ||
| DefaultValueFactory = _ => "sample-queue" | ||
| }; | ||
|
|
||
| var modeOption = new Option<AzureStorageQueueCompatibilityMode>("--mode") | ||
| { | ||
| Description = "Compatibility mode (Default or Legacy)", | ||
| DefaultValueFactory = _ => AzureStorageQueueCompatibilityMode.Default | ||
| }; | ||
|
|
||
| var countOption = new Option<int>("--count") | ||
| { | ||
| Description = "Number of messages to process (0 = infinite)", | ||
| DefaultValueFactory = _ => 1 | ||
| }; | ||
|
|
||
| // Create root command | ||
| var rootCommand = new RootCommand("Azure Storage Queue Dequeue Sample"); | ||
| rootCommand.Options.Add(connectionStringOption); | ||
| rootCommand.Options.Add(queueOption); | ||
| rootCommand.Options.Add(modeOption); | ||
| rootCommand.Options.Add(countOption); | ||
|
|
||
| // Set handler | ||
| rootCommand.SetAction(async parseResult => | ||
| { | ||
| var connectionString = parseResult.GetValue(connectionStringOption) ?? | ||
| Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING") ?? | ||
| EmulatorConnectionString; | ||
|
|
||
| var queueName = parseResult.GetValue(queueOption); | ||
| var mode = parseResult.GetValue(modeOption); | ||
| var count = parseResult.GetValue(countOption); | ||
|
|
||
| Console.WriteLine($"Using connection: {(connectionString == EmulatorConnectionString ? "Azure Storage Emulator" : "Custom connection string")}"); | ||
| Console.WriteLine($"Mode: {mode}"); | ||
| Console.WriteLine($"Queue: {queueName}"); | ||
| Console.WriteLine($"To process: {(count == 0 ? "infinite messages" : $"{count} message(s)")}"); | ||
| Console.WriteLine(); | ||
| Console.WriteLine("Press Ctrl+C to stop..."); | ||
| Console.WriteLine(); | ||
|
|
||
| await DequeueMessages(connectionString, queueName, mode, count); | ||
| return 0; | ||
| }); | ||
|
|
||
| // Parse and invoke | ||
| return await rootCommand.Parse(args).InvokeAsync(); | ||
|
|
||
| static async Task DequeueMessages(string connectionString, string queueName, AzureStorageQueueCompatibilityMode mode, int count) | ||
| { | ||
| using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information)); | ||
| var logger = loggerFactory.CreateLogger("Dequeue"); | ||
| using var cts = new CancellationTokenSource(); | ||
|
|
||
| Console.CancelKeyPress += (s, e) => | ||
| { | ||
| e.Cancel = true; | ||
| try | ||
| { | ||
| cts.Cancel(); | ||
| } | ||
| catch | ||
| { | ||
| // ignored | ||
| } | ||
niemyjski marked this conversation as resolved.
Dismissed
Show dismissed
Hide dismissed
|
||
|
|
||
| logger.LogInformation("Cancellation requested..."); | ||
| }; | ||
|
|
||
| logger.LogInformation("Creating queue with mode: {Mode}", mode); | ||
|
|
||
| using var queue = new AzureStorageQueue<SampleMessage>(options => options | ||
| .ConnectionString(connectionString) | ||
| .Name(queueName) | ||
| .CompatibilityMode(mode) | ||
| .LoggerFactory(loggerFactory)); | ||
|
|
||
| int processed = 0; | ||
| bool infinite = count == 0; | ||
|
|
||
| logger.LogInformation("Waiting for messages... (Press Ctrl+C to stop)"); | ||
|
|
||
| try | ||
| { | ||
| while (!cts.Token.IsCancellationRequested && (infinite || processed < count)) | ||
| { | ||
| var entry = await queue.DequeueAsync(cts.Token); | ||
|
|
||
| if (entry == null) | ||
| { | ||
| if (!infinite && processed >= count) | ||
| break; | ||
|
|
||
| continue; | ||
| } | ||
|
|
||
| try | ||
| { | ||
| processed++; | ||
|
|
||
| logger.LogInformation("Dequeued message {MessageId}: '{Message}' from '{Source}' at {Timestamp}", | ||
| entry.Id, entry.Value.Message, entry.Value.Source, entry.Value.Timestamp); | ||
|
|
||
| logger.LogInformation(" CorrelationId: '{CorrelationId}'", entry.CorrelationId ?? "<none>"); | ||
|
|
||
| if (entry.Properties != null && entry.Properties.Count > 0) | ||
| { | ||
| logger.LogInformation(" Properties: [{Properties}]", | ||
| string.Join(", ", entry.Properties.Select(p => $"{p.Key}={p.Value}"))); | ||
| } | ||
| else | ||
| { | ||
| logger.LogInformation(" Properties: <none>"); | ||
| } | ||
|
|
||
| // Simulate processing time | ||
| await Task.Delay(100, cts.Token); | ||
|
|
||
| await entry.CompleteAsync(); | ||
| logger.LogInformation(" Completed message {MessageId}", entry.Id); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogError(ex, "Error processing message {MessageId}", entry.Id); | ||
| await entry.AbandonAsync(); | ||
| } | ||
niemyjski marked this conversation as resolved.
Dismissed
Show dismissed
Hide dismissed
|
||
| } | ||
| } | ||
| catch (OperationCanceledException ex) | ||
| { | ||
| logger.LogInformation(ex, "Operation was cancelled"); | ||
| } | ||
|
|
||
| logger.LogInformation("Processed {ProcessedCount} message(s)", processed); | ||
| } | ||
8 changes: 8 additions & 0 deletions
8
samples/Foundatio.AzureStorage.Enqueue/Foundatio.AzureStorage.Enqueue.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\Foundatio.AzureStorage\Foundatio.AzureStorage.csproj" /> | ||
| <PackageReference Include="System.CommandLine" Version="2.0.1" /> | ||
| <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> | ||
| <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" /> | ||
| </ItemGroup> | ||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.CommandLine; | ||
| using System.Linq; | ||
| using System.Threading.Tasks; | ||
| using Foundatio.AzureStorage.Samples; | ||
| using Foundatio.Queues; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| // Azure Storage Emulator connection string | ||
| const string EmulatorConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:10000/devstoreaccount1;QueueEndpoint=http://localhost:10001/devstoreaccount1;"; | ||
|
|
||
| // Define options | ||
| var connectionStringOption = new Option<string>("--connection-string", "-c") | ||
| { | ||
| Description = "Azure Storage connection string (defaults to emulator)" | ||
| }; | ||
|
|
||
| var queueOption = new Option<string>("--queue", "-q") | ||
| { | ||
| Description = "Queue name", | ||
| DefaultValueFactory = _ => "sample-queue" | ||
| }; | ||
|
|
||
| var messageOption = new Option<string>("--message", "-m") | ||
| { | ||
| Description = "Message to send", | ||
| DefaultValueFactory = _ => "Hello World" | ||
| }; | ||
|
|
||
| var correlationIdOption = new Option<string>("--correlation-id") | ||
| { | ||
| Description = "Correlation ID for the message" | ||
| }; | ||
|
|
||
| var propertiesOption = new Option<string[]>("--property") | ||
| { | ||
| Description = "Custom properties in key=value format", | ||
| DefaultValueFactory = _ => Array.Empty<string>() | ||
| }; | ||
|
|
||
| var modeOption = new Option<AzureStorageQueueCompatibilityMode>("--mode") | ||
| { | ||
| Description = "Compatibility mode (Default or Legacy)", | ||
| DefaultValueFactory = _ => AzureStorageQueueCompatibilityMode.Default | ||
| }; | ||
|
|
||
| var countOption = new Option<int>("--count") | ||
| { | ||
| Description = "Number of messages to send", | ||
| DefaultValueFactory = _ => 1 | ||
| }; | ||
niemyjski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Create root command | ||
| var rootCommand = new RootCommand("Azure Storage Queue Enqueue Sample"); | ||
| rootCommand.Options.Add(connectionStringOption); | ||
| rootCommand.Options.Add(queueOption); | ||
| rootCommand.Options.Add(messageOption); | ||
| rootCommand.Options.Add(correlationIdOption); | ||
| rootCommand.Options.Add(propertiesOption); | ||
| rootCommand.Options.Add(modeOption); | ||
| rootCommand.Options.Add(countOption); | ||
|
|
||
| // Set handler | ||
| rootCommand.SetAction(async parseResult => | ||
| { | ||
| var connectionString = parseResult.GetValue(connectionStringOption) ?? | ||
| Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING") ?? | ||
| EmulatorConnectionString; | ||
|
|
||
| var queueName = parseResult.GetValue(queueOption); | ||
| var message = parseResult.GetValue(messageOption); | ||
| var correlationId = parseResult.GetValue(correlationIdOption); | ||
| var properties = parseResult.GetValue(propertiesOption); | ||
| var mode = parseResult.GetValue(modeOption); | ||
| var count = parseResult.GetValue(countOption); | ||
|
|
||
| Console.WriteLine($"Using connection: {(connectionString == EmulatorConnectionString ? "Azure Storage Emulator" : "Custom connection string")}"); | ||
| Console.WriteLine($"Mode: {mode}"); | ||
| Console.WriteLine(); | ||
|
|
||
| await EnqueueMessages(connectionString, queueName, message, correlationId, properties, mode, count); | ||
| return 0; | ||
| }); | ||
|
|
||
niemyjski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Parse and invoke | ||
| return await rootCommand.Parse(args).InvokeAsync(); | ||
niemyjski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| static async Task EnqueueMessages(string connectionString, string queueName, string message, string correlationId, string[] properties, AzureStorageQueueCompatibilityMode mode, int count) | ||
| { | ||
| using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information)); | ||
| var logger = loggerFactory.CreateLogger("Enqueue"); | ||
|
|
||
| logger.LogInformation("Creating queue with mode: {Mode}", mode); | ||
|
|
||
| using var queue = new AzureStorageQueue<SampleMessage>(options => options | ||
| .ConnectionString(connectionString) | ||
| .Name(queueName) | ||
| .CompatibilityMode(mode) | ||
| .LoggerFactory(loggerFactory)); | ||
|
|
||
| var queueProperties = new Dictionary<string, string>(); | ||
| if (properties != null) | ||
| { | ||
| foreach (var prop in properties) | ||
| { | ||
| var parts = prop.Split('=', 2); | ||
| if (parts.Length == 2) | ||
| { | ||
| queueProperties[parts[0]] = parts[1]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < count; i++) | ||
| { | ||
| var sampleMessage = new SampleMessage | ||
| { | ||
| Message = count > 1 ? $"{message} #{i + 1}" : message, | ||
| Source = "Enqueue Sample" | ||
| }; | ||
|
|
||
| var entryOptions = new QueueEntryOptions | ||
| { | ||
| CorrelationId = correlationId, | ||
| Properties = queueProperties.Count > 0 ? queueProperties : null | ||
| }; | ||
|
|
||
| var messageId = await queue.EnqueueAsync(sampleMessage, entryOptions); | ||
|
|
||
| logger.LogInformation("Enqueued message {MessageId}: '{Message}' with CorrelationId: '{CorrelationId}' Properties: [{Properties}]", | ||
| messageId, sampleMessage.Message, correlationId ?? "<none>", | ||
| string.Join(", ", queueProperties.Select(p => $"{p.Key}={p.Value}"))); | ||
| } | ||
|
|
||
| logger.LogInformation("Successfully enqueued {Count} message(s)", count); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| using System; | ||
|
|
||
| namespace Foundatio.AzureStorage.Samples; | ||
|
|
||
| public record SampleMessage | ||
| { | ||
| public string Message { get; init; } = string.Empty; | ||
| public DateTime Timestamp { get; init; } = DateTime.UtcNow; | ||
| public string Source { get; init; } = string.Empty; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.