From 586dd6a65269fb4b21597987d59bb3aeb03b7bb6 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 18 Jul 2025 00:04:25 -0600 Subject: [PATCH 1/2] Add baseline ABSDataBus_7 copy from ABSDataBus_6 --- .../AzureDataBusCleanupWithFunctions.sln | 30 +++++ .../DataBusBlobCleanupFunctions.csproj | 32 +++++ .../DataBusBlobCleanupFunctions.sln | 25 ++++ .../DataBusBlobCreated.cs | 46 +++++++ .../DataBusBlobData.cs | 6 + .../DataBusBlobTimeoutCalculator.cs | 116 ++++++++++++++++++ .../DataBusCleanupOrchestrator.cs | 36 ++++++ .../DataBusOrchestrateExistingBlobs.cs | 76 ++++++++++++ .../DeleteBlobFunction.cs | 20 +++ .../DataBusBlobCleanupFunctions/Program.cs | 20 +++ .../Properties/launchSettings.json | 9 ++ .../Properties/serviceDependencies.json | 19 +++ .../Properties/serviceDependencies.local.json | 20 +++ .../DataBusBlobCleanupFunctions/host.json | 12 ++ .../local.settings.json | 8 ++ .../SenderAndReceiver/InputLoopService.cs | 48 ++++++++ .../MessageWithLargePayload.cs | 10 ++ .../MessageWithLargePayloadHandler.cs | 15 +++ .../ABSDataBus_7/SenderAndReceiver/Program.cs | 24 ++++ .../SenderAndReceiver.csproj | 15 +++ 20 files changed, 587 insertions(+) create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/AzureDataBusCleanupWithFunctions.sln create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.sln create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCreated.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobData.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobTimeoutCalculator.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusCleanupOrchestrator.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusOrchestrateExistingBlobs.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DeleteBlobFunction.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Program.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/launchSettings.json create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.json create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.local.json create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/host.json create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/local.settings.json create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/Program.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/AzureDataBusCleanupWithFunctions.sln b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/AzureDataBusCleanupWithFunctions.sln new file mode 100644 index 00000000000..623af222e95 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/AzureDataBusCleanupWithFunctions.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34526.213 +MinimumVisualStudioVersion = 15.0.26730.12 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SenderAndReceiver", "SenderAndReceiver\SenderAndReceiver.csproj", "{B656A5F2-29C7-43EE-86D9-FEC497962600}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataBusBlobCleanupFunctions", "DataBusBlobCleanupFunctions\DataBusBlobCleanupFunctions.csproj", "{4E54C4B8-6A71-4ADE-B7D6-E83082BD50DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B656A5F2-29C7-43EE-86D9-FEC497962600}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B656A5F2-29C7-43EE-86D9-FEC497962600}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B656A5F2-29C7-43EE-86D9-FEC497962600}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B656A5F2-29C7-43EE-86D9-FEC497962600}.Release|Any CPU.Build.0 = Release|Any CPU + {4E54C4B8-6A71-4ADE-B7D6-E83082BD50DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E54C4B8-6A71-4ADE-B7D6-E83082BD50DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E54C4B8-6A71-4ADE-B7D6-E83082BD50DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E54C4B8-6A71-4ADE-B7D6-E83082BD50DC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F5306B81-00A3-4AEA-8E05-AB387F2542AC} + EndGlobalSection +EndGlobal diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj new file mode 100644 index 00000000000..314aa993880 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj @@ -0,0 +1,32 @@ + + + + net9.0;net8.0 + v4 + 12.0 + Exe + enable + enable + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.sln b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.sln new file mode 100644 index 00000000000..aa43555c939 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DataBusBlobCleanupFunctions", "DataBusBlobCleanupFunctions.csproj", "{C34EAECB-5CF4-42F5-9428-3C0C3CCEDFD4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C34EAECB-5CF4-42F5-9428-3C0C3CCEDFD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C34EAECB-5CF4-42F5-9428-3C0C3CCEDFD4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C34EAECB-5CF4-42F5-9428-3C0C3CCEDFD4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C34EAECB-5CF4-42F5-9428-3C0C3CCEDFD4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {65FDA38E-030A-45D0-99D6-3606931E9935} + EndGlobalSection +EndGlobal diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCreated.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCreated.cs new file mode 100644 index 00000000000..c4f58f08f12 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCreated.cs @@ -0,0 +1,46 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.DurableTask; +using Microsoft.DurableTask.Client; +using Microsoft.Extensions.Logging; + +public class DataBusBlobCreated(ILogger logger) +{ + #region DataBusBlobCreatedFunction + + [Function(nameof(DataBusBlobCreated))] + public async Task Run([BlobTrigger("databus/{name}", Connection = "DataBusStorageAccount")] Stream blob, string name, Uri uri, IDictionary metadata, [DurableClient] DurableTaskClient durableTaskClient, CancellationToken cancellationToken) + { + logger.LogInformation("Blob created at {uri}", uri); + + var instanceId = name; + var existingInstance = await durableTaskClient.GetInstanceAsync(instanceId, cancellationToken); + + if (existingInstance != null) + { + logger.LogInformation("{DataBusCleanupOrchestratorName} has already been started for blob {uri}.", DataBusCleanupOrchestratorName, uri); + return; + } + + var validUntilUtc = DataBusBlobTimeoutCalculator.GetValidUntil(metadata); + + if (validUntilUtc == DateTime.MaxValue) + { + logger.LogError("Could not parse the 'ValidUntil' value for blob {uri}. Cleanup will not happen on this blob. You may consider manually removing this entry if non-expiry is incorrect.", uri); + return; + } + + await durableTaskClient.ScheduleNewOrchestrationInstanceAsync(DataBusCleanupOrchestratorName, new DataBusBlobData + { + Name = name, + ValidUntilUtc = DataBusBlobTimeoutCalculator.ToWireFormattedString(validUntilUtc) + }, + new StartOrchestrationOptions() + { + InstanceId = instanceId + }, cancellationToken); + } + + #endregion + + static readonly string DataBusCleanupOrchestratorName = nameof(DataBusCleanupOrchestrator); +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobData.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobData.cs new file mode 100644 index 00000000000..af2c6d63b26 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobData.cs @@ -0,0 +1,6 @@ +public class DataBusBlobData +{ + public required string Name { get; set; } + + public required string ValidUntilUtc { get; set; } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobTimeoutCalculator.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobTimeoutCalculator.cs new file mode 100644 index 00000000000..098f74ab9e7 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobTimeoutCalculator.cs @@ -0,0 +1,116 @@ + +using System.Globalization; + +public static class DataBusBlobTimeoutCalculator +{ + #region GetValidUntil + + public static DateTime GetValidUntil(IDictionary blobMetadata) + { + if (blobMetadata.TryGetValue("ValidUntilUtc", out var validUntilUtcString)) + { + return ToUtcDateTime(validUntilUtcString); + } + + return DateTime.MaxValue; + } + + #endregion + + /// + /// Converts the to a suitable for transport over the wire. + /// + public static string ToWireFormattedString(DateTime dateTime) + { + return dateTime.ToUniversalTime().ToString(format, CultureInfo.InvariantCulture); + } + + /// + /// Converts a wire-formatted from to a UTC + /// . + /// + public static DateTime ToUtcDateTime(string wireFormattedString) + { + if (string.IsNullOrWhiteSpace(wireFormattedString)) + { + throw new ArgumentNullException(nameof(wireFormattedString)); + } + + if (wireFormattedString.Length != format.Length) + { + throw new FormatException(errorMessage); + } + + var year = 0; + var month = 0; + var day = 0; + var hour = 0; + var minute = 0; + var second = 0; + var microSecond = 0; + + for (var i = 0; i < format.Length; i++) + { + var digit = wireFormattedString[i]; + + switch (format[i]) + { + case 'y': + Guard(digit); + year = year * 10 + (digit - '0'); + break; + + case 'M': + Guard(digit); + month = month * 10 + (digit - '0'); + break; + + case 'd': + Guard(digit); + day = day * 10 + (digit - '0'); + break; + + case 'H': + Guard(digit); + hour = hour * 10 + (digit - '0'); + break; + + case 'm': + Guard(digit); + minute = minute * 10 + (digit - '0'); + break; + + case 's': + Guard(digit); + second = second * 10 + (digit - '0'); + break; + + case 'f': + Guard(digit); + microSecond = microSecond * 10 + (digit - '0'); + break; + } + } + + return AddMicroseconds(new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc), microSecond); + + void Guard(char digit) + { + if (digit >= '0' && digit <= '9') + { + return; + } + + throw new FormatException(errorMessage); + } + + DateTime AddMicroseconds(DateTime self, int microseconds) + { + return self.AddTicks(microseconds * ticksPerMicrosecond); + } + } + + const string format = "yyyy-MM-dd HH:mm:ss:ffffff Z"; + const string errorMessage = "String was not recognized as a valid DateTime."; + const int ticksPerMicrosecond = 10; +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusCleanupOrchestrator.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusCleanupOrchestrator.cs new file mode 100644 index 00000000000..c99414b7f1b --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusCleanupOrchestrator.cs @@ -0,0 +1,36 @@ +#nullable disable + +using Microsoft.Azure.Functions.Worker; +using Microsoft.DurableTask; +using Microsoft.Extensions.Logging; + +public class DataBusCleanupOrchestrator(ILogger logger) +{ + #region DataBusCleanupOrchestratorFunction + + [Function(nameof(DataBusCleanupOrchestrator))] + public async Task RunOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context) + { + var blobData = context.GetInput(); + + logger.LogInformation("Orchestrating deletion for blob at {name} with ValidUntilUtc of {validUntilUtc}", blobData.Name, blobData.ValidUntilUtc); + + var validUntilUtc = DataBusBlobTimeoutCalculator.ToUtcDateTime(blobData.ValidUntilUtc); + + DateTime timeoutUntil; + + //Timeouts currently have a 7 day limit, use 6 day loops until the wait is less than 6 days + do + { + timeoutUntil = validUntilUtc > context.CurrentUtcDateTime.AddDays(6) ? context.CurrentUtcDateTime.AddDays(6) : validUntilUtc; + + logger.LogInformation("Waiting until {timeoutUntil}/{validUntilUtc} for blob at {blobData.Name}. Currently {context.CurrentUtcDateTime}.", timeoutUntil, validUntilUtc, blobData.Name, context.CurrentUtcDateTime); + + await context.CreateTimer(DataBusBlobTimeoutCalculator.ToUtcDateTime(blobData.ValidUntilUtc), CancellationToken.None); + } while (validUntilUtc > timeoutUntil); + + await context.CallActivityAsync("DeleteBlob", blobData); + } + + #endregion +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusOrchestrateExistingBlobs.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusOrchestrateExistingBlobs.cs new file mode 100644 index 00000000000..9c352596c7d --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusOrchestrateExistingBlobs.cs @@ -0,0 +1,76 @@ +using System.Net; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.DurableTask; +using Microsoft.DurableTask.Client; +using Microsoft.Extensions.Logging; + +public class DataBusOrchestrateExistingBlobs(BlobContainerClient blobContainerClient, ILogger logger) +{ + #region DataBusOrchestrateExistingBlobsFunction + + [Function(nameof(DataBusOrchestrateExistingBlobs))] + public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, [DurableClient] DurableTaskClient durableTaskClient, CancellationToken cancellationToken) + { + var counter = 0; + + try + { + var segment = blobContainerClient.GetBlobsAsync(traits: BlobTraits.Metadata, cancellationToken: cancellationToken).AsPages(); + + await foreach (var blobPage in segment) + { + foreach (var blobItem in blobPage.Values) + { + var instanceId = blobItem.Name; + + var existingInstance = await durableTaskClient.GetInstanceAsync(instanceId, cancellationToken); + + if (existingInstance != null) + { + logger.LogInformation("{name} has already been started for blob {blobItemName}.", nameof(DataBusCleanupOrchestrator), blobItem.Name); + continue; + } + + var validUntilUtc = DataBusBlobTimeoutCalculator.GetValidUntil(blobItem.Metadata); + + if (validUntilUtc == DateTime.MaxValue) + { + logger.LogError("Could not parse the 'ValidUntilUtc' value for blob {name}. Cleanup will not happen on this blob. You may consider manually removing this entry if non-expiry is incorrect.", blobItem.Name); + continue; + } + + await durableTaskClient.ScheduleNewOrchestrationInstanceAsync(nameof(DataBusCleanupOrchestrator), new DataBusBlobData + { + Name = blobItem.Name, + ValidUntilUtc = DataBusBlobTimeoutCalculator.ToWireFormattedString(validUntilUtc) + }, + new StartOrchestrationOptions() + { + InstanceId = instanceId + }, cancellationToken); + + counter++; + } + } + } + catch (Exception exception) + { + var result = new ObjectResult(exception.Message) + { + StatusCode = (int)HttpStatusCode.InternalServerError + }; + + return result; + } + + var message = "DataBusOrchestrateExistingBlobs has completed." + (counter > 0 ? $" {counter} blob{(counter > 1 ? "s" : string.Empty)} will be tracked for clean-up." : string.Empty); + + return new OkObjectResult(message); + } + + #endregion +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DeleteBlobFunction.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DeleteBlobFunction.cs new file mode 100644 index 00000000000..4122a51534f --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DeleteBlobFunction.cs @@ -0,0 +1,20 @@ +using Azure.Storage.Blobs; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +public class DeleteBlobFunction(BlobContainerClient containerClient, ILogger logger) +{ + #region DeleteBlobFunction + + [Function("DeleteBlob")] + public async Task DeleteBlob([ActivityTrigger] DataBusBlobData blobData) + { + var blob = containerClient.GetBlobClient(blobData.Name); + + logger.LogInformation("Deleting blob at {Name}", blobData.Name); + + await blob.DeleteIfExistsAsync(); + } + + #endregion +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Program.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Program.cs new file mode 100644 index 00000000000..d44eca6991e --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Program.cs @@ -0,0 +1,20 @@ +using Azure.Storage.Blobs; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +var host = new HostBuilder() + .ConfigureFunctionsWebApplication() + .ConfigureServices(services => + { + services.AddApplicationInsightsTelemetryWorkerService(); + services.ConfigureFunctionsApplicationInsights(); + + var storageConnectionString = Environment.GetEnvironmentVariable("DataBusStorageAccount"); + var blobServiceClient = new BlobServiceClient(storageConnectionString); + + services.AddSingleton((services) => blobServiceClient.GetBlobContainerClient("databus")); + }) + .Build(); + +host.Run(); diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/launchSettings.json b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/launchSettings.json new file mode 100644 index 00000000000..a99586e7fd6 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "DataBusBlobCleanupFunctions": { + "commandName": "Project", + "commandLineArgs": "--port 7072", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.json b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.json new file mode 100644 index 00000000000..55c1966e3bd --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.json @@ -0,0 +1,19 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + }, + "secrets1": { + "type": "secrets" + }, + "storage2": { + "type": "storage", + "connectionId": "DataBusStorageAccount", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.local.json b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.local.json new file mode 100644 index 00000000000..469182daa69 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/Properties/serviceDependencies.local.json @@ -0,0 +1,20 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + }, + "secrets1": { + "type": "secrets.user" + }, + "storage2": { + "secretStore": "LocalSecretsFile", + "type": "storage.emulator", + "connectionId": "DataBusStorageAccount", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/host.json b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/host.json new file mode 100644 index 00000000000..ee5cf5f83f4 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/local.settings.json b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/local.settings.json new file mode 100644 index 00000000000..f837db0bc15 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/local.settings.json @@ -0,0 +1,8 @@ +{ + "IsEncrypted": false, + "Values": { + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "DataBusStorageAccount": "UseDevelopmentStorage=true" + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs new file mode 100644 index 00000000000..d9e21ec2d0f --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using NServiceBus; + +namespace SenderAndReceiver +{ + public class InputLoopService(IMessageSession messageSession) : BackgroundService + { + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + Console.WriteLine("Press 'Enter' to send a large message (>4MB)"); + while (true) + { + var key = Console.ReadKey(); + + if (key.Key == ConsoleKey.Enter) + { + await SendMessageLargePayload(messageSession); + } + else + { + return; + } + } + } + static async Task SendMessageLargePayload(IMessageSession messageSession) + { + Console.WriteLine("Sending message..."); + +#pragma warning disable CS0618 // Type or member is obsolete + var message = new MessageWithLargePayload + { + Description = "This message contains a large payload that will be sent on the Azure data bus", + LargePayload = new DataBusProperty(new byte[1024 * 1024 * 5]) // 5MB + }; +#pragma warning restore CS0618 // Type or member is obsolete + + await messageSession.SendLocal(message); + + Console.WriteLine("Message sent."); + } + } +} diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs new file mode 100644 index 00000000000..74c5f5982d6 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs @@ -0,0 +1,10 @@ +using NServiceBus; + +[TimeToBeReceived("00:00:10")] +public class MessageWithLargePayload : ICommand +{ +#pragma warning disable CS0618 // Type or member is obsolete + public DataBusProperty LargePayload { get; set; } +#pragma warning restore CS0618 // Type or member is obsolete + public string Description { get; set; } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs new file mode 100644 index 00000000000..8358d94838e --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using NServiceBus; + +public class MessageWithLargePayloadHandler(ILogger logger) : IHandleMessages +{ + + public Task Handle(MessageWithLargePayload message, IMessageHandlerContext context) + { + #pragma warning disable CS0618 // Type or member is obsolete + logger.LogInformation("Message received. Description: '{Description}'. Size of payload property: {PayloadSize} Bytes", message.Description, message.LargePayload.Value.Length); + #pragma warning restore CS0618 // Type or member is obsolete + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/Program.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/Program.cs new file mode 100644 index 00000000000..280887fd701 --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using NServiceBus; +using SenderAndReceiver; + +Console.Title = "SenderAndReceiver"; + +var builder = Host.CreateApplicationBuilder(args); +builder.Services.AddHostedService(); +var endpointConfiguration = new EndpointConfiguration("Samples.AzureDataBusCleanupWithFunctions.SenderAndReceiver"); + +#pragma warning disable CS0618 // Type or member is obsolete +var dataBus = endpointConfiguration.UseDataBus(); +#pragma warning restore CS0618 // Type or member is obsolete +dataBus.ConnectionString("UseDevelopmentStorage=true"); + +endpointConfiguration.UseSerialization(); +endpointConfiguration.UseTransport(); +endpointConfiguration.EnableInstallers(); +builder.UseNServiceBus(endpointConfiguration); + +await builder.Build().RunAsync(); \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj new file mode 100644 index 00000000000..b2b04cae19f --- /dev/null +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj @@ -0,0 +1,15 @@ + + + + net9.0;net8.0 + Exe + 12.0 + + + + + + + + + \ No newline at end of file From 5eb6ec9d632ccc0694e9da6dcb3feb160d6bbabe Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 18 Jul 2025 00:07:28 -0600 Subject: [PATCH 2/2] Update blob-storage-databus-cleanup-function sample to NServiceBus 10 - Migrate SenderAndReceiver from .NET 9 to .NET 10 preview - Keep Azure Functions on .NET 9 (Azure Functions doesn't support .NET 10 yet) - Update NServiceBus packages to 10.0.0-alpha.1 versions - Migrate from DataBus to ClaimCheck API (NServiceBus.ClaimCheck 2.0.0-alpha.1) - Replace DataBusProperty with regular byte[] properties - Remove InputLoopService pattern and modernize Program.cs - Update ClaimCheck configuration with SystemJsonClaimCheckSerializer - Add prerelease.txt marker file Fixes: #7288 --- .../DataBusBlobCleanupFunctions.csproj | 2 +- .../SenderAndReceiver/InputLoopService.cs | 48 ------------------ .../MessageWithLargePayload.cs | 4 +- .../MessageWithLargePayloadHandler.cs | 4 +- .../ABSDataBus_7/SenderAndReceiver/Program.cs | 50 ++++++++++++++++--- .../SenderAndReceiver.csproj | 11 ++-- .../ABSDataBus_7/prerelease.txt | 0 7 files changed, 51 insertions(+), 68 deletions(-) delete mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs create mode 100644 samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/prerelease.txt diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj index 314aa993880..645dc80f8fa 100644 --- a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/DataBusBlobCleanupFunctions/DataBusBlobCleanupFunctions.csproj @@ -1,7 +1,7 @@ - net9.0;net8.0 + net9.0 v4 12.0 Exe diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs deleted file mode 100644 index d9e21ec2d0f..00000000000 --- a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/InputLoopService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; -using NServiceBus; - -namespace SenderAndReceiver -{ - public class InputLoopService(IMessageSession messageSession) : BackgroundService - { - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - Console.WriteLine("Press 'Enter' to send a large message (>4MB)"); - while (true) - { - var key = Console.ReadKey(); - - if (key.Key == ConsoleKey.Enter) - { - await SendMessageLargePayload(messageSession); - } - else - { - return; - } - } - } - static async Task SendMessageLargePayload(IMessageSession messageSession) - { - Console.WriteLine("Sending message..."); - -#pragma warning disable CS0618 // Type or member is obsolete - var message = new MessageWithLargePayload - { - Description = "This message contains a large payload that will be sent on the Azure data bus", - LargePayload = new DataBusProperty(new byte[1024 * 1024 * 5]) // 5MB - }; -#pragma warning restore CS0618 // Type or member is obsolete - - await messageSession.SendLocal(message); - - Console.WriteLine("Message sent."); - } - } -} diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs index 74c5f5982d6..396a7c4329b 100644 --- a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayload.cs @@ -3,8 +3,6 @@ [TimeToBeReceived("00:00:10")] public class MessageWithLargePayload : ICommand { -#pragma warning disable CS0618 // Type or member is obsolete - public DataBusProperty LargePayload { get; set; } -#pragma warning restore CS0618 // Type or member is obsolete + public byte[] LargePayload { get; set; } public string Description { get; set; } } \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs index 8358d94838e..0c79c81f53a 100644 --- a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/MessageWithLargePayloadHandler.cs @@ -7,9 +7,7 @@ public class MessageWithLargePayloadHandler(ILogger(); var endpointConfiguration = new EndpointConfiguration("Samples.AzureDataBusCleanupWithFunctions.SenderAndReceiver"); -#pragma warning disable CS0618 // Type or member is obsolete -var dataBus = endpointConfiguration.UseDataBus(); -#pragma warning restore CS0618 // Type or member is obsolete -dataBus.ConnectionString("UseDevelopmentStorage=true"); +var blobServiceClient = new BlobServiceClient("UseDevelopmentStorage=true"); +var claimCheck = endpointConfiguration.UseClaimCheck() + .Container("testcontainer") + .UseBlobServiceClient(blobServiceClient); endpointConfiguration.UseSerialization(); -endpointConfiguration.UseTransport(); +endpointConfiguration.UseTransport(new LearningTransport()); endpointConfiguration.EnableInstallers(); builder.UseNServiceBus(endpointConfiguration); -await builder.Build().RunAsync(); \ No newline at end of file +var host = builder.Build(); +await host.StartAsync(); + +var messageSession = host.Services.GetRequiredService(); + +Console.WriteLine("Press 'Enter' to send a large message (>4MB)"); +while (true) +{ + var key = Console.ReadKey(); + + if (key.Key == ConsoleKey.Enter) + { + await SendMessageLargePayload(messageSession); + } + else + { + break; + } +} + +await host.StopAsync(); + +static async Task SendMessageLargePayload(IMessageSession messageSession) +{ + Console.WriteLine("Sending message..."); + + var message = new MessageWithLargePayload + { + Description = "This message contains a large payload that will be sent on the Azure data bus", + LargePayload = new byte[1024 * 1024 * 5] // 5MB + }; + + await messageSession.SendLocal(message); + + Console.WriteLine("Message sent."); +} \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj index b2b04cae19f..751175fb5d7 100644 --- a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj +++ b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/SenderAndReceiver/SenderAndReceiver.csproj @@ -1,15 +1,16 @@ - net9.0;net8.0 + net10.0 Exe - 12.0 + preview - - - + + + + \ No newline at end of file diff --git a/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/prerelease.txt b/samples/databus/blob-storage-databus-cleanup-function/ABSDataBus_7/prerelease.txt new file mode 100644 index 00000000000..e69de29bb2d