diff --git a/src/Custom.Build.props b/src/Custom.Build.props
index 5b885869..48ebfd96 100644
--- a/src/Custom.Build.props
+++ b/src/Custom.Build.props
@@ -5,7 +5,7 @@
- 5.0
+ 6.0
minor
diff --git a/src/IntegrationTests.HostV4/When_starting_the_function_host.cs b/src/IntegrationTests.HostV4/When_starting_the_function_host.cs
index 9fb7a972..4615e882 100644
--- a/src/IntegrationTests.HostV4/When_starting_the_function_host.cs
+++ b/src/IntegrationTests.HostV4/When_starting_the_function_host.cs
@@ -1,204 +1,203 @@
-namespace ServiceBus.Tests
+namespace ServiceBus.Tests;
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus.Administration;
+using Microsoft.Extensions.Configuration;
+using NUnit.Framework;
+
+[TestFixture]
+public class When_starting_the_function_host
{
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus.Administration;
- using Microsoft.Extensions.Configuration;
- using NUnit.Framework;
-
- [TestFixture]
- public class When_starting_the_function_host
+ [Test]
+ public async Task Should_not_blow_up()
{
- [Test]
- public async Task Should_not_blow_up()
- {
- var configBuilder = new ConfigurationBuilder();
- configBuilder.SetBasePath(Directory.GetCurrentDirectory());
- configBuilder.AddEnvironmentVariables();
- configBuilder.AddJsonFile("local.settings.json", true);
+ var configBuilder = new ConfigurationBuilder();
+ configBuilder.SetBasePath(Directory.GetCurrentDirectory());
+ configBuilder.AddEnvironmentVariables();
+ configBuilder.AddJsonFile("local.settings.json", true);
- var config = configBuilder.Build();
+ var config = configBuilder.Build();
- var pathToFuncExe = config.GetValue("PathToFuncExe");
+ var pathToFuncExe = config.GetValue("PathToFuncExe");
- if (pathToFuncExe == null)
- {
- Console.WriteLine("Environment variable 'PathToFuncExe' not defined. Going to try to find the latest version.");
+ if (pathToFuncExe == null)
+ {
+ Console.WriteLine("Environment variable 'PathToFuncExe' not defined. Going to try to find the latest version.");
- var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
- var sdkPath = Path.Combine(userProfile, "AppData", "Local", "AzureFunctionsTools", "Releases");
- if (Directory.Exists(sdkPath))
+ var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+ var sdkPath = Path.Combine(userProfile, "AppData", "Local", "AzureFunctionsTools", "Releases");
+ if (Directory.Exists(sdkPath))
+ {
+ var mostRecent = Directory.GetDirectories(sdkPath)
+ .Select(path =>
+ {
+ var name = Path.GetFileName(path);
+ Version.TryParse(name, out var version);
+ return new { Name = name, Version = version };
+ })
+ .Where(x => x.Version is not null)
+ .OrderByDescending(x => x.Version)
+ .FirstOrDefault()
+ ?.Name;
+
+ if (mostRecent is not null)
{
- var mostRecent = Directory.GetDirectories(sdkPath)
- .Select(path =>
- {
- var name = Path.GetFileName(path);
- Version.TryParse(name, out var version);
- return new { Name = name, Version = version };
- })
- .Where(x => x.Version is not null)
- .OrderByDescending(x => x.Version)
- .FirstOrDefault()
- ?.Name;
-
- if (mostRecent is not null)
+ var exePath = Path.Combine(sdkPath, mostRecent, "cli_x64", "func.exe");
+ if (File.Exists(exePath))
{
- var exePath = Path.Combine(sdkPath, mostRecent, "cli_x64", "func.exe");
- if (File.Exists(exePath))
- {
- Console.WriteLine("Found " + exePath);
- pathToFuncExe = exePath;
- }
+ Console.WriteLine("Found " + exePath);
+ pathToFuncExe = exePath;
}
}
}
+ }
+
+ Assert.That(pathToFuncExe, Is.Not.Null, "Environment variable 'PathToFuncExe' should be defined to run tests. When running locally this is usually 'C:\\Users\\\\AppData\\Local\\AzureFunctionsTools\\Releases\\\\cli_x64\\func.exe'");
+
+ var connectionString = config.GetValue("AzureWebJobsServiceBus") ?? config.GetValue("Values:AzureWebJobsServiceBus");
+ Assert.That(connectionString, Is.Not.Null, "Environment variable 'AzureWebJobsServiceBus' should be defined to run tests.");
- Assert.That(pathToFuncExe, Is.Not.Null, "Environment variable 'PathToFuncExe' should be defined to run tests. When running locally this is usually 'C:\\Users\\\\AppData\\Local\\AzureFunctionsTools\\Releases\\\\cli_x64\\func.exe'");
+ var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60));
+ var client = new ServiceBusAdministrationClient(connectionString);
- var connectionString = config.GetValue("AzureWebJobsServiceBus") ?? config.GetValue("Values:AzureWebJobsServiceBus");
- Assert.That(connectionString, Is.Not.Null, "Environment variable 'AzureWebJobsServiceBus' should be defined to run tests.");
+ const string queueName = "inprocess-hostv4";
+ const string topicName = "bundle-1";
- var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60));
- var client = new ServiceBusAdministrationClient(connectionString);
+ if (!await client.QueueExistsAsync(queueName, cancellationTokenSource.Token))
+ {
+ await client.CreateQueueAsync(queueName, cancellationTokenSource.Token);
+ }
- const string queueName = "inprocess-hostv4";
- const string topicName = "bundle-1";
+ if (!await client.TopicExistsAsync(topicName, cancellationTokenSource.Token))
+ {
+ await client.CreateTopicAsync(topicName, cancellationTokenSource.Token);
+ }
- if (!await client.QueueExistsAsync(queueName, cancellationTokenSource.Token))
+ if (!await client.SubscriptionExistsAsync(topicName, queueName, cancellationTokenSource.Token))
+ {
+ var subscription = new CreateSubscriptionOptions(topicName, queueName)
{
- await client.CreateQueueAsync(queueName, cancellationTokenSource.Token);
- }
+ LockDuration = TimeSpan.FromMinutes(5),
+ ForwardTo = queueName,
+ EnableDeadLetteringOnFilterEvaluationExceptions = false,
+ MaxDeliveryCount = int.MaxValue,
+ EnableBatchedOperations = true,
+ UserMetadata = queueName
+ };
+ await client.CreateSubscriptionAsync(subscription, cancellationTokenSource.Token);
+ }
- if (!await client.TopicExistsAsync(topicName, cancellationTokenSource.Token))
+ var functionRootDir = new DirectoryInfo(TestContext.CurrentContext.TestDirectory);
+ var port = 7076; //Use non-standard port to avoid clashing when debugging locally
+ var funcProcess = new Process();
+ var httpClient = new HttpClient();
+ var hasResult = false;
+ var hostFailed = false;
+ var eventHandlerCalled = false;
+ var commandHandlerCalled = false;
+ var someEventTaskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ var someOtherMessageTaskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+
+ cancellationTokenSource.Token.Register(state => ((TaskCompletionSource)state).TrySetResult(false), someEventTaskCompletionSource);
+ cancellationTokenSource.Token.Register(state => ((TaskCompletionSource)state).TrySetResult(false), someOtherMessageTaskCompletionSource);
+
+ funcProcess.StartInfo.WorkingDirectory = functionRootDir.FullName;
+ funcProcess.StartInfo.Arguments = $"start --port {port} --no-build --verbose";
+ funcProcess.StartInfo.FileName = pathToFuncExe;
+
+ funcProcess.StartInfo.UseShellExecute = false;
+ funcProcess.StartInfo.RedirectStandardOutput = true;
+ funcProcess.StartInfo.RedirectStandardError = true;
+ funcProcess.StartInfo.CreateNoWindow = true;
+ funcProcess.ErrorDataReceived += (_, e) =>
+ {
+ if (e.Data == null)
{
- await client.CreateTopicAsync(topicName, cancellationTokenSource.Token);
+ return;
}
- if (!await client.SubscriptionExistsAsync(topicName, queueName, cancellationTokenSource.Token))
+ hostFailed = true;
+ TestContext.Out.WriteLine(e.Data);
+
+ cancellationTokenSource.Cancel();
+ };
+ funcProcess.OutputDataReceived += (_, e) =>
+ {
+ if (e.Data == null)
{
- var subscription = new CreateSubscriptionOptions(topicName, queueName)
- {
- LockDuration = TimeSpan.FromMinutes(5),
- ForwardTo = queueName,
- EnableDeadLetteringOnFilterEvaluationExceptions = false,
- MaxDeliveryCount = int.MaxValue,
- EnableBatchedOperations = true,
- UserMetadata = queueName
- };
- await client.CreateSubscriptionAsync(subscription, cancellationTokenSource.Token);
+ return;
}
- var functionRootDir = new DirectoryInfo(TestContext.CurrentContext.TestDirectory);
- var port = 7076; //Use non-standard port to avoid clashing when debugging locally
- var funcProcess = new Process();
- var httpClient = new HttpClient();
- var hasResult = false;
- var hostFailed = false;
- var eventHandlerCalled = false;
- var commandHandlerCalled = false;
- var someEventTaskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- var someOtherMessageTaskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
-
- cancellationTokenSource.Token.Register(state => ((TaskCompletionSource)state).TrySetResult(false), someEventTaskCompletionSource);
- cancellationTokenSource.Token.Register(state => ((TaskCompletionSource)state).TrySetResult(false), someOtherMessageTaskCompletionSource);
-
- funcProcess.StartInfo.WorkingDirectory = functionRootDir.FullName;
- funcProcess.StartInfo.Arguments = $"start --port {port} --no-build --verbose";
- funcProcess.StartInfo.FileName = pathToFuncExe;
-
- funcProcess.StartInfo.UseShellExecute = false;
- funcProcess.StartInfo.RedirectStandardOutput = true;
- funcProcess.StartInfo.RedirectStandardError = true;
- funcProcess.StartInfo.CreateNoWindow = true;
- funcProcess.ErrorDataReceived += (_, e) =>
+ TestContext.Out.WriteLine(e.Data);
+
+ if (e.Data.Contains($"Handling {nameof(SomeOtherMessage)}"))
{
- if (e.Data == null)
- {
- return;
- }
+ someOtherMessageTaskCompletionSource.SetResult(true);
+ }
- hostFailed = true;
- TestContext.Out.WriteLine(e.Data);
+ if (e.Data.Contains($"Handling {nameof(SomeEvent)}"))
+ {
+ someEventTaskCompletionSource.SetResult(true);
+ }
+ };
+ funcProcess.EnableRaisingEvents = true;
+ funcProcess.Start();
+ funcProcess.BeginOutputReadLine();
+ funcProcess.BeginErrorReadLine();
- cancellationTokenSource.Cancel();
- };
- funcProcess.OutputDataReceived += (_, e) =>
+ try
+ {
+ while (!cancellationTokenSource.IsCancellationRequested && !hasResult)
{
- if (e.Data == null)
+ try
{
- return;
- }
+ var result = await httpClient.GetAsync($"http://localhost:{port}/api/InProcessHttpSenderV4", cancellationTokenSource.Token);
- TestContext.Out.WriteLine(e.Data);
+ result.EnsureSuccessStatusCode();
- if (e.Data.Contains($"Handling {nameof(SomeOtherMessage)}"))
- {
- someOtherMessageTaskCompletionSource.SetResult(true);
+ hasResult = true;
}
-
- if (e.Data.Contains($"Handling {nameof(SomeEvent)}"))
+ catch (OperationCanceledException) when (cancellationTokenSource.Token.IsCancellationRequested)
{
- someEventTaskCompletionSource.SetResult(true);
}
- };
- funcProcess.EnableRaisingEvents = true;
- funcProcess.Start();
- funcProcess.BeginOutputReadLine();
- funcProcess.BeginErrorReadLine();
-
- try
- {
- while (!cancellationTokenSource.IsCancellationRequested && !hasResult)
+ catch (Exception ex)
{
- try
- {
- var result = await httpClient.GetAsync($"http://localhost:{port}/api/InProcessHttpSenderV4", cancellationTokenSource.Token);
-
- result.EnsureSuccessStatusCode();
-
- hasResult = true;
- }
- catch (OperationCanceledException) when (cancellationTokenSource.Token.IsCancellationRequested)
- {
- }
- catch (Exception ex)
- {
- await TestContext.Out.WriteLineAsync(ex.Message);
- await Task.Delay(TimeSpan.FromSeconds(1), cancellationTokenSource.Token);
- }
+ await TestContext.Out.WriteLineAsync(ex.Message);
+ await Task.Delay(TimeSpan.FromSeconds(1), cancellationTokenSource.Token);
}
+ }
- await Task.WhenAll(someEventTaskCompletionSource.Task, someOtherMessageTaskCompletionSource.Task);
+ await Task.WhenAll(someEventTaskCompletionSource.Task, someOtherMessageTaskCompletionSource.Task);
- eventHandlerCalled = await someEventTaskCompletionSource.Task;
- commandHandlerCalled = await someOtherMessageTaskCompletionSource.Task;
+ eventHandlerCalled = await someEventTaskCompletionSource.Task;
+ commandHandlerCalled = await someOtherMessageTaskCompletionSource.Task;
- funcProcess.Kill();
- }
- finally
+ funcProcess.Kill();
+ }
+ finally
+ {
+ try
{
- try
- {
- await funcProcess.WaitForExitAsync(cancellationTokenSource.Token);
- }
- catch (OperationCanceledException) when (cancellationTokenSource.Token.IsCancellationRequested)
- {
- funcProcess.Kill();
- }
+ await funcProcess.WaitForExitAsync(cancellationTokenSource.Token);
}
-
- Assert.Multiple(() =>
+ catch (OperationCanceledException) when (cancellationTokenSource.Token.IsCancellationRequested)
{
- Assert.That(hostFailed, Is.False, "Host should startup without errors");
- Assert.That(hasResult, Is.True, "Http trigger should respond successfully");
- Assert.That(commandHandlerCalled, Is.True, $"{nameof(SomeOtherMessageHandler)} should have been called");
- Assert.That(eventHandlerCalled, Is.True, $"{nameof(SomeEventMessageHandler)} should have been called");
- });
+ funcProcess.Kill();
+ }
}
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(hostFailed, Is.False, "Host should startup without errors");
+ Assert.That(hasResult, Is.True, "Http trigger should respond successfully");
+ Assert.That(commandHandlerCalled, Is.True, $"{nameof(SomeOtherMessageHandler)} should have been called");
+ Assert.That(eventHandlerCalled, Is.True, $"{nameof(SomeEventMessageHandler)} should have been called");
+ });
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/AnalyzerTestFixture.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/AnalyzerTestFixture.cs
index 61a7dc87..9fa69454 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/AnalyzerTestFixture.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/AnalyzerTestFixture.cs
@@ -1,216 +1,215 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Text;
+using NUnit.Framework;
+
+public class AnalyzerTestFixture where TAnalyzer : DiagnosticAnalyzer, new()
{
- using System;
- using System.Collections.Generic;
- using System.Collections.Immutable;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Core;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CSharp;
- using Microsoft.CodeAnalysis.Diagnostics;
- using Microsoft.CodeAnalysis.Text;
- using NUnit.Framework;
-
- public class AnalyzerTestFixture where TAnalyzer : DiagnosticAnalyzer, new()
- {
- protected virtual LanguageVersion AnalyzerLanguageVersion => LanguageVersion.CSharp7;
+ protected virtual LanguageVersion AnalyzerLanguageVersion => LanguageVersion.CSharp7;
- protected Task Assert(string markupCode, CancellationToken cancellationToken = default) =>
- Assert(Array.Empty(), markupCode, Array.Empty(), cancellationToken);
+ protected Task Assert(string markupCode, CancellationToken cancellationToken = default) =>
+ Assert([], markupCode, [], cancellationToken);
- protected Task Assert(string expectedDiagnosticId, string markupCode, CancellationToken cancellationToken = default) =>
- Assert(new[] { expectedDiagnosticId }, markupCode, Array.Empty(), cancellationToken);
+ protected Task Assert(string expectedDiagnosticId, string markupCode, CancellationToken cancellationToken = default) =>
+ Assert([expectedDiagnosticId], markupCode, [], cancellationToken);
- protected async Task Assert(string[] expectedDiagnosticIds, string markupCode, string[] ignoreDiagnosticIds, CancellationToken cancellationToken = default)
- {
- var (code, markupSpans) = Parse(markupCode);
+ protected async Task Assert(string[] expectedDiagnosticIds, string markupCode, string[] ignoreDiagnosticIds, CancellationToken cancellationToken = default)
+ {
+ var (code, markupSpans) = Parse(markupCode);
- var project = CreateProject(code);
- await WriteCode(project, cancellationToken);
+ var project = CreateProject(code);
+ await WriteCode(project, cancellationToken);
- var compilerDiagnostics = (await Task.WhenAll(project.Documents
+ var compilerDiagnostics = (await Task.WhenAll(project.Documents
.Select(doc => doc.GetCompilerDiagnostics(cancellationToken))))
- .SelectMany(diagnostics => diagnostics);
+ .SelectMany(diagnostics => diagnostics);
- WriteCompilerDiagnostics(compilerDiagnostics);
+ WriteCompilerDiagnostics(compilerDiagnostics);
- var compilation = await project.GetCompilationAsync(cancellationToken);
- compilation.Compile();
+ var compilation = await project.GetCompilationAsync(cancellationToken);
+ compilation.Compile();
- var analyzerDiagnostics = (await compilation.GetAnalyzerDiagnostics(new TAnalyzer(), cancellationToken))
- .Where(d => !ignoreDiagnosticIds.Contains(d.Id))
- .ToList();
- WriteAnalyzerDiagnostics(analyzerDiagnostics);
+ var analyzerDiagnostics = (await compilation.GetAnalyzerDiagnostics(new TAnalyzer(), cancellationToken))
+ .Where(d => !ignoreDiagnosticIds.Contains(d.Id))
+ .ToList();
+ WriteAnalyzerDiagnostics(analyzerDiagnostics);
- var expectedSpansAndIds = expectedDiagnosticIds
- .SelectMany(id => markupSpans.Select(span => (span.file, span.span, id)))
- .OrderBy(item => item.span)
- .ThenBy(item => item.id)
- .ToList();
+ var expectedSpansAndIds = expectedDiagnosticIds
+ .SelectMany(id => markupSpans.Select(span => (span.file, span.span, id)))
+ .OrderBy(item => item.span)
+ .ThenBy(item => item.id)
+ .ToList();
- var actualSpansAndIds = analyzerDiagnostics
- .Select(diagnostic => (diagnostic.Location.SourceTree.FilePath, diagnostic.Location.SourceSpan, diagnostic.Id))
- .ToList();
+ var actualSpansAndIds = analyzerDiagnostics
+ .Select(diagnostic => (diagnostic.Location.SourceTree.FilePath, diagnostic.Location.SourceSpan, diagnostic.Id))
+ .ToList();
- NUnit.Framework.Assert.That(actualSpansAndIds, Is.EqualTo(expectedSpansAndIds).AsCollection);
- }
+ NUnit.Framework.Assert.That(actualSpansAndIds, Is.EqualTo(expectedSpansAndIds).AsCollection);
+ }
- protected static async Task WriteCode(Project project, CancellationToken cancellationToken = default)
+ protected static async Task WriteCode(Project project, CancellationToken cancellationToken = default)
+ {
+ if (!VerboseLogging)
{
- if (!VerboseLogging)
- {
- return;
- }
+ return;
+ }
- foreach (var document in project.Documents)
+ foreach (var document in project.Documents)
+ {
+ Console.WriteLine(document.Name);
+ var code = await document.GetCode(cancellationToken);
+ foreach (var (line, index) in code.Replace("\r\n", "\n").Split('\n')
+ .Select((line, index) => (line, index)))
{
- Console.WriteLine(document.Name);
- var code = await document.GetCode(cancellationToken);
- foreach (var (line, index) in code.Replace("\r\n", "\n").Split('\n')
- .Select((line, index) => (line, index)))
- {
- Console.WriteLine($" {index + 1,3}: {line}");
- }
+ Console.WriteLine($" {index + 1,3}: {line}");
}
-
}
- static readonly ImmutableDictionary DiagnosticOptions = new Dictionary
+ }
+
+ static readonly ImmutableDictionary DiagnosticOptions = new Dictionary
{
{ "CS1701", ReportDiagnostic.Hidden }
}
.ToImmutableDictionary();
- protected Project CreateProject(string[] code)
+ protected Project CreateProject(string[] code)
+ {
+ var workspace = new AdhocWorkspace();
+ var project = workspace.AddProject("TestProject", LanguageNames.CSharp)
+ .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
+ .WithSpecificDiagnosticOptions(DiagnosticOptions))
+ .WithParseOptions(new CSharpParseOptions(AnalyzerLanguageVersion))
+ .AddMetadataReferences(ProjectReferences);
+
+ for (int i = 0; i < code.Length; i++)
{
- var workspace = new AdhocWorkspace();
- var project = workspace.AddProject("TestProject", LanguageNames.CSharp)
- .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
- .WithSpecificDiagnosticOptions(DiagnosticOptions))
- .WithParseOptions(new CSharpParseOptions(AnalyzerLanguageVersion))
- .AddMetadataReferences(ProjectReferences);
-
- for (int i = 0; i < code.Length; i++)
- {
- project = project.AddDocument($"TestDocument{i}", code[i]).Project;
- }
-
- return project;
+ project = project.AddDocument($"TestDocument{i}", code[i]).Project;
}
- static AnalyzerTestFixture()
- {
- ProjectReferences =
- [
- MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(typeof(System.Linq.Expressions.Expression).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
- MetadataReference.CreateFromFile(typeof(IFunctionEndpoint).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(typeof(TokenCredential).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(typeof(EndpointConfiguration).GetTypeInfo().Assembly.Location),
- MetadataReference.CreateFromFile(typeof(AzureServiceBusTransport).GetTypeInfo().Assembly.Location),
- ];
- }
+ return project;
+ }
- static readonly ImmutableList ProjectReferences;
+ static AnalyzerTestFixture()
+ {
+ ProjectReferences =
+ [
+ MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(System.Linq.Expressions.Expression).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
+ MetadataReference.CreateFromFile(typeof(IFunctionEndpoint).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(TokenCredential).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(EndpointConfiguration).GetTypeInfo().Assembly.Location),
+ MetadataReference.CreateFromFile(typeof(AzureServiceBusTransport).GetTypeInfo().Assembly.Location),
+ ];
+ }
- static readonly Regex DocumentSplittingRegex = new Regex("^-{5,}.*", RegexOptions.Compiled | RegexOptions.Multiline);
+ static readonly ImmutableList ProjectReferences;
- protected static void WriteCompilerDiagnostics(IEnumerable diagnostics)
+ static readonly Regex DocumentSplittingRegex = new Regex("^-{5,}.*", RegexOptions.Compiled | RegexOptions.Multiline);
+
+ protected static void WriteCompilerDiagnostics(IEnumerable diagnostics)
+ {
+ if (!VerboseLogging)
{
- if (!VerboseLogging)
- {
- return;
- }
+ return;
+ }
- Console.WriteLine("Compiler diagnostics:");
+ Console.WriteLine("Compiler diagnostics:");
- foreach (var diagnostic in diagnostics)
- {
- Console.WriteLine($" {diagnostic}");
- }
+ foreach (var diagnostic in diagnostics)
+ {
+ Console.WriteLine($" {diagnostic}");
}
+ }
- protected static void WriteAnalyzerDiagnostics(IEnumerable diagnostics)
+ protected static void WriteAnalyzerDiagnostics(IEnumerable diagnostics)
+ {
+ if (!VerboseLogging)
{
- if (!VerboseLogging)
- {
- return;
- }
+ return;
+ }
- Console.WriteLine("Analyzer diagnostics:");
+ Console.WriteLine("Analyzer diagnostics:");
- foreach (var diagnostic in diagnostics)
- {
- Console.WriteLine($" {diagnostic}");
- }
+ foreach (var diagnostic in diagnostics)
+ {
+ Console.WriteLine($" {diagnostic}");
}
+ }
+
+ protected static string[] SplitMarkupCodeIntoFiles(string markupCode)
+ {
+ return DocumentSplittingRegex.Split(markupCode)
+ .Where(docCode => !string.IsNullOrWhiteSpace(docCode))
+ .ToArray();
+ }
- protected static string[] SplitMarkupCodeIntoFiles(string markupCode)
+ static (string[] code, List<(string file, TextSpan span)>) Parse(string markupCode)
+ {
+ if (markupCode == null)
{
- return DocumentSplittingRegex.Split(markupCode)
- .Where(docCode => !string.IsNullOrWhiteSpace(docCode))
- .ToArray();
+ return ([], []);
}
- static (string[] code, List<(string file, TextSpan span)>) Parse(string markupCode)
- {
- if (markupCode == null)
- {
- return (Array.Empty(), new List<(string, TextSpan)>());
- }
+ var documents = SplitMarkupCodeIntoFiles(markupCode);
- var documents = SplitMarkupCodeIntoFiles(markupCode);
+ var markupSpans = new List<(string, TextSpan)>();
- var markupSpans = new List<(string, TextSpan)>();
+ for (var i = 0; i < documents.Length; i++)
+ {
+ var code = new StringBuilder();
+ var name = $"TestDocument{i}";
- for (var i = 0; i < documents.Length; i++)
- {
- var code = new StringBuilder();
- var name = $"TestDocument{i}";
+ var remainingCode = documents[i];
+ var remainingCodeStart = 0;
- var remainingCode = documents[i];
- var remainingCodeStart = 0;
+ while (remainingCode.Length > 0)
+ {
+ var beforeAndAfterOpening = remainingCode.Split(["[|"], 2, StringSplitOptions.None);
- while (remainingCode.Length > 0)
+ if (beforeAndAfterOpening.Length == 1)
{
- var beforeAndAfterOpening = remainingCode.Split(new[] { "[|" }, 2, StringSplitOptions.None);
-
- if (beforeAndAfterOpening.Length == 1)
- {
- _ = code.Append(beforeAndAfterOpening[0]);
- break;
- }
-
- var midAndAfterClosing = beforeAndAfterOpening[1].Split(new[] { "|]" }, 2, StringSplitOptions.None);
+ _ = code.Append(beforeAndAfterOpening[0]);
+ break;
+ }
- if (midAndAfterClosing.Length == 1)
- {
- throw new Exception("The markup code does not contain a closing '|]'");
- }
+ var midAndAfterClosing = beforeAndAfterOpening[1].Split(["|]"], 2, StringSplitOptions.None);
- var markupSpan = new TextSpan(remainingCodeStart + beforeAndAfterOpening[0].Length, midAndAfterClosing[0].Length);
+ if (midAndAfterClosing.Length == 1)
+ {
+ throw new Exception("The markup code does not contain a closing '|]'");
+ }
- _ = code.Append(beforeAndAfterOpening[0]).Append(midAndAfterClosing[0]);
- markupSpans.Add((name, markupSpan));
+ var markupSpan = new TextSpan(remainingCodeStart + beforeAndAfterOpening[0].Length, midAndAfterClosing[0].Length);
- remainingCode = midAndAfterClosing[1];
- remainingCodeStart += beforeAndAfterOpening[0].Length + markupSpan.Length;
- }
+ _ = code.Append(beforeAndAfterOpening[0]).Append(midAndAfterClosing[0]);
+ markupSpans.Add((name, markupSpan));
- documents[i] = code.ToString();
+ remainingCode = midAndAfterClosing[1];
+ remainingCodeStart += beforeAndAfterOpening[0].Length + markupSpan.Length;
}
- return (documents, markupSpans);
+ documents[i] = code.ToString();
}
- protected static readonly bool VerboseLogging = Environment.GetEnvironmentVariable("CI") != "true"
- || Environment.GetEnvironmentVariable("VERBOSE_TEST_LOGGING")?.ToLower() == "true";
+ return (documents, markupSpans);
}
-}
+
+ protected static readonly bool VerboseLogging = Environment.GetEnvironmentVariable("CI") != "true"
+ || Environment.GetEnvironmentVariable("VERBOSE_TEST_LOGGING")?.ToLower() == "true";
+}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTests.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTests.cs
index 3e1938d5..df32e28f 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTests.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTests.cs
@@ -1,23 +1,23 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
-{
- using System.Threading.Tasks;
- using NUnit.Framework;
- using static AzureFunctionsDiagnostics;
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System.Threading.Tasks;
+using NUnit.Framework;
+using static AzureFunctionsDiagnostics;
- [TestFixture]
- public class ConfigurationAnalyzerTests : AnalyzerTestFixture
+[TestFixture]
+public class ConfigurationAnalyzerTests : AnalyzerTestFixture
+{
+ [TestCase("DefineCriticalErrorAction((errorContext, cancellationToken) => Task.CompletedTask)", DefineCriticalErrorActionNotAllowedId)]
+ [TestCase("LimitMessageProcessingConcurrencyTo(5)", LimitMessageProcessingToNotAllowedId)]
+ [TestCase("MakeInstanceUniquelyAddressable(null)", MakeInstanceUniquelyAddressableNotAllowedId)]
+ [TestCase("OverrideLocalAddress(null)", OverrideLocalAddressNotAllowedId)]
+ [TestCase("PurgeOnStartup(true)", PurgeOnStartupNotAllowedId)]
+ [TestCase("SetDiagnosticsPath(null)", SetDiagnosticsPathNotAllowedId)]
+ [TestCase("UseTransport(new AzureServiceBusTransport(null, default(TopicTopology)))", UseTransportNotAllowedId)]
+ public Task DiagnosticIsReportedForEndpointConfiguration(string configuration, string diagnosticId)
{
- [TestCase("DefineCriticalErrorAction((errorContext, cancellationToken) => Task.CompletedTask)", DefineCriticalErrorActionNotAllowedId)]
- [TestCase("LimitMessageProcessingConcurrencyTo(5)", LimitMessageProcessingToNotAllowedId)]
- [TestCase("MakeInstanceUniquelyAddressable(null)", MakeInstanceUniquelyAddressableNotAllowedId)]
- [TestCase("OverrideLocalAddress(null)", OverrideLocalAddressNotAllowedId)]
- [TestCase("PurgeOnStartup(true)", PurgeOnStartupNotAllowedId)]
- [TestCase("SetDiagnosticsPath(null)", SetDiagnosticsPathNotAllowedId)]
- [TestCase("UseTransport(new AzureServiceBusTransport(null, default(TopicTopology)))", UseTransportNotAllowedId)]
- public Task DiagnosticIsReportedForEndpointConfiguration(string configuration, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
class Foo
@@ -31,20 +31,20 @@ void Bar(ServiceBusTriggeredEndpointConfiguration endpointConfig)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
+ }
- [TestCase("DefineCriticalErrorAction((errorContext, cancellationToken) => Task.CompletedTask)", DefineCriticalErrorActionNotAllowedId)]
- [TestCase("LimitMessageProcessingConcurrencyTo(5)", LimitMessageProcessingToNotAllowedId)]
- [TestCase("MakeInstanceUniquelyAddressable(null)", MakeInstanceUniquelyAddressableNotAllowedId)]
- [TestCase("OverrideLocalAddress(null)", OverrideLocalAddressNotAllowedId)]
- [TestCase("PurgeOnStartup(true)", PurgeOnStartupNotAllowedId)]
- [TestCase("SetDiagnosticsPath(null)", SetDiagnosticsPathNotAllowedId)]
- [TestCase("UseTransport(new AzureServiceBusTransport(null, default(TopicTopology)))", UseTransportNotAllowedId)]
- public Task DiagnosticIsNotReportedForOtherEndpointConfiguration(string configuration, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ [TestCase("DefineCriticalErrorAction((errorContext, cancellationToken) => Task.CompletedTask)", DefineCriticalErrorActionNotAllowedId)]
+ [TestCase("LimitMessageProcessingConcurrencyTo(5)", LimitMessageProcessingToNotAllowedId)]
+ [TestCase("MakeInstanceUniquelyAddressable(null)", MakeInstanceUniquelyAddressableNotAllowedId)]
+ [TestCase("OverrideLocalAddress(null)", OverrideLocalAddressNotAllowedId)]
+ [TestCase("PurgeOnStartup(true)", PurgeOnStartupNotAllowedId)]
+ [TestCase("SetDiagnosticsPath(null)", SetDiagnosticsPathNotAllowedId)]
+ [TestCase("UseTransport(new AzureServiceBusTransport(null, default(TopicTopology)))", UseTransportNotAllowedId)]
+ public Task DiagnosticIsNotReportedForOtherEndpointConfiguration(string configuration, string diagnosticId)
+ {
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading;
using System.Threading.Tasks;
@@ -68,7 +68,6 @@ void Bar(SomeOtherClass endpointConfig)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTestsCSharp8.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTestsCSharp8.cs
index 9f50a20d..f621d928 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTestsCSharp8.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/ConfigurationAnalyzerTestsCSharp8.cs
@@ -1,19 +1,19 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
-{
- using System.Threading.Tasks;
- using Microsoft.CodeAnalysis.CSharp;
- using NUnit.Framework;
- using static AzureFunctionsDiagnostics;
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CSharp;
+using NUnit.Framework;
+using static AzureFunctionsDiagnostics;
- [TestFixture]
- public class ConfigurationAnalyzerTestsCSharp8 : AnalyzerTestFixture
+[TestFixture]
+public class ConfigurationAnalyzerTestsCSharp8 : AnalyzerTestFixture
+{
+ // HINT: In C# 7 this call is ambiguous with the LearningTransport version as the compiler cannot differentiate method calls via generic type constraints
+ [TestCase("UseTransport(null)", UseTransportNotAllowedId)]
+ public Task DiagnosticIsReportedForEndpointConfiguration(string configuration, string diagnosticId)
{
- // HINT: In C# 7 this call is ambiguous with the LearningTransport version as the compiler cannot differentiate method calls via generic type constraints
- [TestCase("UseTransport(null)", UseTransportNotAllowedId)]
- public Task DiagnosticIsReportedForEndpointConfiguration(string configuration, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
class Foo
@@ -27,8 +27,7 @@ void Bar(ServiceBusTriggeredEndpointConfiguration endpointConfig)
}}
}}";
- return Assert(diagnosticId, source);
- }
- protected override LanguageVersion AnalyzerLanguageVersion => LanguageVersion.CSharp8;
+ return Assert(diagnosticId, source);
}
+ protected override LanguageVersion AnalyzerLanguageVersion => LanguageVersion.CSharp8;
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/CompilationExtensions.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/CompilationExtensions.cs
index 2eadb657..b859cab8 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/CompilationExtensions.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/CompilationExtensions.cs
@@ -1,60 +1,59 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+static class CompilationExtensions
{
- using System;
- using System.Collections.Generic;
- using System.Collections.Immutable;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.Diagnostics;
-
- static class CompilationExtensions
+ public static void Compile(this Compilation compilation, bool throwOnFailure = true)
{
- public static void Compile(this Compilation compilation, bool throwOnFailure = true)
+ using (var peStream = new MemoryStream())
{
- using (var peStream = new MemoryStream())
- {
- var emitResult = compilation.Emit(peStream);
+ var emitResult = compilation.Emit(peStream);
- if (!emitResult.Success)
+ if (!emitResult.Success)
+ {
+ if (throwOnFailure)
{
- if (throwOnFailure)
- {
- throw new Exception("Compilation failed.");
- }
- else
- {
- Debug.WriteLine("Compilation failed.");
- }
+ throw new Exception("Compilation failed.");
+ }
+ else
+ {
+ Debug.WriteLine("Compilation failed.");
}
}
}
+ }
- public static async Task> GetAnalyzerDiagnostics(this Compilation compilation, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken = default)
- {
- var exceptions = new List();
-
- var analysisOptions = new CompilationWithAnalyzersOptions(
- new AnalyzerOptions(ImmutableArray.Empty),
- (exception, _, __) => exceptions.Add(exception),
- concurrentAnalysis: false,
- logAnalyzerExecutionTime: false);
+ public static async Task> GetAnalyzerDiagnostics(this Compilation compilation, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken = default)
+ {
+ var exceptions = new List();
- var diagnostics = await compilation
- .WithAnalyzers([analyzer], analysisOptions)
- .GetAnalyzerDiagnosticsAsync(cancellationToken);
+ var analysisOptions = new CompilationWithAnalyzersOptions(
+ new AnalyzerOptions(ImmutableArray.Empty),
+ (exception, _, __) => exceptions.Add(exception),
+ concurrentAnalysis: false,
+ logAnalyzerExecutionTime: false);
- if (exceptions.Any())
- {
- throw new AggregateException(exceptions);
- }
+ var diagnostics = await compilation
+ .WithAnalyzers([analyzer], analysisOptions)
+ .GetAnalyzerDiagnosticsAsync(cancellationToken);
- return diagnostics
- .OrderBy(diagnostic => diagnostic.Location.SourceSpan)
- .ThenBy(diagnostic => diagnostic.Id);
+ if (exceptions.Any())
+ {
+ throw new AggregateException(exceptions);
}
+
+ return diagnostics
+ .OrderBy(diagnostic => diagnostic.Location.SourceSpan)
+ .ThenBy(diagnostic => diagnostic.Id);
}
-}
+}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/DocumentExtensions.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/DocumentExtensions.cs
index deeeae96..1fdfe873 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/DocumentExtensions.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/Extensions/DocumentExtensions.cs
@@ -1,48 +1,47 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Formatting;
+using Microsoft.CodeAnalysis.Simplification;
+
+static class DocumentExtensions
{
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CodeActions;
- using Microsoft.CodeAnalysis.CodeFixes;
- using Microsoft.CodeAnalysis.Formatting;
- using Microsoft.CodeAnalysis.Simplification;
+ public static async Task> GetCompilerDiagnostics(this Document document, CancellationToken cancellationToken = default) =>
+ (await document.GetSemanticModelAsync(cancellationToken))
+ .GetDiagnostics(cancellationToken: cancellationToken)
+ .Where(diagnostic => diagnostic.Severity != DiagnosticSeverity.Hidden)
+ .OrderBy(diagnostic => diagnostic.Location.SourceSpan)
+ .ThenBy(diagnostic => diagnostic.Id);
- static class DocumentExtensions
+ public static async Task<(Document Document, CodeAction Action)[]> GetCodeActions(this Project project, CodeFixProvider codeFix, Diagnostic diagnostic, CancellationToken cancellationToken = default)
{
- public static async Task> GetCompilerDiagnostics(this Document document, CancellationToken cancellationToken = default) =>
- (await document.GetSemanticModelAsync(cancellationToken))
- .GetDiagnostics(cancellationToken: cancellationToken)
- .Where(diagnostic => diagnostic.Severity != DiagnosticSeverity.Hidden)
- .OrderBy(diagnostic => diagnostic.Location.SourceSpan)
- .ThenBy(diagnostic => diagnostic.Id);
-
- public static async Task<(Document Document, CodeAction Action)[]> GetCodeActions(this Project project, CodeFixProvider codeFix, Diagnostic diagnostic, CancellationToken cancellationToken = default)
+ var actions = new List<(Document, CodeAction)>();
+ foreach (var document in project.Documents)
{
- var actions = new List<(Document, CodeAction)>();
- foreach (var document in project.Documents)
- {
- var context = new CodeFixContext(document, diagnostic, (action, _) => actions.Add((document, action)), cancellationToken);
- await codeFix.RegisterCodeFixesAsync(context);
- }
- return actions.ToArray();
+ var context = new CodeFixContext(document, diagnostic, (action, _) => actions.Add((document, action)), cancellationToken);
+ await codeFix.RegisterCodeFixesAsync(context);
}
+ return actions.ToArray();
+ }
- public static async Task ApplyChanges(this Document document, CodeAction codeAction, CancellationToken cancellationToken = default)
- {
- var operations = await codeAction.GetOperationsAsync(cancellationToken);
- var solution = operations.OfType().Single().ChangedSolution;
- return solution.GetDocument(document.Id);
- }
+ public static async Task ApplyChanges(this Document document, CodeAction codeAction, CancellationToken cancellationToken = default)
+ {
+ var operations = await codeAction.GetOperationsAsync(cancellationToken);
+ var solution = operations.OfType().Single().ChangedSolution;
+ return solution.GetDocument(document.Id);
+ }
- public static async Task GetCode(this Document document, CancellationToken cancellationToken = default)
- {
- var simplifiedDoc = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken);
- var root = await simplifiedDoc.GetSyntaxRootAsync(cancellationToken);
- root = Formatter.Format(root, Formatter.Annotation, simplifiedDoc.Project.Solution.Workspace, cancellationToken: cancellationToken);
- return root.GetText().ToString();
- }
+ public static async Task GetCode(this Document document, CancellationToken cancellationToken = default)
+ {
+ var simplifiedDoc = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken);
+ var root = await simplifiedDoc.GetSyntaxRootAsync(cancellationToken);
+ root = Formatter.Format(root, Formatter.Annotation, simplifiedDoc.Project.Solution.Workspace, cancellationToken: cancellationToken);
+ return root.GetText().ToString();
}
-}
+}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/OptionsAnalyzerTests.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/OptionsAnalyzerTests.cs
index 3bc1d76c..ca31652c 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/OptionsAnalyzerTests.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/OptionsAnalyzerTests.cs
@@ -1,19 +1,19 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
-{
- using System.Threading.Tasks;
- using NUnit.Framework;
- using static AzureFunctionsDiagnostics;
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System.Threading.Tasks;
+using NUnit.Framework;
+using static AzureFunctionsDiagnostics;
- [TestFixture]
- public class OptionsAnalyzerTests : AnalyzerTestFixture
+[TestFixture]
+public class OptionsAnalyzerTests : AnalyzerTestFixture
+{
+ [TestCase("SendOptions", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
+ [TestCase("SendOptions", "RouteToThisInstance", RouteToThisInstanceNotAllowedId)]
+ [TestCase("ReplyOptions", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
+ public Task DiagnosticIsReportedForOptions(string optionsType, string method, string diagnosticId)
{
- [TestCase("SendOptions", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
- [TestCase("SendOptions", "RouteToThisInstance", RouteToThisInstanceNotAllowedId)]
- [TestCase("ReplyOptions", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
- public Task DiagnosticIsReportedForOptions(string optionsType, string method, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ var source =
+ $@"using NServiceBus;
class Foo
{{
void Bar({optionsType} options)
@@ -22,15 +22,15 @@ void Bar({optionsType} options)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
+ }
- [TestCase("SomeOtherClass", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
- [TestCase("SomeOtherClass", "RouteToThisInstance", RouteToThisInstanceNotAllowedId)]
- public Task DiagnosticIsNotReportedForOtherOptions(string optionsType, string method, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ [TestCase("SomeOtherClass", "RouteReplyToThisInstance", RouteReplyToThisInstanceNotAllowedId)]
+ [TestCase("SomeOtherClass", "RouteToThisInstance", RouteToThisInstanceNotAllowedId)]
+ public Task DiagnosticIsNotReportedForOtherOptions(string optionsType, string method, string diagnosticId)
+ {
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
@@ -49,7 +49,6 @@ void Bar({optionsType} options)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/SourceGeneratorApprovals.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/SourceGeneratorApprovals.cs
index f713e7fb..7ddd0255 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/SourceGeneratorApprovals.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/SourceGeneratorApprovals.cs
@@ -1,25 +1,25 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.WebJobs;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.Extensions.Logging;
+using NUnit.Framework;
+using Particular.Approvals;
+
+[TestFixture]
+public class SourceGeneratorApprovals
{
- using System;
- using System.Collections.Generic;
- using System.Collections.Immutable;
- using System.Linq;
- using Azure.Messaging.ServiceBus;
- using Microsoft.Azure.WebJobs;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CSharp;
- using Microsoft.Extensions.Logging;
- using NUnit.Framework;
- using Particular.Approvals;
-
- [TestFixture]
- public class SourceGeneratorApprovals
- {
- [Test]
- public void UsingNamespace()
- {
- var source =
-@"using NServiceBus;
+ [Test]
+ public void UsingNamespace()
+ {
+ var source =
+ @"using NServiceBus;
[assembly: NServiceBusTriggerFunction(Foo.Startup.EndpointName)]
@@ -30,16 +30,16 @@ public class Startup
public const string EndpointName = ""endpoint"";
}
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void UsingFullyQualifiedAttributeName()
- {
- var source =
-@"[assembly: NServiceBus.NServiceBusTriggerFunction(Foo.Startup.EndpointName)]
+ [Test]
+ public void UsingFullyQualifiedAttributeName()
+ {
+ var source =
+ @"[assembly: NServiceBus.NServiceBusTriggerFunction(Foo.Startup.EndpointName)]
namespace Foo
{
@@ -48,88 +48,88 @@ public class Startup
public const string EndpointName = ""endpoint"";
}
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void NameIsStringValue()
- {
- var source = @"[assembly: NServiceBus.NServiceBusTriggerFunction(""endpoint"")]";
- var (output, _) = GetGeneratedOutput(source);
+ [Test]
+ public void NameIsStringValue()
+ {
+ var source = @"[assembly: NServiceBus.NServiceBusTriggerFunction(""endpoint"")]";
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void No_attribute_should_not_generate_trigger_function()
- {
- var source = @"";
- var (output, _) = GetGeneratedOutput(source);
+ [Test]
+ public void No_attribute_should_not_generate_trigger_function()
+ {
+ var source = @"";
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void No_attribute_should_not_generate_compilation_error()
- {
- var source = @"using NServiceBus;";
- var (_, diagnostics) = GetGeneratedOutput(source);
+ [Test]
+ public void No_attribute_should_not_generate_compilation_error()
+ {
+ var source = @"using NServiceBus;";
+ var (_, diagnostics) = GetGeneratedOutput(source);
- Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), Is.False);
- }
+ Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), Is.False);
+ }
- [Test]
- public void Can_override_trigger_function_name()
- {
- var source =
- @"using NServiceBus;
+ [Test]
+ public void Can_override_trigger_function_name()
+ {
+ var source =
+ @"using NServiceBus;
[assembly: NServiceBusTriggerFunction(""endpoint"", TriggerFunctionName = ""trigger"")]
public class Startup
{
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [TestCase(null)]
- [TestCase("")]
- [TestCase(" ")]
- public void Invalid_name_should_cause_an_error(string endpointName)
- {
- var source = @"
+ [TestCase(null)]
+ [TestCase("")]
+ [TestCase(" ")]
+ public void Invalid_name_should_cause_an_error(string endpointName)
+ {
+ var source = @"
using NServiceBus;
[assembly: NServiceBusTriggerFunction(""" + endpointName + @""")]
";
- var (_, diagnostics) = GetGeneratedOutput(source, suppressGeneratedDiagnosticsErrors: true);
+ var (_, diagnostics) = GetGeneratedOutput(source, suppressGeneratedDiagnosticsErrors: true);
- Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error && d.Id == AzureFunctionsDiagnostics.InvalidEndpointNameErrorId), Is.True);
- }
+ Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error && d.Id == AzureFunctionsDiagnostics.InvalidEndpointNameErrorId), Is.True);
+ }
- [TestCase(null)]
- [TestCase("")]
- [TestCase(" ")]
- public void Invalid_trigger_function_name_should_cause_an_error(string triggerFunctionName)
- {
- var source = @"
+ [TestCase(null)]
+ [TestCase("")]
+ [TestCase(" ")]
+ public void Invalid_trigger_function_name_should_cause_an_error(string triggerFunctionName)
+ {
+ var source = @"
using NServiceBus;
[assembly: NServiceBusTriggerFunction(""endpoint"", TriggerFunctionName = """ + triggerFunctionName + @""")]
";
- var (_, diagnostics) = GetGeneratedOutput(source, suppressGeneratedDiagnosticsErrors: true);
+ var (_, diagnostics) = GetGeneratedOutput(source, suppressGeneratedDiagnosticsErrors: true);
- Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error && d.Id == AzureFunctionsDiagnostics.InvalidTriggerFunctionNameErrorId), Is.True);
- }
+ Assert.That(diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error && d.Id == AzureFunctionsDiagnostics.InvalidTriggerFunctionNameErrorId), Is.True);
+ }
- [Test]
- public void Can_enable_transactions()
- {
- var source = @"
+ [Test]
+ public void Can_enable_transactions()
+ {
+ var source = @"
using NServiceBus;
[assembly: NServiceBusTriggerFunction(""endpoint"", SendsAtomicWithReceive = true)]
@@ -137,15 +137,15 @@ public void Can_enable_transactions()
public class Startup
{
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void Use_two_optionals()
- {
- var source = @"
+ [Test]
+ public void Use_two_optionals()
+ {
+ var source = @"
using NServiceBus;
[assembly: NServiceBusTriggerFunction(""endpoint"", TriggerFunctionName = ""trigger"", SendsAtomicWithReceive = true)]
@@ -153,15 +153,15 @@ public void Use_two_optionals()
public class Startup
{
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [Test]
- public void Two_optionals_out_of_order()
- {
- var source = @"
+ [Test]
+ public void Two_optionals_out_of_order()
+ {
+ var source = @"
using NServiceBus;
[assembly: NServiceBusTriggerFunction(""endpoint"", SendsAtomicWithReceive = true, TriggerFunctionName = ""trigger"")]
@@ -169,70 +169,68 @@ public void Two_optionals_out_of_order()
public class Startup
{
}";
- var (output, _) = GetGeneratedOutput(source);
+ var (output, _) = GetGeneratedOutput(source);
- Approver.Verify(output);
- }
+ Approver.Verify(output);
+ }
- [OneTimeSetUp]
- public void Init()
- {
- // For the unit tests to work, the compilation used by the source generator needs to know that NServiceBusTriggerFunction
- // is an attribute from NServiceBus namespace and its full name is NServiceBus.NServiceBusTriggerFunctionAttribute.
- // By referencing NServiceBusTriggerFunctionAttribute here, NServiceBus.AzureFunctions.InProcess.ServiceBus is forced to load and participate in the compilation.
- _ = new NServiceBusTriggerFunctionAttribute(endpointName: "test");
- }
+ [OneTimeSetUp]
+ public void Init()
+ {
+ // For the unit tests to work, the compilation used by the source generator needs to know that NServiceBusTriggerFunction
+ // is an attribute from NServiceBus namespace and its full name is NServiceBus.NServiceBusTriggerFunctionAttribute.
+ // By referencing NServiceBusTriggerFunctionAttribute here, NServiceBus.AzureFunctions.InProcess.ServiceBus is forced to load and participate in the compilation.
+ _ = new NServiceBusTriggerFunctionAttribute(endpointName: "test");
+ }
- static (string output, ImmutableArray diagnostics) GetGeneratedOutput(string source, bool suppressGeneratedDiagnosticsErrors = false)
- {
- var syntaxTree = CSharpSyntaxTree.ParseText(source);
- var references = new List();
- var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+ static (string output, ImmutableArray diagnostics) GetGeneratedOutput(string source, bool suppressGeneratedDiagnosticsErrors = false)
+ {
+ var syntaxTree = CSharpSyntaxTree.ParseText(source);
+ var references = new List();
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies();
- foreach (var assembly in assemblies)
+ foreach (var assembly in assemblies)
+ {
+ if (!assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location))
{
- if (!assembly.IsDynamic && !string.IsNullOrWhiteSpace(assembly.Location))
- {
- references.Add(MetadataReference.CreateFromFile(assembly.Location));
- }
+ references.Add(MetadataReference.CreateFromFile(assembly.Location));
}
+ }
- var compilation = Compile(new[]
- {
- syntaxTree
- }, references);
+ var compilation = Compile([
+ syntaxTree
+ ], references);
- var generator = new TriggerFunctionGenerator();
+ var generator = new TriggerFunctionGenerator();
- var driver = CSharpGeneratorDriver.Create(generator);
- driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics);
+ var driver = CSharpGeneratorDriver.Create(generator);
+ driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var generateDiagnostics);
- // add necessary references for the generated trigger
- references.Add(MetadataReference.CreateFromFile(typeof(ServiceBusTriggerAttribute).Assembly.Location));
- references.Add(MetadataReference.CreateFromFile(typeof(ExecutionContext).Assembly.Location));
- references.Add(MetadataReference.CreateFromFile(typeof(ServiceBusReceivedMessage).Assembly.Location));
- references.Add(MetadataReference.CreateFromFile(typeof(ILogger).Assembly.Location));
- Compile(outputCompilation.SyntaxTrees, references);
+ // add necessary references for the generated trigger
+ references.Add(MetadataReference.CreateFromFile(typeof(ServiceBusTriggerAttribute).Assembly.Location));
+ references.Add(MetadataReference.CreateFromFile(typeof(ExecutionContext).Assembly.Location));
+ references.Add(MetadataReference.CreateFromFile(typeof(ServiceBusReceivedMessage).Assembly.Location));
+ references.Add(MetadataReference.CreateFromFile(typeof(ILogger).Assembly.Location));
+ Compile(outputCompilation.SyntaxTrees, references);
- if (!suppressGeneratedDiagnosticsErrors)
- {
- Assert.That(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), Is.False, "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage());
- }
-
- return (outputCompilation.SyntaxTrees.Last().ToString(), generateDiagnostics);
+ if (!suppressGeneratedDiagnosticsErrors)
+ {
+ Assert.That(generateDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error), Is.False, "Failed: " + generateDiagnostics.FirstOrDefault()?.GetMessage());
}
- static CSharpCompilation Compile(IEnumerable syntaxTrees, IEnumerable references)
- {
- var compilation = CSharpCompilation.Create("result", syntaxTrees, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+ return (outputCompilation.SyntaxTrees.Last().ToString(), generateDiagnostics);
+ }
- // Verify the code compiled:
- var compilationErrors = compilation
- .GetDiagnostics()
- .Where(d => d.Severity >= DiagnosticSeverity.Warning);
- Assert.That(compilationErrors, Is.Empty, compilationErrors.FirstOrDefault()?.GetMessage());
+ static CSharpCompilation Compile(IEnumerable syntaxTrees, IEnumerable references)
+ {
+ var compilation = CSharpCompilation.Create("result", syntaxTrees, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
- return compilation;
- }
+ // Verify the code compiled:
+ var compilationErrors = compilation
+ .GetDiagnostics()
+ .Where(d => d.Severity >= DiagnosticSeverity.Warning);
+ Assert.That(compilationErrors, Is.Empty, compilationErrors.FirstOrDefault()?.GetMessage());
+
+ return compilation;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/TransportConfigurationAnalyzerTests.cs b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/TransportConfigurationAnalyzerTests.cs
index 23697da5..de571137 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/TransportConfigurationAnalyzerTests.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.Analyzer.Tests/TransportConfigurationAnalyzerTests.cs
@@ -1,23 +1,23 @@
-namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests
-{
- using System.Threading.Tasks;
- using NUnit.Framework;
- using static AzureFunctionsDiagnostics;
+namespace NServiceBus.AzureFunctions.InProcess.Analyzer.Tests;
+
+using System.Threading.Tasks;
+using NUnit.Framework;
+using static AzureFunctionsDiagnostics;
- [TestFixture]
- public class TransportConfigurationAnalyzerTests : AnalyzerTestFixture
+[TestFixture]
+public class TransportConfigurationAnalyzerTests : AnalyzerTestFixture
+{
+ [TestCase("TransportTransactionMode", "TransportTransactionMode.None", TransportTransactionModeNotAllowedId)]
+ [TestCase("EnablePartitioning", "true", EnablePartitioningNotAllowedId)]
+ [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
+ [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
+ [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
+ [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
+ [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
+ public Task DiagnosticIsReportedTransportConfigurationDirect(string configName, string configValue, string diagnosticId)
{
- [TestCase("TransportTransactionMode", "TransportTransactionMode.None", TransportTransactionModeNotAllowedId)]
- [TestCase("EnablePartitioning", "true", EnablePartitioningNotAllowedId)]
- [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
- [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
- [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
- [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
- [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
- public Task DiagnosticIsReportedTransportConfigurationDirect(string configName, string configValue, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
class Foo
@@ -31,20 +31,20 @@ void Direct(ServiceBusTriggeredEndpointConfiguration endpointConfig)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
+ }
- [TestCase("Transactions", "TransportTransactionMode.None", TransportTransactionModeNotAllowedId)]
- [TestCase("EnablePartitioning", "", EnablePartitioningNotAllowedId)]
- [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
- [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
- [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
- [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
- [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
- public Task DiagnosticIsReportedTransportConfigurationExtension(string configName, string configValue, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ [TestCase("Transactions", "TransportTransactionMode.None", TransportTransactionModeNotAllowedId)]
+ [TestCase("EnablePartitioning", "", EnablePartitioningNotAllowedId)]
+ [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
+ [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
+ [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
+ [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
+ [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
+ public Task DiagnosticIsReportedTransportConfigurationExtension(string configName, string configValue, string diagnosticId)
+ {
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
class Foo
@@ -55,19 +55,19 @@ void Extension(TransportExtensions transportExtension)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
+ }
- [TestCase("EnablePartitioning", "true", EnablePartitioningNotAllowedId)]
- [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
- [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
- [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
- [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
- [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
- public Task DiagnosticIsNotReportedForNonTransportConfiguration(string configName, string configValue, string diagnosticId)
- {
- var source =
- $@"using NServiceBus;
+ [TestCase("EnablePartitioning", "true", EnablePartitioningNotAllowedId)]
+ [TestCase("EntityMaximumSize", "5", EntityMaximumSizeNotAllowedId)]
+ [TestCase("MaxAutoLockRenewalDuration", "new System.TimeSpan(0, 0, 5, 0)", MaxAutoLockRenewalDurationNotAllowedId)]
+ [TestCase("PrefetchCount", "5", PrefetchCountNotAllowedId)]
+ [TestCase("PrefetchMultiplier", "5", PrefetchMultiplierNotAllowedId)]
+ [TestCase("TimeToWaitBeforeTriggeringCircuitBreaker", "new System.TimeSpan(0, 0, 5, 0)", TimeToWaitBeforeTriggeringCircuitBreakerNotAllowedId)]
+ public Task DiagnosticIsNotReportedForNonTransportConfiguration(string configName, string configValue, string diagnosticId)
+ {
+ var source =
+ $@"using NServiceBus;
using System;
using System.Threading.Tasks;
@@ -89,7 +89,6 @@ void Direct(SomeOtherClass endpointConfig)
}}
}}";
- return Assert(diagnosticId, source);
- }
+ return Assert(diagnosticId, source);
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionExecutionContext.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionExecutionContext.cs
index d74dea26..6b785c89 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionExecutionContext.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionExecutionContext.cs
@@ -1,30 +1,29 @@
-namespace NServiceBus
-{
- using Microsoft.Azure.WebJobs;
- using Microsoft.Extensions.Logging;
+namespace NServiceBus;
+
+using Microsoft.Azure.WebJobs;
+using Microsoft.Extensions.Logging;
+///
+/// Contains specific context information of the current function invocation.
+///
+public class FunctionExecutionContext
+{
///
- /// Contains specific context information of the current function invocation.
+ /// Creates a new .
///
- public class FunctionExecutionContext
+ public FunctionExecutionContext(ExecutionContext executionContext, ILogger logger)
{
- ///
- /// Creates a new .
- ///
- public FunctionExecutionContext(ExecutionContext executionContext, ILogger logger)
- {
- Logger = logger;
- ExecutionContext = executionContext;
- }
+ Logger = logger;
+ ExecutionContext = executionContext;
+ }
- ///
- /// The associated with the current function invocation.
- ///
- public ExecutionContext ExecutionContext { get; }
+ ///
+ /// The associated with the current function invocation.
+ ///
+ public ExecutionContext ExecutionContext { get; }
- ///
- /// The associated with the current function invocation.
- ///
- public ILogger Logger { get; }
- }
-}
+ ///
+ /// The associated with the current function invocation.
+ ///
+ public ILogger Logger { get; }
+}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionsHostBuilderExtensions.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionsHostBuilderExtensions.cs
index 52b33d4f..1e8dfbf0 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionsHostBuilderExtensions.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/FunctionsHostBuilderExtensions.cs
@@ -1,164 +1,163 @@
-namespace NServiceBus
+namespace NServiceBus;
+
+using System;
+using System.IO;
+using System.Reflection;
+using AzureFunctions.InProcess.ServiceBus;
+using Configuration.AdvancedExtensibility;
+using Microsoft.Azure.Functions.Extensions.DependencyInjection;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Transport.AzureServiceBus;
+
+///
+/// Provides extension methods to configure a using .
+///
+public static partial class FunctionsHostBuilderExtensions
{
- using System;
- using System.IO;
- using System.Reflection;
- using AzureFunctions.InProcess.ServiceBus;
- using Configuration.AdvancedExtensibility;
- using Microsoft.Azure.Functions.Extensions.DependencyInjection;
- using Microsoft.Extensions.Azure;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Options;
- using Transport.AzureServiceBus;
+ ///
+ /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
+ ///
+ public static void UseNServiceBus(
+ this IFunctionsHostBuilder functionsHostBuilder,
+ Action configurationFactory = null) =>
+ RegisterEndpointFactory(functionsHostBuilder, null, Assembly.GetCallingAssembly(), (c) => configurationFactory?.Invoke(c));
///
- /// Provides extension methods to configure a using .
+ /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
///
- public static partial class FunctionsHostBuilderExtensions
+ public static void UseNServiceBus(
+ this IFunctionsHostBuilder functionsHostBuilder,
+ string endpointName,
+ Action configurationFactory = null)
{
- ///
- /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
- ///
- public static void UseNServiceBus(
- this IFunctionsHostBuilder functionsHostBuilder,
- Action configurationFactory = null) =>
- RegisterEndpointFactory(functionsHostBuilder, null, Assembly.GetCallingAssembly(), (c) => configurationFactory?.Invoke(c));
-
- ///
- /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
- ///
- public static void UseNServiceBus(
- this IFunctionsHostBuilder functionsHostBuilder,
- string endpointName,
- Action configurationFactory = null)
+ if (string.IsNullOrWhiteSpace(endpointName))
{
- if (string.IsNullOrWhiteSpace(endpointName))
- {
- throw new ArgumentException($"{nameof(endpointName)} must have a value");
- }
- RegisterEndpointFactory(functionsHostBuilder, endpointName, null, configurationFactory);
+ throw new ArgumentException($"{nameof(endpointName)} must have a value");
}
+ RegisterEndpointFactory(functionsHostBuilder, endpointName, null, configurationFactory);
+ }
- ///
- /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
- ///
- public static void UseNServiceBus(
- this IFunctionsHostBuilder functionsHostBuilder,
- string endpointName,
- string connectionString,
- Action configurationFactory = null)
+ ///
+ /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
+ ///
+ public static void UseNServiceBus(
+ this IFunctionsHostBuilder functionsHostBuilder,
+ string endpointName,
+ string connectionString,
+ Action configurationFactory = null)
+ {
+ if (string.IsNullOrWhiteSpace(endpointName))
{
- if (string.IsNullOrWhiteSpace(endpointName))
- {
- throw new ArgumentException($"{nameof(endpointName)} must have a value");
- }
- RegisterEndpointFactory(functionsHostBuilder, endpointName, null, configurationFactory, connectionString);
+ throw new ArgumentException($"{nameof(endpointName)} must have a value");
}
+ RegisterEndpointFactory(functionsHostBuilder, endpointName, null, configurationFactory, connectionString);
+ }
- ///
- /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
- ///
- public static void UseNServiceBus(
- this IFunctionsHostBuilder functionsHostBuilder,
- Func configurationFactory)
- {
- var functionsHostBuilderContext = functionsHostBuilder.GetContextInternal();
- var configuration = functionsHostBuilderContext.Configuration;
- var serviceBusTriggeredEndpointConfiguration = configurationFactory(configuration);
+ ///
+ /// Configures an NServiceBus endpoint that can be injected into a function trigger as a via dependency injection.
+ ///
+ public static void UseNServiceBus(
+ this IFunctionsHostBuilder functionsHostBuilder,
+ Func configurationFactory)
+ {
+ var functionsHostBuilderContext = functionsHostBuilder.GetContextInternal();
+ var configuration = functionsHostBuilderContext.Configuration;
+ var serviceBusTriggeredEndpointConfiguration = configurationFactory(configuration);
- ConfigureEndpointFactory(functionsHostBuilder.Services, functionsHostBuilderContext, serviceBusTriggeredEndpointConfiguration);
- }
+ ConfigureEndpointFactory(functionsHostBuilder.Services, functionsHostBuilderContext, serviceBusTriggeredEndpointConfiguration);
+ }
+
+ static void RegisterEndpointFactory(IFunctionsHostBuilder functionsHostBuilder,
+ string endpointName,
+ Assembly callingAssembly,
+ Action configurationFactory,
+ string connectionString = null)
+ {
+ var functionsHostBuilderContext = functionsHostBuilder.GetContextInternal();
+ var configuration = functionsHostBuilderContext.Configuration;
+ var triggerAttribute = callingAssembly
+ ?.GetCustomAttribute();
+ var endpointNameValue = triggerAttribute?.EndpointName;
+ var connectionName = triggerAttribute?.Connection;
- static void RegisterEndpointFactory(IFunctionsHostBuilder functionsHostBuilder,
- string endpointName,
- Assembly callingAssembly,
- Action configurationFactory,
- string connectionString = null)
+ endpointName ??= configuration?.GetValue("ENDPOINT_NAME") ?? endpointNameValue;
+
+ if (string.IsNullOrWhiteSpace(endpointName))
{
- var functionsHostBuilderContext = functionsHostBuilder.GetContextInternal();
- var configuration = functionsHostBuilderContext.Configuration;
- var triggerAttribute = callingAssembly
- ?.GetCustomAttribute();
- var endpointNameValue = triggerAttribute?.EndpointName;
- var connectionName = triggerAttribute?.Connection;
-
- endpointName ??= configuration?.GetValue("ENDPOINT_NAME") ?? endpointNameValue;
-
- if (string.IsNullOrWhiteSpace(endpointName))
- {
- throw new Exception($@"Endpoint name cannot be determined automatically. Use one of the following options to specify endpoint name:
+ throw new Exception($@"Endpoint name cannot be determined automatically. Use one of the following options to specify endpoint name:
- Use `{nameof(NServiceBusTriggerFunctionAttribute)}(endpointName)` to generate a trigger
- Use `functionsHostBuilder.UseNServiceBus(endpointName, configuration)`
- Add a configuration or environment variable with the key ENDPOINT_NAME");
- }
+ }
- functionsHostBuilder.Services.AddAzureClientsCore();
+ functionsHostBuilder.Services.AddAzureClientsCore();
- var functionEndpointConfiguration = new ServiceBusTriggeredEndpointConfiguration(endpointName, configuration, connectionString, connectionName);
+ var functionEndpointConfiguration = new ServiceBusTriggeredEndpointConfiguration(endpointName, configuration, connectionString, connectionName);
- configurationFactory?.Invoke(functionEndpointConfiguration);
+ configurationFactory?.Invoke(functionEndpointConfiguration);
- ConfigureEndpointFactory(functionsHostBuilder.Services, functionsHostBuilderContext, functionEndpointConfiguration);
- }
+ ConfigureEndpointFactory(functionsHostBuilder.Services, functionsHostBuilderContext, functionEndpointConfiguration);
+ }
- static void ConfigureEndpointFactory(IServiceCollection services, FunctionsHostBuilderContext functionsHostBuilderContext,
- ServiceBusTriggeredEndpointConfiguration serviceBusTriggeredEndpointConfiguration)
- {
- var serverless = serviceBusTriggeredEndpointConfiguration.InitializeTransport();
- // When using functions, assemblies are moved to a 'bin' folder within FunctionsHostBuilderContext.ApplicationRootPath.
- var advancedConfiguration = serviceBusTriggeredEndpointConfiguration.AdvancedConfiguration;
- var assemblyDirectoryName = advancedConfiguration.GetSettings().GetOrDefault("NServiceBus.AzureFunctions.InProcess.ServiceBus.AssemblyDirectoryName") ?? "bin";
- var startableEndpoint = Configure(
- advancedConfiguration,
- services,
- Path.Combine(functionsHostBuilderContext.ApplicationRootPath, assemblyDirectoryName));
-
- _ = services.AddSingleton(serviceBusTriggeredEndpointConfiguration);
- _ = services.AddSingleton(startableEndpoint);
- _ = services.AddSingleton(serverless);
- _ = services.AddSingleton();
- _ = services.AddSingleton(sp => sp.GetRequiredService());
+ static void ConfigureEndpointFactory(IServiceCollection services, FunctionsHostBuilderContext functionsHostBuilderContext,
+ ServiceBusTriggeredEndpointConfiguration serviceBusTriggeredEndpointConfiguration)
+ {
+ var serverless = serviceBusTriggeredEndpointConfiguration.InitializeTransport();
+ // When using functions, assemblies are moved to a 'bin' folder within FunctionsHostBuilderContext.ApplicationRootPath.
+ var advancedConfiguration = serviceBusTriggeredEndpointConfiguration.AdvancedConfiguration;
+ var assemblyDirectoryName = advancedConfiguration.GetSettings().GetOrDefault("NServiceBus.AzureFunctions.InProcess.ServiceBus.AssemblyDirectoryName") ?? "bin";
+ var startableEndpoint = Configure(
+ advancedConfiguration,
+ services,
+ Path.Combine(functionsHostBuilderContext.ApplicationRootPath, assemblyDirectoryName));
+
+ _ = services.AddSingleton(serviceBusTriggeredEndpointConfiguration);
+ _ = services.AddSingleton(startableEndpoint);
+ _ = services.AddSingleton(serverless);
+ _ = services.AddSingleton();
+ _ = services.AddSingleton(sp => sp.GetRequiredService());
#pragma warning disable CS0618 // Type or member is obsolete
- // Validator is registered here in case the user wants to use the options directly. This makes sure that the options are validated.
- // The transport still has to validate the options because options validators are only executed when the options are resolved.
- _ = services.AddSingleton, MigrationTopologyOptionsValidator>();
- _ = services.AddOptions()
+ // Validator is registered here in case the user wants to use the options directly. This makes sure that the options are validated.
+ // The transport still has to validate the options because options validators are only executed when the options are resolved.
+ _ = services.AddSingleton, MigrationTopologyOptionsValidator>();
+ _ = services.AddOptions()
#pragma warning restore CS0618 // Type or member is obsolete
- .BindConfiguration("AzureServiceBus:MigrationTopologyOptions");
+ .BindConfiguration("AzureServiceBus:MigrationTopologyOptions");
- // Validator is registered here in case the user wants to use the options directly. This makes sure that the options are validated.
- // The transport still has to validate the options because options validators are only executed when the options are resolved.
- _ = services.AddSingleton, TopologyOptionsValidator>();
- _ = services.AddOptions().BindConfiguration("AzureServiceBus:TopologyOptions");
- }
+ // Validator is registered here in case the user wants to use the options directly. This makes sure that the options are validated.
+ // The transport still has to validate the options because options validators are only executed when the options are resolved.
+ _ = services.AddSingleton, TopologyOptionsValidator>();
+ _ = services.AddOptions().BindConfiguration("AzureServiceBus:TopologyOptions");
+ }
- static FunctionsHostBuilderContext GetContextInternal(this IFunctionsHostBuilder functionsHostBuilder)
+ static FunctionsHostBuilderContext GetContextInternal(this IFunctionsHostBuilder functionsHostBuilder)
+ {
+ // This check is for testing purposes only. See more details on the internal interface below.
+ if (functionsHostBuilder is IFunctionsHostBuilderExt internalBuilder)
{
- // This check is for testing purposes only. See more details on the internal interface below.
- if (functionsHostBuilder is IFunctionsHostBuilderExt internalBuilder)
- {
- return internalBuilder.Context;
- }
-
- return functionsHostBuilder.GetContext();
+ return internalBuilder.Context;
}
- static IStartableEndpointWithExternallyManagedContainer Configure(
- EndpointConfiguration endpointConfiguration,
- IServiceCollection serviceCollection,
- string appDirectory = null)
+ return functionsHostBuilder.GetContext();
+ }
+
+ static IStartableEndpointWithExternallyManagedContainer Configure(
+ EndpointConfiguration endpointConfiguration,
+ IServiceCollection serviceCollection,
+ string appDirectory = null)
+ {
+ var scanner = endpointConfiguration.AssemblyScanner();
+ if (appDirectory != null)
{
- var scanner = endpointConfiguration.AssemblyScanner();
- if (appDirectory != null)
- {
- scanner.AdditionalAssemblyScanningPath = appDirectory;
- }
+ scanner.AdditionalAssemblyScanningPath = appDirectory;
+ }
- scanner.ExcludeAssemblies(InProcessFunctionEndpoint.AssembliesToExcludeFromScanning);
+ scanner.ExcludeAssemblies(InProcessFunctionEndpoint.AssembliesToExcludeFromScanning);
- return EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
- }
+ return EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionEndpoint.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionEndpoint.cs
index 84e0c49a..218a09fc 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionEndpoint.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionEndpoint.cs
@@ -1,99 +1,98 @@
-namespace NServiceBus
-{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus;
- using Microsoft.Azure.WebJobs.ServiceBus;
- using Microsoft.Extensions.Logging;
- using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
+namespace NServiceBus;
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.WebJobs.ServiceBus;
+using Microsoft.Extensions.Logging;
+using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
+///
+/// An NServiceBus endpoint hosted in Azure Function which does not receive messages automatically but only handles
+/// messages explicitly passed to it by the caller.
+///
+public interface IFunctionEndpoint
+{
///
- /// An NServiceBus endpoint hosted in Azure Function which does not receive messages automatically but only handles
- /// messages explicitly passed to it by the caller.
+ /// Processes the received message in atomic sends with receive mode.
///
- public interface IFunctionEndpoint
- {
- ///
- /// Processes the received message in atomic sends with receive mode.
- ///
- Task ProcessAtomic(
- ServiceBusReceivedMessage message,
- ExecutionContext executionContext,
- ServiceBusClient serviceBusClient,
- ServiceBusMessageActions messageActions,
- ILogger functionsLogger = null,
- CancellationToken cancellationToken = default);
+ Task ProcessAtomic(
+ ServiceBusReceivedMessage message,
+ ExecutionContext executionContext,
+ ServiceBusClient serviceBusClient,
+ ServiceBusMessageActions messageActions,
+ ILogger functionsLogger = null,
+ CancellationToken cancellationToken = default);
- ///
- /// Processes the received message in receive only transaction mode.
- ///
- Task ProcessNonAtomic(
- ServiceBusReceivedMessage message,
- ExecutionContext executionContext,
- ILogger functionsLogger = null,
- CancellationToken cancellationToken = default);
+ ///
+ /// Processes the received message in receive only transaction mode.
+ ///
+ Task ProcessNonAtomic(
+ ServiceBusReceivedMessage message,
+ ExecutionContext executionContext,
+ ILogger functionsLogger = null,
+ CancellationToken cancellationToken = default);
- ///
- /// Sends the provided message.
- ///
- Task Send(object message, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Sends the provided message.
+ ///
+ Task Send(object message, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Sends the provided message.
- ///
- Task Send(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Sends the provided message.
+ ///
+ Task Send(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Instantiates a message of type T and sends it.
- ///
- Task Send(Action messageConstructor, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Instantiates a message of type T and sends it.
+ ///
+ Task Send(Action messageConstructor, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Instantiates a message of type T and sends it.
- ///
- Task Send(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Instantiates a message of type T and sends it.
+ ///
+ Task Send(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Publish the message to subscribers.
- ///
- Task Publish(object message, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Publish the message to subscribers.
+ ///
+ Task Publish(object message, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Instantiates a message of type T and publishes it.
- ///
- Task Publish(Action messageConstructor, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Instantiates a message of type T and publishes it.
+ ///
+ Task Publish(Action messageConstructor, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Instantiates a message of type T and publishes it.
- ///
- Task Publish(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Instantiates a message of type T and publishes it.
+ ///
+ Task Publish(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Instantiates a message of type T and publishes it.
- ///
- Task Publish(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Instantiates a message of type T and publishes it.
+ ///
+ Task Publish(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Subscribes to receive published messages of the specified type.
- /// This method is only necessary if you turned off auto-subscribe.
- ///
- Task Subscribe(Type eventType, SubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Subscribes to receive published messages of the specified type.
+ /// This method is only necessary if you turned off auto-subscribe.
+ ///
+ Task Subscribe(Type eventType, SubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Subscribes to receive published messages of the specified type.
- /// This method is only necessary if you turned off auto-subscribe.
- ///
- Task Subscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Subscribes to receive published messages of the specified type.
+ /// This method is only necessary if you turned off auto-subscribe.
+ ///
+ Task Subscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Unsubscribes to receive published messages of the specified type.
- ///
- Task Unsubscribe(Type eventType, UnsubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
+ ///
+ /// Unsubscribes to receive published messages of the specified type.
+ ///
+ Task Unsubscribe(Type eventType, UnsubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- ///
- /// Unsubscribes to receive published messages of the specified type.
- ///
- Task Unsubscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
- }
+ ///
+ /// Unsubscribes to receive published messages of the specified type.
+ ///
+ Task Unsubscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionsHostBuilderExt.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionsHostBuilderExt.cs
index 5f0e6a7e..d0b1bc21 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionsHostBuilderExt.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/IFunctionsHostBuilderExt.cs
@@ -1,12 +1,11 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using Microsoft.Azure.Functions.Extensions.DependencyInjection;
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using Microsoft.Azure.Functions.Extensions.DependencyInjection;
- // This is an internal marker interface similar to Microsoft.Azure.Functions.Extensions.DependencyInjection.IFunctionsHostBuilderExt
- // to facilitate test. It will only ever be implemented by the testing infrastructure and probably only required until in process
- // functions properly support the generic host.
- interface IFunctionsHostBuilderExt
- {
- FunctionsHostBuilderContext Context { get; }
- }
+// This is an internal marker interface similar to Microsoft.Azure.Functions.Extensions.DependencyInjection.IFunctionsHostBuilderExt
+// to facilitate test. It will only ever be implemented by the testing infrastructure and probably only required until in process
+// functions properly support the generic host.
+interface IFunctionsHostBuilderExt
+{
+ FunctionsHostBuilderContext Context { get; }
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/InProcessFunctionEndpoint.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/InProcessFunctionEndpoint.cs
index 95863bd5..24af567c 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/InProcessFunctionEndpoint.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/InProcessFunctionEndpoint.cs
@@ -1,189 +1,189 @@
-namespace NServiceBus
+namespace NServiceBus;
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using AzureFunctions.InProcess.ServiceBus;
+using Microsoft.Azure.WebJobs.ServiceBus;
+using Microsoft.Extensions.Logging;
+using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
+
+class InProcessFunctionEndpoint : IFunctionEndpoint
{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus;
- using AzureFunctions.InProcess.ServiceBus;
- using Microsoft.Azure.WebJobs.ServiceBus;
- using Microsoft.Extensions.Logging;
- using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
-
- class InProcessFunctionEndpoint : IFunctionEndpoint
- {
- public InProcessFunctionEndpoint(
- IStartableEndpointWithExternallyManagedContainer externallyManagedContainerEndpoint,
- ServerlessTransport serverlessTransport,
- IServiceProvider serviceProvider)
+ public InProcessFunctionEndpoint(
+ IStartableEndpointWithExternallyManagedContainer externallyManagedContainerEndpoint,
+ ServerlessTransport serverlessTransport,
+ IServiceProvider serviceProvider)
+ {
+ this.serverlessTransport = serverlessTransport;
+ this.serverlessTransport.ServiceProvider = serviceProvider;
+ endpointFactory = () => externallyManagedContainerEndpoint.Start(serviceProvider);
+ }
+
+ public async Task ProcessAtomic(
+ ServiceBusReceivedMessage message,
+ ExecutionContext executionContext,
+ ServiceBusClient serviceBusClient,
+ ServiceBusMessageActions messageActions,
+ ILogger functionsLogger = null,
+ CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+
+ try
{
- this.serverlessTransport = serverlessTransport;
- this.serverlessTransport.ServiceProvider = serviceProvider;
- endpointFactory = () => externallyManagedContainerEndpoint.Start(serviceProvider);
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
}
-
- public async Task ProcessAtomic(
- ServiceBusReceivedMessage message,
- ExecutionContext executionContext,
- ServiceBusClient serviceBusClient,
- ServiceBusMessageActions messageActions,
- ILogger functionsLogger = null,
- CancellationToken cancellationToken = default)
+ catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
{
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
-
- try
- {
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
- {
- await messageActions.AbandonMessageAsync(message, cancellationToken: cancellationToken).ConfigureAwait(false);
- throw;
- }
-
- await messageProcessor.ProcessAtomic(message, serviceBusClient, messageActions, cancellationToken)
- .ConfigureAwait(false);
+ await messageActions.AbandonMessageAsync(message, cancellationToken: cancellationToken).ConfigureAwait(false);
+ throw;
}
- public async Task ProcessNonAtomic(
- ServiceBusReceivedMessage message,
- ExecutionContext executionContext,
- ILogger functionsLogger = null,
- CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ await messageProcessor.ProcessAtomic(message, serviceBusClient, messageActions, cancellationToken)
+ .ConfigureAwait(false);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ public async Task ProcessNonAtomic(
+ ServiceBusReceivedMessage message,
+ ExecutionContext executionContext,
+ ILogger functionsLogger = null,
+ CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- await messageProcessor.ProcessNonAtomic(message, cancellationToken)
- .ConfigureAwait(false);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- public async Task Send(object message, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ await messageProcessor.ProcessNonAtomic(message, cancellationToken)
+ .ConfigureAwait(false);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Send(message, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Send(object message, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Send(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Send(message, new SendOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Send(message, options, cancellationToken).ConfigureAwait(false);
+ }
- public async Task Send(Action messageConstructor, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ public Task Send(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Send(message, new SendOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Send(messageConstructor, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Send(Action messageConstructor, SendOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Send(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Send(messageConstructor, new SendOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Send(messageConstructor, options, cancellationToken).ConfigureAwait(false);
+ }
- public async Task Publish(object message, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ public Task Send(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Send(messageConstructor, new SendOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Publish(message, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Publish(object message, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Publish(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Publish(message, new PublishOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Publish(message, options, cancellationToken).ConfigureAwait(false);
+ }
- public async Task Publish(Action messageConstructor, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ public Task Publish(object message, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Publish(message, new PublishOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Publish(messageConstructor, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Publish(Action messageConstructor, PublishOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Publish(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Publish(messageConstructor, new PublishOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Publish(messageConstructor, options, cancellationToken).ConfigureAwait(false);
+ }
- public async Task Subscribe(Type eventType, SubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ public Task Publish(Action messageConstructor, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Publish(messageConstructor, new PublishOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Subscribe(eventType, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Subscribe(Type eventType, SubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Subscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Subscribe(eventType, new SubscribeOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Subscribe(eventType, options, cancellationToken).ConfigureAwait(false);
+ }
- public async Task Unsubscribe(Type eventType, UnsubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
+ public Task Subscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Subscribe(eventType, new SubscribeOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
- await endpoint.Unsubscribe(eventType, options, cancellationToken).ConfigureAwait(false);
- }
+ public async Task Unsubscribe(Type eventType, UnsubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);
- public Task Unsubscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
- {
- return Unsubscribe(eventType, new UnsubscribeOptions(), executionContext, functionsLogger, cancellationToken);
- }
+ await InitializeEndpointIfNecessary(cancellationToken).ConfigureAwait(false);
+ await endpoint.Unsubscribe(eventType, options, cancellationToken).ConfigureAwait(false);
+ }
+
+ public Task Unsubscribe(Type eventType, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
+ {
+ return Unsubscribe(eventType, new UnsubscribeOptions(), executionContext, functionsLogger, cancellationToken);
+ }
- internal static readonly string[] AssembliesToExcludeFromScanning = {
- "Azure.Core.dll",
- "Azure.Identity.dll",
- "Azure.Security.KeyVault.Secrets.dll",
- "Azure.Storage.Blobs.dll",
- "Azure.Storage.Common.dll",
- "Google.Protobuf.dll",
- "Grpc.AspNetCore.Server.ClientFactory.dll",
- "Grpc.AspNetCore.Server.dll",
- "Grpc.Core.Api.dll",
- "Grpc.Net.Client.dll",
- "Grpc.Net.ClientFactory.dll",
- "Grpc.Net.Common.dll",
- "Microsoft.Extensions.Azure.dll",
- "Microsoft.Identity.Client.dll",
- "Microsoft.Identity.Client.Extensions.Msal.dll",
- "NCrontab.Signed.dll",
- "NServiceBus.Extensions.DependencyInjection.dll",
- "System.ClientModel.dll"
- };
-
- internal async Task InitializeEndpointIfNecessary(CancellationToken cancellationToken = default)
+ internal static readonly string[] AssembliesToExcludeFromScanning =
+ [
+ "Azure.Core.dll",
+ "Azure.Identity.dll",
+ "Azure.Security.KeyVault.Secrets.dll",
+ "Azure.Storage.Blobs.dll",
+ "Azure.Storage.Common.dll",
+ "Google.Protobuf.dll",
+ "Grpc.AspNetCore.Server.ClientFactory.dll",
+ "Grpc.AspNetCore.Server.dll",
+ "Grpc.Core.Api.dll",
+ "Grpc.Net.Client.dll",
+ "Grpc.Net.ClientFactory.dll",
+ "Grpc.Net.Common.dll",
+ "Microsoft.Extensions.Azure.dll",
+ "Microsoft.Identity.Client.dll",
+ "Microsoft.Identity.Client.Extensions.Msal.dll",
+ "NCrontab.Signed.dll",
+ "NServiceBus.Extensions.DependencyInjection.dll",
+ "System.ClientModel.dll"
+ ];
+
+ internal async Task InitializeEndpointIfNecessary(CancellationToken cancellationToken = default)
+ {
+ if (messageProcessor == null)
{
- if (messageProcessor == null)
+ await semaphoreLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+ try
{
- await semaphoreLock.WaitAsync(cancellationToken).ConfigureAwait(false);
- try
+ if (messageProcessor == null)
{
- if (messageProcessor == null)
- {
- endpoint = await endpointFactory().ConfigureAwait(false);
+ endpoint = await endpointFactory().ConfigureAwait(false);
- messageProcessor = serverlessTransport.MessageProcessor;
- }
- }
- finally
- {
- semaphoreLock.Release();
+ messageProcessor = serverlessTransport.MessageProcessor;
}
}
+ finally
+ {
+ semaphoreLock.Release();
+ }
}
+ }
- IMessageProcessor messageProcessor;
- IEndpointInstance endpoint;
+ IMessageProcessor messageProcessor;
+ IEndpointInstance endpoint;
- readonly Func> endpointFactory;
- readonly SemaphoreSlim semaphoreLock = new SemaphoreSlim(initialCount: 1, maxCount: 1);
- readonly ServerlessTransport serverlessTransport;
- }
+ readonly Func> endpointFactory;
+ readonly SemaphoreSlim semaphoreLock = new SemaphoreSlim(initialCount: 1, maxCount: 1);
+ readonly ServerlessTransport serverlessTransport;
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/FunctionsLoggerFactory.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/FunctionsLoggerFactory.cs
index 40fdcd03..8c0e4c91 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/FunctionsLoggerFactory.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/FunctionsLoggerFactory.cs
@@ -1,41 +1,40 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Threading;
+using Logging;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using ILoggerFactory = Logging.ILoggerFactory;
+
+class FunctionsLoggerFactory : ILoggerFactory
{
- using System;
- using System.Threading;
- using Logging;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using ILoggerFactory = Logging.ILoggerFactory;
-
- class FunctionsLoggerFactory : ILoggerFactory
- {
- public static FunctionsLoggerFactory Instance { get; } = new FunctionsLoggerFactory();
+ public static FunctionsLoggerFactory Instance { get; } = new FunctionsLoggerFactory();
- Logger log;
+ Logger log;
- AsyncLocal logger = new AsyncLocal();
+ AsyncLocal logger = new AsyncLocal();
- FunctionsLoggerFactory()
- {
- log = new Logger(logger);
- }
+ FunctionsLoggerFactory()
+ {
+ log = new Logger(logger);
+ }
- public void SetCurrentLogger(ILogger currentLogger)
- {
- var newLogger = currentLogger ?? NullLogger.Instance;
+ public void SetCurrentLogger(ILogger currentLogger)
+ {
+ var newLogger = currentLogger ?? NullLogger.Instance;
- logger.Value = newLogger;
- log.Flush(newLogger);
- }
+ logger.Value = newLogger;
+ log.Flush(newLogger);
+ }
- public ILog GetLogger(Type type)
- {
- return log;
- }
+ public ILog GetLogger(Type type)
+ {
+ return log;
+ }
- public ILog GetLogger(string name)
- {
- return log;
- }
+ public ILog GetLogger(string name)
+ {
+ return log;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/Logger.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/Logger.cs
index 97f33406..00a32de0 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/Logger.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Logging/Logger.cs
@@ -1,109 +1,108 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+using Logging;
+using Microsoft.Extensions.Logging;
+using LogLevel = Microsoft.Extensions.Logging.LogLevel;
+
+class Logger : ILog
{
- using System;
- using System.Collections.Concurrent;
- using System.Threading;
- using Logging;
- using Microsoft.Extensions.Logging;
- using LogLevel = Microsoft.Extensions.Logging.LogLevel;
-
- class Logger : ILog
+ public Logger(AsyncLocal logger)
{
- public Logger(AsyncLocal logger)
- {
- this.logger = logger;
- }
+ this.logger = logger;
+ }
- public bool IsDebugEnabled => logger.Value?.IsEnabled(LogLevel.Debug) ?? true;
- public bool IsInfoEnabled => logger.Value?.IsEnabled(LogLevel.Information) ?? true;
- public bool IsWarnEnabled => logger.Value?.IsEnabled(LogLevel.Warning) ?? true;
- public bool IsErrorEnabled => logger.Value?.IsEnabled(LogLevel.Error) ?? true;
- public bool IsFatalEnabled => logger.Value?.IsEnabled(LogLevel.Critical) ?? true;
+ public bool IsDebugEnabled => logger.Value?.IsEnabled(LogLevel.Debug) ?? true;
+ public bool IsInfoEnabled => logger.Value?.IsEnabled(LogLevel.Information) ?? true;
+ public bool IsWarnEnabled => logger.Value?.IsEnabled(LogLevel.Warning) ?? true;
+ public bool IsErrorEnabled => logger.Value?.IsEnabled(LogLevel.Error) ?? true;
+ public bool IsFatalEnabled => logger.Value?.IsEnabled(LogLevel.Critical) ?? true;
- void Log(LogLevel level, string message)
+ void Log(LogLevel level, string message)
+ {
+ var concreteLogger = logger.Value;
+ if (concreteLogger == null)
{
- var concreteLogger = logger.Value;
- if (concreteLogger == null)
- {
- deferredMessageLogs.Enqueue((level, message));
- return;
- }
- concreteLogger.Log(level, message);
+ deferredMessageLogs.Enqueue((level, message));
+ return;
}
+ concreteLogger.Log(level, message);
+ }
- void Log(LogLevel level, string message, Exception exception)
+ void Log(LogLevel level, string message, Exception exception)
+ {
+ var concreteLogger = logger.Value;
+ if (concreteLogger == null)
{
- var concreteLogger = logger.Value;
- if (concreteLogger == null)
- {
- deferredExceptionLogs.Enqueue((level, message, exception));
- return;
- }
- concreteLogger.Log(level, exception, message);
+ deferredExceptionLogs.Enqueue((level, message, exception));
+ return;
}
+ concreteLogger.Log(level, exception, message);
+ }
- void Log(LogLevel level, string format, object[] args)
+ void Log(LogLevel level, string format, object[] args)
+ {
+ var concreteLogger = logger.Value;
+ if (concreteLogger == null)
{
- var concreteLogger = logger.Value;
- if (concreteLogger == null)
- {
- deferredFormatLogs.Enqueue((level, format, args));
- return;
- }
- concreteLogger.Log(level, format, args);
+ deferredFormatLogs.Enqueue((level, format, args));
+ return;
}
+ concreteLogger.Log(level, format, args);
+ }
- public void Debug(string message) => Log(LogLevel.Debug, message);
+ public void Debug(string message) => Log(LogLevel.Debug, message);
- public void Debug(string message, Exception exception) => Log(LogLevel.Debug, message, exception);
+ public void Debug(string message, Exception exception) => Log(LogLevel.Debug, message, exception);
- public void DebugFormat(string format, params object[] args) => Log(LogLevel.Debug, format, args);
+ public void DebugFormat(string format, params object[] args) => Log(LogLevel.Debug, format, args);
- public void Info(string message) => Log(LogLevel.Information, message);
+ public void Info(string message) => Log(LogLevel.Information, message);
- public void Info(string message, Exception exception) => Log(LogLevel.Information, message, exception);
+ public void Info(string message, Exception exception) => Log(LogLevel.Information, message, exception);
- public void InfoFormat(string format, params object[] args) => Log(LogLevel.Information, format, args);
+ public void InfoFormat(string format, params object[] args) => Log(LogLevel.Information, format, args);
- public void Warn(string message) => Log(LogLevel.Warning, message);
+ public void Warn(string message) => Log(LogLevel.Warning, message);
- public void Warn(string message, Exception exception) => Log(LogLevel.Warning, message, exception);
+ public void Warn(string message, Exception exception) => Log(LogLevel.Warning, message, exception);
- public void WarnFormat(string format, params object[] args) => Log(LogLevel.Warning, format, args);
+ public void WarnFormat(string format, params object[] args) => Log(LogLevel.Warning, format, args);
- public void Error(string message) => Log(LogLevel.Error, message);
+ public void Error(string message) => Log(LogLevel.Error, message);
- public void Error(string message, Exception exception) => Log(LogLevel.Error, message, exception);
+ public void Error(string message, Exception exception) => Log(LogLevel.Error, message, exception);
- public void ErrorFormat(string format, params object[] args) => Log(LogLevel.Error, format, args);
+ public void ErrorFormat(string format, params object[] args) => Log(LogLevel.Error, format, args);
- public void Fatal(string message) => Log(LogLevel.Critical, message);
+ public void Fatal(string message) => Log(LogLevel.Critical, message);
- public void Fatal(string message, Exception exception) => Log(LogLevel.Critical, message, exception);
+ public void Fatal(string message, Exception exception) => Log(LogLevel.Critical, message, exception);
- public void FatalFormat(string format, params object[] args) => Log(LogLevel.Critical, format, args);
+ public void FatalFormat(string format, params object[] args) => Log(LogLevel.Critical, format, args);
- internal void Flush(ILogger concreteLogger)
+ internal void Flush(ILogger concreteLogger)
+ {
+ while (deferredMessageLogs.TryDequeue(out var entry))
{
- while (deferredMessageLogs.TryDequeue(out var entry))
- {
- concreteLogger.Log(entry.level, entry.message);
- }
-
- while (deferredExceptionLogs.TryDequeue(out var entry))
- {
- concreteLogger.Log(entry.level, entry.exception, entry.message);
- }
-
- while (deferredFormatLogs.TryDequeue(out var entry))
- {
- concreteLogger.Log(entry.level, entry.format, entry.args);
- }
+ concreteLogger.Log(entry.level, entry.message);
}
- AsyncLocal logger;
- readonly ConcurrentQueue<(LogLevel level, string message)> deferredMessageLogs = new ConcurrentQueue<(LogLevel level, string message)>();
- readonly ConcurrentQueue<(LogLevel level, string message, Exception exception)> deferredExceptionLogs = new ConcurrentQueue<(LogLevel level, string message, Exception exception)>();
- readonly ConcurrentQueue<(LogLevel level, string format, object[] args)> deferredFormatLogs = new ConcurrentQueue<(LogLevel level, string format, object[] args)>();
+ while (deferredExceptionLogs.TryDequeue(out var entry))
+ {
+ concreteLogger.Log(entry.level, entry.exception, entry.message);
+ }
+
+ while (deferredFormatLogs.TryDequeue(out var entry))
+ {
+ concreteLogger.Log(entry.level, entry.format, entry.args);
+ }
}
+
+ AsyncLocal logger;
+ readonly ConcurrentQueue<(LogLevel level, string message)> deferredMessageLogs = new ConcurrentQueue<(LogLevel level, string message)>();
+ readonly ConcurrentQueue<(LogLevel level, string message, Exception exception)> deferredExceptionLogs = new ConcurrentQueue<(LogLevel level, string message, Exception exception)>();
+ readonly ConcurrentQueue<(LogLevel level, string format, object[] args)> deferredFormatLogs = new ConcurrentQueue<(LogLevel level, string format, object[] args)>();
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/MessageExtensions.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/MessageExtensions.cs
index e77a6da1..bc72228e 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/MessageExtensions.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/MessageExtensions.cs
@@ -1,44 +1,43 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using System;
- using System.Collections.Generic;
- using Azure.Messaging.ServiceBus;
-
- static class MessageExtensions
- {
- public static Dictionary GetHeaders(this ServiceBusReceivedMessage message)
- {
- var headers = new Dictionary(message.ApplicationProperties.Count);
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
- foreach (var kvp in message.ApplicationProperties)
- {
- headers[kvp.Key] = kvp.Value?.ToString();
- }
+using System;
+using System.Collections.Generic;
+using Azure.Messaging.ServiceBus;
- headers.Remove("NServiceBus.Transport.Encoding");
+static class MessageExtensions
+{
+ public static Dictionary GetHeaders(this ServiceBusReceivedMessage message)
+ {
+ var headers = new Dictionary(message.ApplicationProperties.Count);
- if (!string.IsNullOrWhiteSpace(message.ReplyTo))
- {
- headers[Headers.ReplyToAddress] = message.ReplyTo;
- }
+ foreach (var kvp in message.ApplicationProperties)
+ {
+ headers[kvp.Key] = kvp.Value?.ToString();
+ }
- if (!string.IsNullOrWhiteSpace(message.CorrelationId))
- {
- headers[Headers.CorrelationId] = message.CorrelationId;
- }
+ headers.Remove("NServiceBus.Transport.Encoding");
- return headers;
+ if (!string.IsNullOrWhiteSpace(message.ReplyTo))
+ {
+ headers[Headers.ReplyToAddress] = message.ReplyTo;
}
- public static string GetMessageId(this ServiceBusReceivedMessage message)
+ if (!string.IsNullOrWhiteSpace(message.CorrelationId))
{
- if (string.IsNullOrEmpty(message.MessageId))
- {
- // assume native message w/o message ID
- return Guid.NewGuid().ToString("N");
- }
+ headers[Headers.CorrelationId] = message.CorrelationId;
+ }
+
+ return headers;
+ }
- return message.MessageId;
+ public static string GetMessageId(this ServiceBusReceivedMessage message)
+ {
+ if (string.IsNullOrEmpty(message.MessageId))
+ {
+ // assume native message w/o message ID
+ return Guid.NewGuid().ToString("N");
}
+
+ return message.MessageId;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/NServiceBusTriggerFunctionAttribute.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/NServiceBusTriggerFunctionAttribute.cs
index 8cf28ed1..5375b29d 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/NServiceBusTriggerFunctionAttribute.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/NServiceBusTriggerFunctionAttribute.cs
@@ -1,39 +1,38 @@
-namespace NServiceBus
+namespace NServiceBus;
+
+///
+/// Assembly attribute to configure generated NServiceBus Azure Function.
+/// The attribute is used to wire up an auto-generated Service Bus trigger function, responding to messages in the queue specified by the name provided.
+///
+[System.AttributeUsage(System.AttributeTargets.Assembly)]
+public sealed class NServiceBusTriggerFunctionAttribute : System.Attribute
{
- ///
- /// Assembly attribute to configure generated NServiceBus Azure Function.
- /// The attribute is used to wire up an auto-generated Service Bus trigger function, responding to messages in the queue specified by the name provided.
- ///
- [System.AttributeUsage(System.AttributeTargets.Assembly)]
- public sealed class NServiceBusTriggerFunctionAttribute : System.Attribute
- {
- ///
- /// Endpoint name that is the input queue name.
- ///
- public string EndpointName { get; }
+ ///
+ /// Endpoint name that is the input queue name.
+ ///
+ public string EndpointName { get; }
- ///
- /// Override trigger function name.
- ///
- public string TriggerFunctionName { get; set; }
+ ///
+ /// Override trigger function name.
+ ///
+ public string TriggerFunctionName { get; set; }
- ///
- /// Enable Azure Service Bus transactions to provide transport guarantees.
- ///
- public bool SendsAtomicWithReceive { get; set; }
+ ///
+ /// Enable Azure Service Bus transactions to provide transport guarantees.
+ ///
+ public bool SendsAtomicWithReceive { get; set; }
- ///
- /// Gets or sets the app setting name that contains the Service Bus connection string.
- ///
- public string Connection { get; set; }
+ ///
+ /// Gets or sets the app setting name that contains the Service Bus connection string.
+ ///
+ public string Connection { get; set; }
- ///
- /// Endpoint logical name.
- ///
- /// Endpoint name that is the input queue name.
- public NServiceBusTriggerFunctionAttribute(string endpointName)
- {
- EndpointName = endpointName;
- }
+ ///
+ /// Endpoint logical name.
+ ///
+ /// Endpoint name that is the input queue name.
+ public NServiceBusTriggerFunctionAttribute(string endpointName)
+ {
+ EndpointName = endpointName;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/DeterministicGuid.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/DeterministicGuid.cs
index 9a693937..1ca3e01b 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/DeterministicGuid.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/DeterministicGuid.cs
@@ -1,21 +1,20 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using System;
- using System.Security.Cryptography;
- using System.Text;
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Security.Cryptography;
+using System.Text;
- static class DeterministicGuid
+static class DeterministicGuid
+{
+ public static Guid Create(string data)
{
- public static Guid Create(string data)
+ // use MD5 hash to get a 16-byte hash of the string
+ using (var provider = MD5.Create())
{
- // use MD5 hash to get a 16-byte hash of the string
- using (var provider = MD5.Create())
- {
- var inputBytes = Encoding.Default.GetBytes(data);
- var hashBytes = provider.ComputeHash(inputBytes);
- // generate a guid from the hash:
- return new Guid(hashBytes);
- }
+ var inputBytes = Encoding.Default.GetBytes(data);
+ var hashBytes = provider.ComputeHash(inputBytes);
+ // generate a guid from the hash:
+ return new Guid(hashBytes);
}
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/Recoverability/ServerlessRecoverabilityPolicy.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/Recoverability/ServerlessRecoverabilityPolicy.cs
index 8a7cf8e5..f2503362 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/Recoverability/ServerlessRecoverabilityPolicy.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/Recoverability/ServerlessRecoverabilityPolicy.cs
@@ -1,28 +1,27 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using Transport;
+
+class ServerlessRecoverabilityPolicy
{
- using System;
- using Transport;
+ public bool SendFailedMessagesToErrorQueue { get; set; }
- class ServerlessRecoverabilityPolicy
+ public RecoverabilityAction Invoke(RecoverabilityConfig config, ErrorContext errorContext)
{
- public bool SendFailedMessagesToErrorQueue { get; set; }
+ var action = DefaultRecoverabilityPolicy.Invoke(config, errorContext);
- public RecoverabilityAction Invoke(RecoverabilityConfig config, ErrorContext errorContext)
+ if (action is MoveToError)
{
- var action = DefaultRecoverabilityPolicy.Invoke(config, errorContext);
-
- if (action is MoveToError)
+ if (SendFailedMessagesToErrorQueue)
{
- if (SendFailedMessagesToErrorQueue)
- {
- return action;
- }
-
- // 7.2 offers a Discard option, but we want to bubble up the exception so it can fail the function invocation.
- throw new Exception("Failed to process message.", errorContext.Exception);
+ return action;
}
- return action;
+ // 7.2 offers a Discard option, but we want to bubble up the exception so it can fail the function invocation.
+ throw new Exception("Failed to process message.", errorContext.Exception);
}
+
+ return action;
}
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/IMessageProcessor.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/IMessageProcessor.cs
index d2396645..3229a0e9 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/IMessageProcessor.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/IMessageProcessor.cs
@@ -1,20 +1,19 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus;
- using Microsoft.Azure.WebJobs.ServiceBus;
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.WebJobs.ServiceBus;
- interface IMessageProcessor
- {
- Task ProcessNonAtomic(
- ServiceBusReceivedMessage message,
- CancellationToken cancellationToken = default);
+interface IMessageProcessor
+{
+ Task ProcessNonAtomic(
+ ServiceBusReceivedMessage message,
+ CancellationToken cancellationToken = default);
- Task ProcessAtomic(
- ServiceBusReceivedMessage message,
- ServiceBusClient serviceBusClient,
- ServiceBusMessageActions messageActions,
- CancellationToken cancellationToken = default);
- }
+ Task ProcessAtomic(
+ ServiceBusReceivedMessage message,
+ ServiceBusClient serviceBusClient,
+ ServiceBusMessageActions messageActions,
+ CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/PipelineInvokingMessageProcessor.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/PipelineInvokingMessageProcessor.cs
index e592c0c6..feac946a 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/PipelineInvokingMessageProcessor.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/PipelineInvokingMessageProcessor.cs
@@ -1,154 +1,153 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Transactions;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.WebJobs.ServiceBus;
+using NServiceBus.AzureFunctions.InProcess.ServiceBus.Serverless;
+using NServiceBus.Extensibility;
+using NServiceBus.Transport.AzureServiceBus;
+using Transport;
+
+class PipelineInvokingMessageProcessor : IMessageReceiver, IMessageProcessor
{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Transactions;
- using Azure.Messaging.ServiceBus;
- using Microsoft.Azure.WebJobs.ServiceBus;
- using NServiceBus.AzureFunctions.InProcess.ServiceBus.Serverless;
- using NServiceBus.Extensibility;
- using NServiceBus.Transport.AzureServiceBus;
- using Transport;
-
- class PipelineInvokingMessageProcessor : IMessageReceiver, IMessageProcessor
+ public PipelineInvokingMessageProcessor(IMessageReceiver baseTransportReceiver) => this.baseTransportReceiver = baseTransportReceiver;
+
+ public Task Initialize(PushRuntimeSettings limitations, OnMessage onMessage, OnError onError,
+ CancellationToken cancellationToken = default)
{
- public PipelineInvokingMessageProcessor(IMessageReceiver baseTransportReceiver) => this.baseTransportReceiver = baseTransportReceiver;
+ this.onMessage = onMessage;
+ this.onError = onError;
+ return baseTransportReceiver.Initialize(limitations,
+ (_, __) => Task.CompletedTask,
+ (_, __) => Task.FromResult(ErrorHandleResult.Handled),
+ cancellationToken) ?? Task.CompletedTask;
+ }
- public Task Initialize(PushRuntimeSettings limitations, OnMessage onMessage, OnError onError,
- CancellationToken cancellationToken = default)
+ public async Task ProcessNonAtomic(
+ ServiceBusReceivedMessage message,
+ CancellationToken cancellationToken = default)
+ {
+ try
{
- this.onMessage = onMessage;
- this.onError = onError;
- return baseTransportReceiver.Initialize(limitations,
- (_, __) => Task.CompletedTask,
- (_, __) => Task.FromResult(ErrorHandleResult.Handled),
- cancellationToken) ?? Task.CompletedTask;
- }
+ var messageContext = CreateMessageContext(message, new TransportTransaction(), false);
+
+ await onMessage(messageContext, cancellationToken).ConfigureAwait(false);
- public async Task ProcessNonAtomic(
- ServiceBusReceivedMessage message,
- CancellationToken cancellationToken = default)
+ }
+ catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
{
- try
- {
- var messageContext = CreateMessageContext(message, new TransportTransaction(), false);
+ var errorContext = CreateErrorContext(message, new TransportTransaction(), ex);
- await onMessage(messageContext, cancellationToken).ConfigureAwait(false);
+ var errorHandleResult = await onError(errorContext, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
+ if (errorHandleResult == ErrorHandleResult.Handled)
{
- var errorContext = CreateErrorContext(message, new TransportTransaction(), ex);
-
- var errorHandleResult = await onError(errorContext, cancellationToken).ConfigureAwait(false);
-
- if (errorHandleResult == ErrorHandleResult.Handled)
- {
- return;
- }
- throw;
+ return;
}
+ throw;
}
+ }
- public async Task ProcessAtomic(
- ServiceBusReceivedMessage message,
- ServiceBusClient serviceBusClient,
- ServiceBusMessageActions messageActions,
- CancellationToken cancellationToken = default)
+ public async Task ProcessAtomic(
+ ServiceBusReceivedMessage message,
+ ServiceBusClient serviceBusClient,
+ ServiceBusMessageActions messageActions,
+ CancellationToken cancellationToken = default)
+ {
+ try
{
- try
+ using (var azureServiceBusTransaction = CreateTransaction(message.PartitionKey, serviceBusClient))
{
- using (var azureServiceBusTransaction = CreateTransaction(message.PartitionKey, serviceBusClient))
- {
- var messageContext = CreateMessageContext(message, azureServiceBusTransaction.TransportTransaction, true);
+ var messageContext = CreateMessageContext(message, azureServiceBusTransaction.TransportTransaction, true);
- await onMessage(messageContext, cancellationToken).ConfigureAwait(false);
+ await onMessage(messageContext, cancellationToken).ConfigureAwait(false);
- await SafeCompleteMessageAsync(messageActions, message, azureServiceBusTransaction, cancellationToken).ConfigureAwait(false);
- azureServiceBusTransaction.Commit();
- }
+ await SafeCompleteMessageAsync(messageActions, message, azureServiceBusTransaction, cancellationToken).ConfigureAwait(false);
+ azureServiceBusTransaction.Commit();
}
- catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
+ }
+ catch (Exception ex) when (ex is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
+ {
+ ErrorHandleResult result;
+ using (var azureServiceBusTransaction = CreateTransaction(message.PartitionKey, serviceBusClient))
{
- ErrorHandleResult result;
- using (var azureServiceBusTransaction = CreateTransaction(message.PartitionKey, serviceBusClient))
- {
- var errorContext = CreateErrorContext(message, azureServiceBusTransaction.TransportTransaction, ex);
-
- result = await onError(errorContext, cancellationToken).ConfigureAwait(false);
+ var errorContext = CreateErrorContext(message, azureServiceBusTransaction.TransportTransaction, ex);
- if (result == ErrorHandleResult.Handled)
- {
- await SafeCompleteMessageAsync(messageActions, message, azureServiceBusTransaction, cancellationToken).ConfigureAwait(false);
- }
+ result = await onError(errorContext, cancellationToken).ConfigureAwait(false);
- azureServiceBusTransaction.Commit();
- }
-
- if (result != ErrorHandleResult.Handled)
+ if (result == ErrorHandleResult.Handled)
{
- await messageActions.AbandonMessageAsync(message, cancellationToken: cancellationToken).ConfigureAwait(false);
+ await SafeCompleteMessageAsync(messageActions, message, azureServiceBusTransaction, cancellationToken).ConfigureAwait(false);
}
+
+ azureServiceBusTransaction.Commit();
}
- }
- ErrorContext CreateErrorContext(ServiceBusReceivedMessage message, TransportTransaction transportTransaction, Exception exception)
- {
- var errorContext = new ErrorContext(
- exception,
- message.GetHeaders(),
- message.MessageId,
- message.Body,
- transportTransaction,
- message.DeliveryCount,
- ReceiveAddress,
- new ContextBag());
- return errorContext;
+ if (result != ErrorHandleResult.Handled)
+ {
+ await messageActions.AbandonMessageAsync(message, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
}
+ }
- MessageContext CreateMessageContext(ServiceBusReceivedMessage message, TransportTransaction transportTransaction, bool atomic)
- {
- var contextBag = new ContextBag();
- var invocationMode = new FunctionInvocationMode(atomic);
- contextBag.Set(invocationMode);
- var messageContext = new MessageContext(
- message.MessageId,
- message.GetHeaders(),
- message.Body,
- transportTransaction,
- ReceiveAddress,
- contextBag);
- return messageContext;
- }
+ ErrorContext CreateErrorContext(ServiceBusReceivedMessage message, TransportTransaction transportTransaction, Exception exception)
+ {
+ var errorContext = new ErrorContext(
+ exception,
+ message.GetHeaders(),
+ message.MessageId,
+ message.Body,
+ transportTransaction,
+ message.DeliveryCount,
+ ReceiveAddress,
+ new ContextBag());
+ return errorContext;
+ }
- static async Task SafeCompleteMessageAsync(ServiceBusMessageActions messageActions, ServiceBusReceivedMessage message, AzureServiceBusTransportTransaction azureServiceBusTransaction, CancellationToken cancellationToken)
- {
- using var scope = azureServiceBusTransaction.ToTransactionScope();
- await messageActions.CompleteMessageAsync(message, cancellationToken).ConfigureAwait(false);
- scope.Complete();
- }
+ MessageContext CreateMessageContext(ServiceBusReceivedMessage message, TransportTransaction transportTransaction, bool atomic)
+ {
+ var contextBag = new ContextBag();
+ var invocationMode = new FunctionInvocationMode(atomic);
+ contextBag.Set(invocationMode);
+ var messageContext = new MessageContext(
+ message.MessageId,
+ message.GetHeaders(),
+ message.Body,
+ transportTransaction,
+ ReceiveAddress,
+ contextBag);
+ return messageContext;
+ }
- static AzureServiceBusTransportTransaction CreateTransaction(string messagePartitionKey, ServiceBusClient serviceBusClient) =>
- new(serviceBusClient, messagePartitionKey, new TransactionOptions
- {
- IsolationLevel = IsolationLevel.Serializable,
- Timeout = TransactionManager.MaximumTimeout
- });
+ static async Task SafeCompleteMessageAsync(ServiceBusMessageActions messageActions, ServiceBusReceivedMessage message, AzureServiceBusTransportTransaction azureServiceBusTransaction, CancellationToken cancellationToken)
+ {
+ using var scope = azureServiceBusTransaction.ToTransactionScope();
+ await messageActions.CompleteMessageAsync(message, cancellationToken).ConfigureAwait(false);
+ scope.Complete();
+ }
- public Task StartReceive(CancellationToken cancellationToken = default) => Task.CompletedTask;
+ static AzureServiceBusTransportTransaction CreateTransaction(string messagePartitionKey, ServiceBusClient serviceBusClient) =>
+ new(serviceBusClient, messagePartitionKey, new TransactionOptions
+ {
+ IsolationLevel = IsolationLevel.Serializable,
+ Timeout = TransactionManager.MaximumTimeout
+ });
- // No-op because the rate at which Azure Functions pushes messages to the pipeline can't be controlled.
- public Task ChangeConcurrency(PushRuntimeSettings limitations, CancellationToken cancellationToken = default) => Task.CompletedTask;
+ public Task StartReceive(CancellationToken cancellationToken = default) => Task.CompletedTask;
- public Task StopReceive(CancellationToken cancellationToken = default) => Task.CompletedTask;
- public ISubscriptionManager Subscriptions => baseTransportReceiver.Subscriptions;
- public string Id => baseTransportReceiver.Id;
+ // No-op because the rate at which Azure Functions pushes messages to the pipeline can't be controlled.
+ public Task ChangeConcurrency(PushRuntimeSettings limitations, CancellationToken cancellationToken = default) => Task.CompletedTask;
- public string ReceiveAddress => baseTransportReceiver.ReceiveAddress;
+ public Task StopReceive(CancellationToken cancellationToken = default) => Task.CompletedTask;
+ public ISubscriptionManager Subscriptions => baseTransportReceiver.Subscriptions;
+ public string Id => baseTransportReceiver.Id;
- readonly IMessageReceiver baseTransportReceiver;
- OnMessage onMessage;
- OnError onError;
- }
+ public string ReceiveAddress => baseTransportReceiver.ReceiveAddress;
+
+ readonly IMessageReceiver baseTransportReceiver;
+ OnMessage onMessage;
+ OnError onError;
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/SendOnlyMessageProcessor.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/SendOnlyMessageProcessor.cs
index 654b4e25..69e1f685 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/SendOnlyMessageProcessor.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/SendOnlyMessageProcessor.cs
@@ -1,27 +1,26 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus;
- using Microsoft.Azure.WebJobs.ServiceBus;
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.WebJobs.ServiceBus;
- class SendOnlyMessageProcessor : IMessageProcessor
- {
- public Task ProcessNonAtomic(
- ServiceBusReceivedMessage message,
- CancellationToken cancellationToken = default)
- => throw new InvalidOperationException(
- $"This endpoint cannot process messages because it is configured in send-only mode. Remove the '{nameof(EndpointConfiguration)}.{nameof(EndpointConfiguration.SendOnly)}' configuration.'"
- );
+class SendOnlyMessageProcessor : IMessageProcessor
+{
+ public Task ProcessNonAtomic(
+ ServiceBusReceivedMessage message,
+ CancellationToken cancellationToken = default)
+ => throw new InvalidOperationException(
+ $"This endpoint cannot process messages because it is configured in send-only mode. Remove the '{nameof(EndpointConfiguration)}.{nameof(EndpointConfiguration.SendOnly)}' configuration.'"
+ );
- public Task ProcessAtomic(
- ServiceBusReceivedMessage message,
- ServiceBusClient serviceBusClient,
- ServiceBusMessageActions messageActions,
- CancellationToken cancellationToken = default)
- => throw new InvalidOperationException(
- $"This endpoint cannot process messages because it is configured in send-only mode. Remove the '{nameof(EndpointConfiguration)}.{nameof(EndpointConfiguration.SendOnly)}' configuration.'"
- );
- }
+ public Task ProcessAtomic(
+ ServiceBusReceivedMessage message,
+ ServiceBusClient serviceBusClient,
+ ServiceBusMessageActions messageActions,
+ CancellationToken cancellationToken = default)
+ => throw new InvalidOperationException(
+ $"This endpoint cannot process messages because it is configured in send-only mode. Remove the '{nameof(EndpointConfiguration)}.{nameof(EndpointConfiguration.SendOnly)}' configuration.'"
+ );
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransport.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransport.cs
index 92ada331..c4ca1b93 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransport.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransport.cs
@@ -1,114 +1,113 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Core;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Transport;
+
+class ServerlessTransport(AzureServiceBusTransport transport, string connectionString, string connectionName) : TransportDefinition(
+ TransportTransactionMode.ReceiveOnly,
+ transport.SupportsDelayedDelivery,
+ transport.SupportsPublishSubscribe,
+ transport.SupportsTTBR)
{
- using System;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Core;
- using Microsoft.Extensions.Azure;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Transport;
-
- class ServerlessTransport(AzureServiceBusTransport transport, string connectionString, string connectionName) : TransportDefinition(
- TransportTransactionMode.ReceiveOnly,
- transport.SupportsDelayedDelivery,
- transport.SupportsPublishSubscribe,
- transport.SupportsTTBR)
- {
- // HINT: This constant is defined in NServiceBus but is not exposed
- const string MainReceiverId = "Main";
- const string SendOnlyConfigKey = "Endpoint.SendOnly";
+ // HINT: This constant is defined in NServiceBus but is not exposed
+ const string MainReceiverId = "Main";
+ const string SendOnlyConfigKey = "Endpoint.SendOnly";
- public IMessageProcessor MessageProcessor { get; private set; }
+ public IMessageProcessor MessageProcessor { get; private set; }
- public IServiceProvider ServiceProvider { get; set; }
+ public IServiceProvider ServiceProvider { get; set; }
- public override async Task Initialize(HostSettings hostSettings, ReceiveSettings[] receivers,
- string[] sendingAddresses,
- CancellationToken cancellationToken = default)
- {
- var configuredTransport = ConfigureTransportConnection(connectionString, connectionName, ServiceProvider.GetRequiredService(), transport,
- ServiceProvider.GetRequiredService());
+ public override async Task Initialize(HostSettings hostSettings, ReceiveSettings[] receivers,
+ string[] sendingAddresses,
+ CancellationToken cancellationToken = default)
+ {
+ var configuredTransport = ConfigureTransportConnection(connectionString, connectionName, ServiceProvider.GetRequiredService(), transport,
+ ServiceProvider.GetRequiredService());
- var baseTransportInfrastructure = await configuredTransport.Initialize(
- hostSettings,
- receivers,
- sendingAddresses,
- cancellationToken)
- .ConfigureAwait(false);
+ var baseTransportInfrastructure = await configuredTransport.Initialize(
+ hostSettings,
+ receivers,
+ sendingAddresses,
+ cancellationToken)
+ .ConfigureAwait(false);
- var serverlessTransportInfrastructure = new ServerlessTransportInfrastructure(baseTransportInfrastructure);
+ var serverlessTransportInfrastructure = new ServerlessTransportInfrastructure(baseTransportInfrastructure);
- var isSendOnly = hostSettings.CoreSettings.GetOrDefault(SendOnlyConfigKey);
+ var isSendOnly = hostSettings.CoreSettings.GetOrDefault(SendOnlyConfigKey);
- MessageProcessor = isSendOnly
- ? new SendOnlyMessageProcessor() // send-only endpoint
- : (IMessageProcessor)serverlessTransportInfrastructure.Receivers[MainReceiverId];
+ MessageProcessor = isSendOnly
+ ? new SendOnlyMessageProcessor() // send-only endpoint
+ : (IMessageProcessor)serverlessTransportInfrastructure.Receivers[MainReceiverId];
- return serverlessTransportInfrastructure;
- }
+ return serverlessTransportInfrastructure;
+ }
- public override IReadOnlyCollection GetSupportedTransactionModes() =>
- supportedTransactionModes;
+ public override IReadOnlyCollection GetSupportedTransactionModes() =>
+ supportedTransactionModes;
- static AzureServiceBusTransport ConfigureTransportConnection(string connectionString, string connectionName, IConfiguration configuration,
- AzureServiceBusTransport transport, AzureComponentFactory azureComponentFactory)
+ static AzureServiceBusTransport ConfigureTransportConnection(string connectionString, string connectionName, IConfiguration configuration,
+ AzureServiceBusTransport transport, AzureComponentFactory azureComponentFactory)
+ {
+ if (connectionString != null)
+ {
+ GetConnectionStringRef(transport) = connectionString;
+ }
+ else
{
- if (connectionString != null)
+ var serviceBusConnectionName = string.IsNullOrWhiteSpace(connectionName) ? DefaultServiceBusConnectionName : connectionName;
+ IConfigurationSection connectionSection = configuration.GetSection(serviceBusConnectionName);
+ if (!connectionSection.Exists())
{
- GetConnectionStringRef(transport) = connectionString;
+ throw new Exception($"Azure Service Bus connection string/section has not been configured. Specify a connection string through IConfiguration, an environment variable named {serviceBusConnectionName} or passing it to `UseNServiceBus(ENDPOINTNAME,CONNECTIONSTRING)`");
+ }
+
+ if (!string.IsNullOrWhiteSpace(connectionSection.Value))
+ {
+ GetConnectionStringRef(transport) = connectionSection.Value;
}
else
{
- var serviceBusConnectionName = string.IsNullOrWhiteSpace(connectionName) ? DefaultServiceBusConnectionName : connectionName;
- IConfigurationSection connectionSection = configuration.GetSection(serviceBusConnectionName);
- if (!connectionSection.Exists())
+ string fullyQualifiedNamespace = connectionSection["fullyQualifiedNamespace"];
+ if (string.IsNullOrWhiteSpace(fullyQualifiedNamespace))
{
- throw new Exception($"Azure Service Bus connection string/section has not been configured. Specify a connection string through IConfiguration, an environment variable named {serviceBusConnectionName} or passing it to `UseNServiceBus(ENDPOINTNAME,CONNECTIONSTRING)`");
+ throw new Exception("Connection should have an 'fullyQualifiedNamespace' property or be a string representing a connection string.");
}
- if (!string.IsNullOrWhiteSpace(connectionSection.Value))
- {
- GetConnectionStringRef(transport) = connectionSection.Value;
- }
- else
- {
- string fullyQualifiedNamespace = connectionSection["fullyQualifiedNamespace"];
- if (string.IsNullOrWhiteSpace(fullyQualifiedNamespace))
- {
- throw new Exception("Connection should have an 'fullyQualifiedNamespace' property or be a string representing a connection string.");
- }
-
- var credential = azureComponentFactory.CreateTokenCredential(connectionSection);
- GetFullyQualifiedNamespaceRef(transport) = fullyQualifiedNamespace;
- GetTokenCredentialRef(transport) = credential;
- }
+ var credential = azureComponentFactory.CreateTokenCredential(connectionSection);
+ GetFullyQualifiedNamespaceRef(transport) = fullyQualifiedNamespace;
+ GetTokenCredentialRef(transport) = credential;
}
-
- return transport;
}
- // As a temporary workaround we are accessing the properties of the AzureServiceBusTransport using UnsafeAccessor
- // This is another blocker to AoT but we are already using the execution assembly in the code base anyway
- // Furthermore this allows us to still comply with initializing the transport as late as possible without having to
- // expose the properties on the transport itself which would pollute the public API for not much added value.
- [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
- static extern ref string GetConnectionStringRef(AzureServiceBusTransport transport);
+ return transport;
+ }
- [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
- static extern ref string GetFullyQualifiedNamespaceRef(AzureServiceBusTransport transport);
+ // As a temporary workaround we are accessing the properties of the AzureServiceBusTransport using UnsafeAccessor
+ // This is another blocker to AoT but we are already using the execution assembly in the code base anyway
+ // Furthermore this allows us to still comply with initializing the transport as late as possible without having to
+ // expose the properties on the transport itself which would pollute the public API for not much added value.
+ [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
+ static extern ref string GetConnectionStringRef(AzureServiceBusTransport transport);
- [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
- static extern ref TokenCredential GetTokenCredentialRef(AzureServiceBusTransport transport);
+ [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
+ static extern ref string GetFullyQualifiedNamespaceRef(AzureServiceBusTransport transport);
- internal const string DefaultServiceBusConnectionName = "AzureWebJobsServiceBus";
+ [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "k__BackingField")]
+ static extern ref TokenCredential GetTokenCredentialRef(AzureServiceBusTransport transport);
- readonly TransportTransactionMode[] supportedTransactionModes =
- [
- TransportTransactionMode.ReceiveOnly,
- TransportTransactionMode.SendsAtomicWithReceive
- ];
- }
+ internal const string DefaultServiceBusConnectionName = "AzureWebJobsServiceBus";
+
+ readonly TransportTransactionMode[] supportedTransactionModes =
+ [
+ TransportTransactionMode.ReceiveOnly,
+ TransportTransactionMode.SendsAtomicWithReceive
+ ];
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransportInfrastructure.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransportInfrastructure.cs
index d2c6fdb4..36e029bd 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransportInfrastructure.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/Serverless/TransportWrapper/ServerlessTransportInfrastructure.cs
@@ -1,27 +1,26 @@
-namespace NServiceBus.AzureFunctions.InProcess.ServiceBus
-{
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using Transport;
+namespace NServiceBus.AzureFunctions.InProcess.ServiceBus;
- class ServerlessTransportInfrastructure : TransportInfrastructure
- {
- readonly TransportInfrastructure baseTransportInfrastructure;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Transport;
- public ServerlessTransportInfrastructure(TransportInfrastructure baseTransportInfrastructure)
- {
- this.baseTransportInfrastructure = baseTransportInfrastructure;
- Dispatcher = baseTransportInfrastructure.Dispatcher;
- Receivers = baseTransportInfrastructure.Receivers.ToDictionary(
- r => r.Key,
- r => (IMessageReceiver)new PipelineInvokingMessageProcessor(r.Value)
- );
- }
+class ServerlessTransportInfrastructure : TransportInfrastructure
+{
+ readonly TransportInfrastructure baseTransportInfrastructure;
- public override Task Shutdown(CancellationToken cancellationToken = default)
- => baseTransportInfrastructure.Shutdown(cancellationToken);
- public override string ToTransportAddress(QueueAddress address)
- => baseTransportInfrastructure.ToTransportAddress(address);
+ public ServerlessTransportInfrastructure(TransportInfrastructure baseTransportInfrastructure)
+ {
+ this.baseTransportInfrastructure = baseTransportInfrastructure;
+ Dispatcher = baseTransportInfrastructure.Dispatcher;
+ Receivers = baseTransportInfrastructure.Receivers.ToDictionary(
+ r => r.Key,
+ r => (IMessageReceiver)new PipelineInvokingMessageProcessor(r.Value)
+ );
}
+
+ public override Task Shutdown(CancellationToken cancellationToken = default)
+ => baseTransportInfrastructure.Shutdown(cancellationToken);
+ public override string ToTransportAddress(QueueAddress address)
+ => baseTransportInfrastructure.ToTransportAddress(address);
}
\ No newline at end of file
diff --git a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/ServiceBusTriggeredEndpointConfiguration.cs b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/ServiceBusTriggeredEndpointConfiguration.cs
index fae5acb7..30b6ea9c 100644
--- a/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/ServiceBusTriggeredEndpointConfiguration.cs
+++ b/src/NServiceBus.AzureFunctions.InProcess.ServiceBus/ServiceBusTriggeredEndpointConfiguration.cs
@@ -1,135 +1,134 @@
-namespace NServiceBus
+namespace NServiceBus;
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using AzureFunctions.InProcess.ServiceBus;
+using AzureFunctions.InProcess.ServiceBus.Serverless;
+using Configuration.AdvancedExtensibility;
+using Logging;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Serialization;
+using Settings;
+using Transport.AzureServiceBus;
+
+///
+/// Represents a serverless NServiceBus endpoint.
+///
+public partial class ServiceBusTriggeredEndpointConfiguration
{
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using AzureFunctions.InProcess.ServiceBus;
- using AzureFunctions.InProcess.ServiceBus.Serverless;
- using Configuration.AdvancedExtensibility;
- using Logging;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Serialization;
- using Settings;
- using Transport.AzureServiceBus;
+ static ServiceBusTriggeredEndpointConfiguration() => LogManager.UseFactory(FunctionsLoggerFactory.Instance);
+
+ // Disable diagnostics by default as it will fail to create the diagnostics file in the default path.
+ Func customDiagnosticsWriter = (_, __) => Task.CompletedTask;
+
+ ///
+ /// The Azure Service Bus Transport configuration.
+ ///
+ public AzureServiceBusTransport Transport { get; }
+
+ ///
+ /// The routing configuration.
+ ///
+ public RoutingSettings Routing { get; }
+
+ ///
+ /// Gives access to the underlying endpoint configuration for advanced configuration options.
+ ///
+ public EndpointConfiguration AdvancedConfiguration { get; }
///
- /// Represents a serverless NServiceBus endpoint.
+ /// Creates a serverless NServiceBus endpoint.
///
- public partial class ServiceBusTriggeredEndpointConfiguration
+ internal ServiceBusTriggeredEndpointConfiguration(string endpointName, IConfiguration configuration, string connectionString = default, string connectionName = default)
{
- static ServiceBusTriggeredEndpointConfiguration() => LogManager.UseFactory(FunctionsLoggerFactory.Instance);
-
- // Disable diagnostics by default as it will fail to create the diagnostics file in the default path.
- Func customDiagnosticsWriter = (_, __) => Task.CompletedTask;
-
- ///
- /// The Azure Service Bus Transport configuration.
- ///
- public AzureServiceBusTransport Transport { get; }
-
- ///
- /// The routing configuration.
- ///
- public RoutingSettings Routing { get; }
-
- ///
- /// Gives access to the underlying endpoint configuration for advanced configuration options.
- ///
- public EndpointConfiguration AdvancedConfiguration { get; }
-
- ///
- /// Creates a serverless NServiceBus endpoint.
- ///
- internal ServiceBusTriggeredEndpointConfiguration(string endpointName, IConfiguration configuration, string connectionString = default, string connectionName = default)
- {
- this.connectionString = connectionString;
- this.connectionName = connectionName;
- var endpointConfiguration = new EndpointConfiguration(endpointName);
-
- var recoverability = endpointConfiguration.Recoverability();
- recoverability.Immediate(settings => settings.NumberOfRetries(5));
- recoverability.Delayed(settings => settings.NumberOfRetries(3));
- recoverabilityPolicy.SendFailedMessagesToErrorQueue = true;
- recoverability.CustomPolicy(recoverabilityPolicy.Invoke);
-
- endpointConfiguration.Pipeline.Register(b => new OutboxProcessingValidationBehavior(b.GetRequiredService()),
- "Validates the API calls preventing calling ProcessAtomic if the Outbox is enabled.");
-
- endpointConfiguration.CustomDiagnosticsWriter(customDiagnosticsWriter);
-
- // 'WEBSITE_SITE_NAME' represents an Azure Function App and the environment variable is set when hosting the function in Azure.
- var functionAppName = configuration?.GetValue("WEBSITE_SITE_NAME") ?? Environment.MachineName;
- endpointConfiguration.UniquelyIdentifyRunningInstance()
- .UsingCustomDisplayName(functionAppName)
- .UsingCustomIdentifier(DeterministicGuid.Create(functionAppName));
-
- var licenseText = configuration?.GetValue("NSERVICEBUS_LICENSE");
- if (!string.IsNullOrWhiteSpace(licenseText))
- {
- endpointConfiguration.License(licenseText);
- }
-
- TopicTopology topicTopology = TopicTopology.Default;
- var topologyOptionsSection = configuration?.GetSection("AzureServiceBus:TopologyOptions");
- if (topologyOptionsSection.Exists())
- {
- topicTopology = TopicTopology.FromOptions(topologyOptionsSection.Get());
- }
- // Migration options take precedence over topology options. We are not doing additional checks here for now.
- var migrationOptionsSection = configuration?.GetSection("AzureServiceBus:MigrationTopologyOptions");
- if (migrationOptionsSection.Exists())
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- topicTopology = TopicTopology.FromOptions(migrationOptionsSection.Get());
-#pragma warning restore CS0618 // Type or member is obsolete
- }
+ this.connectionString = connectionString;
+ this.connectionName = connectionName;
+ var endpointConfiguration = new EndpointConfiguration(endpointName);
- Transport = new AzureServiceBusTransport("TransportWillBeInitializedCorrectlyLater", topicTopology)
- {
- // This is required for the Outbox validation to work in NServiceBus 8. It does not affect the actual consistency mode because it is controlled by the functions
- // endpoint API (calling ProcessAtomic vs ProcessNonAtomic).
- TransportTransactionMode = TransportTransactionMode.ReceiveOnly
- };
- Routing = new RoutingSettings(endpointConfiguration.GetSettings());
+ var recoverability = endpointConfiguration.Recoverability();
+ recoverability.Immediate(settings => settings.NumberOfRetries(5));
+ recoverability.Delayed(settings => settings.NumberOfRetries(3));
+ recoverabilityPolicy.SendFailedMessagesToErrorQueue = true;
+ recoverability.CustomPolicy(recoverabilityPolicy.Invoke);
- endpointConfiguration.UseSerialization();
+ endpointConfiguration.Pipeline.Register(b => new OutboxProcessingValidationBehavior(b.GetRequiredService()),
+ "Validates the API calls preventing calling ProcessAtomic if the Outbox is enabled.");
- AdvancedConfiguration = endpointConfiguration;
- }
+ endpointConfiguration.CustomDiagnosticsWriter(customDiagnosticsWriter);
+
+ // 'WEBSITE_SITE_NAME' represents an Azure Function App and the environment variable is set when hosting the function in Azure.
+ var functionAppName = configuration?.GetValue("WEBSITE_SITE_NAME") ?? Environment.MachineName;
+ endpointConfiguration.UniquelyIdentifyRunningInstance()
+ .UsingCustomDisplayName(functionAppName)
+ .UsingCustomIdentifier(DeterministicGuid.Create(functionAppName));
- internal ServerlessTransport InitializeTransport()
+ var licenseText = configuration?.GetValue("NSERVICEBUS_LICENSE");
+ if (!string.IsNullOrWhiteSpace(licenseText))
{
- var serverlessTransport = new ServerlessTransport(Transport, connectionString, connectionName);
- AdvancedConfiguration.UseTransport(serverlessTransport);
- return serverlessTransport;
+ endpointConfiguration.License(licenseText);
}
- ///
- /// Define the serializer to be used.
- ///
- public SerializationExtensions UseSerialization() where T : SerializationDefinition, new()
+ TopicTopology topicTopology = TopicTopology.Default;
+ var topologyOptionsSection = configuration?.GetSection("AzureServiceBus:TopologyOptions");
+ if (topologyOptionsSection.Exists())
{
- return AdvancedConfiguration.UseSerialization();
+ topicTopology = TopicTopology.FromOptions(topologyOptionsSection.Get());
+ }
+ // Migration options take precedence over topology options. We are not doing additional checks here for now.
+ var migrationOptionsSection = configuration?.GetSection("AzureServiceBus:MigrationTopologyOptions");
+ if (migrationOptionsSection.Exists())
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ topicTopology = TopicTopology.FromOptions(migrationOptionsSection.Get());
+#pragma warning restore CS0618 // Type or member is obsolete
}
- ///
- /// Disables moving messages to the error queue even if an error queue name is configured.
- ///
- public void DoNotSendMessagesToErrorQueue() => recoverabilityPolicy.SendFailedMessagesToErrorQueue = false;
-
- ///
- /// Logs endpoint diagnostics information to the log. Diagnostics are logged on level .
- ///
- public void LogDiagnostics() =>
- customDiagnosticsWriter = (diagnostics, cancellationToken) =>
- {
- LogManager.GetLogger("StartupDiagnostics").Info(diagnostics);
- return Task.CompletedTask;
- };
-
- readonly ServerlessRecoverabilityPolicy recoverabilityPolicy = new ServerlessRecoverabilityPolicy();
- readonly string connectionString;
- readonly string connectionName;
+ Transport = new AzureServiceBusTransport("TransportWillBeInitializedCorrectlyLater", topicTopology)
+ {
+ // This is required for the Outbox validation to work in NServiceBus 8. It does not affect the actual consistency mode because it is controlled by the functions
+ // endpoint API (calling ProcessAtomic vs ProcessNonAtomic).
+ TransportTransactionMode = TransportTransactionMode.ReceiveOnly
+ };
+ Routing = new RoutingSettings(endpointConfiguration.GetSettings());
+
+ endpointConfiguration.UseSerialization();
+
+ AdvancedConfiguration = endpointConfiguration;
+ }
+
+ internal ServerlessTransport InitializeTransport()
+ {
+ var serverlessTransport = new ServerlessTransport(Transport, connectionString, connectionName);
+ AdvancedConfiguration.UseTransport(serverlessTransport);
+ return serverlessTransport;
+ }
+
+ ///
+ /// Define the serializer to be used.
+ ///
+ public SerializationExtensions UseSerialization() where T : SerializationDefinition, new()
+ {
+ return AdvancedConfiguration.UseSerialization();
}
-}
+
+ ///
+ /// Disables moving messages to the error queue even if an error queue name is configured.
+ ///
+ public void DoNotSendMessagesToErrorQueue() => recoverabilityPolicy.SendFailedMessagesToErrorQueue = false;
+
+ ///
+ /// Logs endpoint diagnostics information to the log. Diagnostics are logged on level .
+ ///
+ public void LogDiagnostics() =>
+ customDiagnosticsWriter = (diagnostics, cancellationToken) =>
+ {
+ LogManager.GetLogger("StartupDiagnostics").Info(diagnostics);
+ return Task.CompletedTask;
+ };
+
+ readonly ServerlessRecoverabilityPolicy recoverabilityPolicy = new ServerlessRecoverabilityPolicy();
+ readonly string connectionString;
+ readonly string connectionName;
+}
\ No newline at end of file
diff --git a/src/ServiceBus.AcceptanceTests/DefaultEndpoint.cs b/src/ServiceBus.AcceptanceTests/DefaultEndpoint.cs
index 42e8b343..a713cb39 100644
--- a/src/ServiceBus.AcceptanceTests/DefaultEndpoint.cs
+++ b/src/ServiceBus.AcceptanceTests/DefaultEndpoint.cs
@@ -1,57 +1,56 @@
-namespace ServiceBus.Tests
+namespace ServiceBus.Tests;
+
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using NServiceBus;
+using NServiceBus.AcceptanceTesting.Customization;
+using NServiceBus.AcceptanceTesting.Support;
+using NServiceBus.AzureFunctions.InProcess.ServiceBus;
+
+class DefaultEndpoint : IEndpointSetupTemplate
{
- using System;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.Extensions.DependencyInjection;
- using NServiceBus;
- using NServiceBus.AcceptanceTesting.Customization;
- using NServiceBus.AcceptanceTesting.Support;
- using NServiceBus.AzureFunctions.InProcess.ServiceBus;
-
- class DefaultEndpoint : IEndpointSetupTemplate
+ public async Task GetConfiguration(
+ RunDescriptor runDescriptor,
+ EndpointCustomizationConfiguration endpointConfiguration,
+ Func configurationBuilderCustomization)
{
- public async Task GetConfiguration(
- RunDescriptor runDescriptor,
- EndpointCustomizationConfiguration endpointConfiguration,
- Func configurationBuilderCustomization)
- {
- var configuration = new EndpointConfiguration(endpointConfiguration.EndpointName);
+ var configuration = new EndpointConfiguration(endpointConfiguration.EndpointName);
- configuration.TypesToIncludeInScan(endpointConfiguration.GetTypesScopedByTestClass());
- configuration.EnableInstallers();
+ configuration.TypesToIncludeInScan(endpointConfiguration.GetTypesScopedByTestClass());
+ configuration.EnableInstallers();
- configuration.RegisterComponents(c => c
- .AddSingleton(runDescriptor.ScenarioContext.GetType(), runDescriptor.ScenarioContext));
+ configuration.RegisterComponents(c => c
+ .AddSingleton(runDescriptor.ScenarioContext.GetType(), runDescriptor.ScenarioContext));
- var recoverability = configuration.Recoverability();
- recoverability.Delayed(delayed => delayed.NumberOfRetries(0));
- recoverability.Immediate(immediate => immediate.NumberOfRetries(0));
- configuration.SendFailedMessagesTo("error");
+ var recoverability = configuration.Recoverability();
+ recoverability.Delayed(delayed => delayed.NumberOfRetries(0));
+ recoverability.Immediate(immediate => immediate.NumberOfRetries(0));
+ configuration.SendFailedMessagesTo("error");
- configuration.EnforcePublisherMetadataRegistration(endpointConfiguration.EndpointName, endpointConfiguration.PublisherMetadata);
+ configuration.EnforcePublisherMetadataRegistration(endpointConfiguration.EndpointName, endpointConfiguration.PublisherMetadata);
- var connectionString =
- Environment.GetEnvironmentVariable(ServerlessTransport.DefaultServiceBusConnectionName);
+ var connectionString =
+ Environment.GetEnvironmentVariable(ServerlessTransport.DefaultServiceBusConnectionName);
- var topology = TopicTopology.Default;
- topology.OverrideSubscriptionNameFor(endpointConfiguration.EndpointName, endpointConfiguration.EndpointName.Shorten());
- foreach (var eventType in endpointConfiguration.PublisherMetadata.Publishers.SelectMany(p => p.Events))
- {
- topology.PublishTo(eventType, eventType.ToTopicName());
- topology.SubscribeTo(eventType, eventType.ToTopicName());
- }
- var azureServiceBusTransport = new AzureServiceBusTransport(connectionString, topology);
+ var topology = TopicTopology.Default;
+ topology.OverrideSubscriptionNameFor(endpointConfiguration.EndpointName, endpointConfiguration.EndpointName.Shorten());
+ foreach (var eventType in endpointConfiguration.PublisherMetadata.Publishers.SelectMany(p => p.Events))
+ {
+ topology.PublishTo(eventType, eventType.ToTopicName());
+ topology.SubscribeTo(eventType, eventType.ToTopicName());
+ }
+ var azureServiceBusTransport = new AzureServiceBusTransport(connectionString, topology);
- _ = configuration.UseTransport(azureServiceBusTransport);
+ _ = configuration.UseTransport(azureServiceBusTransport);
- configuration.Pipeline.Register("TestIndependenceBehavior", b => new TestIndependenceSkipBehavior(runDescriptor.ScenarioContext), "Skips messages not created during the current test.");
+ configuration.Pipeline.Register("TestIndependenceBehavior", b => new TestIndependenceSkipBehavior(runDescriptor.ScenarioContext), "Skips messages not created during the current test.");
- configuration.UseSerialization();
+ configuration.UseSerialization();
- await configurationBuilderCustomization(configuration);
+ await configurationBuilderCustomization(configuration);
- return configuration;
- }
+ return configuration;
}
}
\ No newline at end of file
diff --git a/src/ServiceBus.AcceptanceTests/Extensions.cs b/src/ServiceBus.AcceptanceTests/Extensions.cs
index 7a5529c2..b9befcb3 100644
--- a/src/ServiceBus.AcceptanceTests/Extensions.cs
+++ b/src/ServiceBus.AcceptanceTests/Extensions.cs
@@ -1,55 +1,54 @@
-namespace ServiceBus.Tests
+namespace ServiceBus.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using NServiceBus.AcceptanceTesting.Support;
+using NServiceBus.Hosting.Helpers;
+
+public static class Extensions
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using NServiceBus.AcceptanceTesting.Support;
- using NServiceBus.Hosting.Helpers;
-
- public static class Extensions
+ public static IEnumerable GetTypesScopedByTestClass(this EndpointCustomizationConfiguration endpointConfiguration)
{
- public static IEnumerable GetTypesScopedByTestClass(this EndpointCustomizationConfiguration endpointConfiguration)
- {
- var types = endpointConfiguration.BuilderType.GetTypesScopedByTestClass();
- types = types.Union(endpointConfiguration.TypesToInclude);
- return types.Where(t => !endpointConfiguration.TypesToExclude.Contains(t)).ToList();
- }
+ var types = endpointConfiguration.BuilderType.GetTypesScopedByTestClass();
+ types = types.Union(endpointConfiguration.TypesToInclude);
+ return types.Where(t => !endpointConfiguration.TypesToExclude.Contains(t)).ToList();
+ }
- public static IEnumerable GetTypesScopedByTestClass(this Type componentType)
- {
- var assemblies = new AssemblyScanner().GetScannableAssemblies();
+ public static IEnumerable GetTypesScopedByTestClass(this Type componentType)
+ {
+ var assemblies = new AssemblyScanner().GetScannableAssemblies();
- var assembliesToScan = assemblies.Assemblies
- //exclude acceptance tests by default
- .Where(a => a != Assembly.GetExecutingAssembly()).ToList();
- var types = assembliesToScan
- .SelectMany(a => a.GetTypes());
+ var assembliesToScan = assemblies.Assemblies
+ //exclude acceptance tests by default
+ .Where(a => a != Assembly.GetExecutingAssembly()).ToList();
+ var types = assembliesToScan
+ .SelectMany(a => a.GetTypes());
- types = types.Union(GetNestedTypeRecursive(componentType.DeclaringType, componentType));
+ types = types.Union(GetNestedTypeRecursive(componentType.DeclaringType, componentType));
- return types.ToList();
+ return types.ToList();
+ }
+
+ static IEnumerable GetNestedTypeRecursive(Type rootType, Type builderType)
+ {
+ if (rootType == null)
+ {
+ throw new InvalidOperationException("Make sure you nest the endpoint infrastructure inside the TestFixture as nested classes");
+ }
+
+ yield return rootType;
+
+ if (typeof(IEndpointConfigurationFactory).IsAssignableFrom(rootType) && rootType != builderType)
+ {
+ yield break;
}
- static IEnumerable GetNestedTypeRecursive(Type rootType, Type builderType)
+ foreach (var nestedType in rootType.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SelectMany(t => GetNestedTypeRecursive(t, builderType)))
{
- if (rootType == null)
- {
- throw new InvalidOperationException("Make sure you nest the endpoint infrastructure inside the TestFixture as nested classes");
- }
-
- yield return rootType;
-
- if (typeof(IEndpointConfigurationFactory).IsAssignableFrom(rootType) && rootType != builderType)
- {
- yield break;
- }
-
- foreach (var nestedType in rootType.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SelectMany(t => GetNestedTypeRecursive(t, builderType)))
- {
- yield return nestedType;
- }
+ yield return nestedType;
}
}
}
\ No newline at end of file
diff --git a/src/ServiceBus.AcceptanceTests/FunctionEndpointComponent.cs b/src/ServiceBus.AcceptanceTests/FunctionEndpointComponent.cs
index a09c9a96..ac0f8ba7 100644
--- a/src/ServiceBus.AcceptanceTests/FunctionEndpointComponent.cs
+++ b/src/ServiceBus.AcceptanceTests/FunctionEndpointComponent.cs
@@ -1,230 +1,245 @@
-namespace ServiceBus.Tests
+namespace ServiceBus.Tests;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Azure.Messaging.ServiceBus.Administration;
+using Microsoft.Azure.Functions.Extensions.DependencyInjection;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.ServiceBus;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using NServiceBus;
+using NServiceBus.AcceptanceTesting;
+using NServiceBus.AcceptanceTesting.Customization;
+using NServiceBus.AcceptanceTesting.Support;
+using NServiceBus.AzureFunctions.InProcess.ServiceBus;
+using NServiceBus.MessageMutator;
+using NServiceBus.Transport.AzureServiceBus;
+using Conventions = NServiceBus.AcceptanceTesting.Customization.Conventions;
+using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
+
+abstract class FunctionEndpointComponent : IComponentBehavior
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using Azure.Messaging.ServiceBus;
- using Azure.Messaging.ServiceBus.Administration;
- using Microsoft.Azure.Functions.Extensions.DependencyInjection;
- using Microsoft.Azure.WebJobs;
- using Microsoft.Azure.WebJobs.ServiceBus;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using NServiceBus;
- using NServiceBus.AcceptanceTesting;
- using NServiceBus.AcceptanceTesting.Customization;
- using NServiceBus.AcceptanceTesting.Support;
- using NServiceBus.AzureFunctions.InProcess.ServiceBus;
- using NServiceBus.MessageMutator;
- using NServiceBus.Transport.AzureServiceBus;
- using Conventions = NServiceBus.AcceptanceTesting.Customization.Conventions;
- using ExecutionContext = Microsoft.Azure.WebJobs.ExecutionContext;
-
- abstract class FunctionEndpointComponent : IComponentBehavior
- {
- protected FunctionEndpointComponent(TransportTransactionMode transactionMode = TransportTransactionMode.ReceiveOnly) =>
- sendsAtomicWithReceive = transactionMode switch
- {
- TransportTransactionMode.SendsAtomicWithReceive => true,
- TransportTransactionMode.ReceiveOnly => false,
- TransportTransactionMode.None => throw new Exception("Unsupported transaction mode " + transactionMode),
- TransportTransactionMode.TransactionScope => throw new Exception("Unsupported transaction mode " + transactionMode),
- _ => throw new Exception("Unsupported transaction mode " + transactionMode),
- };
-
- public Task CreateRunner(RunDescriptor runDescriptor) =>
- Task.FromResult(
- new FunctionRunner(
- Messages,
- CustomizeConfiguration,
- HostConfigurationCustomization,
- OnStartCore,
- runDescriptor.ScenarioContext,
- PublisherMetadata,
- GetType(),
- DoNotFailOnErrorMessages,
- TypesScopedByTestClassAssemblyScanningEnabled,
- sendsAtomicWithReceive,
- ServiceBusMessageActionsFactory));
-
- protected IList