diff --git a/.docfx/Dockerfile.docfx b/.docfx/Dockerfile.docfx index 95d581e..b39795b 100644 --- a/.docfx/Dockerfile.docfx +++ b/.docfx/Dockerfile.docfx @@ -1,4 +1,6 @@ -FROM --platform=$BUILDPLATFORM nginx:1.28.0-alpine AS base +ARG NGINX_VERSION=1.29.0-alpine + +FROM --platform=$BUILDPLATFORM nginx:${NGINX_VERSION} AS base RUN rm -rf /usr/share/nginx/html/* FROM --platform=$BUILDPLATFORM codebeltnet/docfx:2.78.3 AS build @@ -8,7 +10,7 @@ ADD [".", "docfx"] RUN cd docfx; \ docfx build -FROM nginx:1.28.0-alpine AS final +FROM nginx:${NGINX_VERSION} AS final WORKDIR /usr/share/nginx/html COPY --from=build /build/docfx/wwwroot /usr/share/nginx/html diff --git a/.docfx/docfx.json b/.docfx/docfx.json index 45e8bea..d67eb59 100644 --- a/.docfx/docfx.json +++ b/.docfx/docfx.json @@ -36,6 +36,7 @@ "Savvyio.Extensions.DependencyInjection.EFCore/**.csproj", "Savvyio.Extensions.DependencyInjection.EFCore.Domain/**.csproj", "Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/**.csproj", + "Savvyio.Extensions.DependencyInjection.NATS/**.csproj", "Savvyio.Extensions.DependencyInjection.QueueStorage/**.csproj", "Savvyio.Extensions.DependencyInjection.RabbitMQ/**.csproj", "Savvyio.Extensions.DependencyInjection.SimpleQueueService/**.csproj", @@ -43,6 +44,7 @@ "Savvyio.Extensions.EFCore/**.csproj", "Savvyio.Extensions.EFCore.Domain/**.csproj", "Savvyio.Extensions.EFCore.Domain.EventSourcing/**.csproj", + "Savvyio.Extensions.NATS/**.csproj", "Savvyio.Extensions.Newtonsoft.Json/**.csproj", "Savvyio.Extensions.QueueStorage/**.csproj", "Savvyio.Extensions.RabbitMQ/**.csproj", diff --git a/.github/workflows/pipelines.yml b/.github/workflows/pipelines.yml index b95b79f..3852651 100644 --- a/.github/workflows/pipelines.yml +++ b/.github/workflows/pipelines.yml @@ -40,6 +40,7 @@ jobs: !test/**/Savvyio.FunctionalTests.csproj !test/**/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj !test/**/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj + !test/**/Savvyio.Extensions.NATS.FunctionalTests.csproj !test/**/Savvyio.Extensions.RabbitMQ.FunctionalTests.csproj - name: JSON output @@ -157,10 +158,41 @@ jobs: docker stop rabbitmq docker rm rabbitmq + integration_test_nats: + name: ⚗️ Integration Test - NATS + needs: [build] + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - name: Checkout + uses: codebeltnet/git-checkout@v1 + + - name: Install .NET + uses: codebeltnet/install-dotnet@v2 + + - name: Install .NET Tool - Report Generator + uses: codebeltnet/dotnet-tool-install-reportgenerator@v1 + + - name: Spin up NATS test dependency + run: | + docker run -d --name nats -p 4222:4222 nats:latest --js + + - name: Test with Release build + uses: codebeltnet/dotnet-test@v4 + with: + projects: test/**/Savvyio.Extensions.NATS.FunctionalTests.csproj + build-switches: -p:SkipSignAssembly=true + build: true + + - name: Stop NATS + run: | + docker stop nats + docker rm nats + sonarcloud: name: call-sonarcloud - needs: [build, test, integration_test] - uses: codebeltnet/jobs-sonarcloud/.github/workflows/default.yml@v1 + needs: [build, test, integration_test, integration_test_rabbitmq, integration_test_nats] + uses: codebeltnet/jobs-sonarcloud/.github/workflows/default.yml@v2 with: organization: geekle projectKey: savvyio @@ -169,7 +201,7 @@ jobs: codecov: name: call-codecov - needs: [build, test, integration_test] + needs: [build, test, integration_test, integration_test_rabbitmq, integration_test_nats] uses: codebeltnet/jobs-codecov/.github/workflows/default.yml@v1 with: repository: codebeltnet/savvyio @@ -177,15 +209,15 @@ jobs: codeql: name: call-codeql - needs: [build, test, integration_test] - uses: codebeltnet/jobs-codeql/.github/workflows/default.yml@v1 + needs: [build, test, integration_test, integration_test_rabbitmq, integration_test_nats] + uses: codebeltnet/jobs-codeql/.github/workflows/default.yml@v2 permissions: security-events: write deploy: if: github.event_name != 'pull_request' name: call-nuget - needs: [build, pack, test, integration_test, sonarcloud, codecov, codeql] + needs: [build, pack, test, integration_test, integration_test_rabbitmq, integration_test_nats, sonarcloud, codecov, codeql] uses: codebeltnet/jobs-nuget-push/.github/workflows/default.yml@v1 with: version: ${{ needs.build.outputs.version }} diff --git a/.nuget/Savvyio.App/PackageReleaseNotes.txt b/.nuget/Savvyio.App/PackageReleaseNotes.txt index bcc441e..00ae505 100644 --- a/.nuget/Savvyio.App/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.App/PackageReleaseNotes.txt @@ -1,3 +1,37 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# References +- Savvyio +- Savvyio.Commands +- Savvyio.Commands.Messaging +- Savvyio.Domain +- Savvyio.Domain.EventSourcing +- Savvyio.EventDriven +- Savvyio.EventDriven.Messaging +- Savvyio.Extensions.Dapper +- Savvyio.Extensions.DependencyInjection +- Savvyio.Extensions.DependencyInjection.Dapper +- Savvyio.Extensions.DependencyInjection.Domain +- Savvyio.Extensions.DependencyInjection.EFCore +- Savvyio.Extensions.DependencyInjection.EFCore.Domain +- Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing +- Savvyio.Extensions.DependencyInjection.NATS +- Savvyio.Extensions.DependencyInjection.QueueStorage +- Savvyio.Extensions.DependencyInjection.RabbitMQ +- Savvyio.Extensions.DependencyInjection.SimpleQueueService +- Savvyio.Extensions.Dispatchers +- Savvyio.Extensions.EFCore +- Savvyio.Extensions.EFCore.Domain +- Savvyio.Extensions.EFCore.Domain.EventSourcing +- Savvyio.Extensions.NATS +- Savvyio.Extensions.QueueStorage +- Savvyio.Extensions.RabbitMQ +- Savvyio.Extensions.SimpleQueueService +- Savvyio.Extensions.Text.Json +- Savvyio.Messaging +- Savvyio.Queries +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.App/README.md b/.nuget/Savvyio.App/README.md index e8657d3..ecf5979 100644 --- a/.nuget/Savvyio.App/README.md +++ b/.nuget/Savvyio.App/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt index 36a683b..df9a80a 100644 --- a/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,6 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Commands.Messaging/README.md b/.nuget/Savvyio.Commands.Messaging/README.md index 94b1c5b..51378c0 100644 --- a/.nuget/Savvyio.Commands.Messaging/README.md +++ b/.nuget/Savvyio.Commands.Messaging/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Commands/PackageReleaseNotes.txt b/.nuget/Savvyio.Commands/PackageReleaseNotes.txt index 75545ec..86f8ed6 100644 --- a/.nuget/Savvyio.Commands/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Commands/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Commands/README.md b/.nuget/Savvyio.Commands/README.md index 6b6dc3b..0748fb9 100644 --- a/.nuget/Savvyio.Commands/README.md +++ b/.nuget/Savvyio.Commands/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Core/PackageReleaseNotes.txt b/.nuget/Savvyio.Core/PackageReleaseNotes.txt index 3da0bcf..c81a815 100644 --- a/.nuget/Savvyio.Core/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Core/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Core/README.md b/.nuget/Savvyio.Core/README.md index 0331b95..a46a416 100644 --- a/.nuget/Savvyio.Core/README.md +++ b/.nuget/Savvyio.Core/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt index acb87a1..95e6a8a 100644 --- a/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Domain.EventSourcing/README.md b/.nuget/Savvyio.Domain.EventSourcing/README.md index 0eabba4..68a741c 100644 --- a/.nuget/Savvyio.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Domain.EventSourcing/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Domain/PackageReleaseNotes.txt index 08c06e6..16f26d6 100644 --- a/.nuget/Savvyio.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Domain/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Domain/README.md b/.nuget/Savvyio.Domain/README.md index 3739c3e..2ef164c 100644 --- a/.nuget/Savvyio.Domain/README.md +++ b/.nuget/Savvyio.Domain/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt index e4643dd..53f9537 100644 --- a/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.EventDriven.Messaging/README.md b/.nuget/Savvyio.EventDriven.Messaging/README.md index da19638..af0046f 100644 --- a/.nuget/Savvyio.EventDriven.Messaging/README.md +++ b/.nuget/Savvyio.EventDriven.Messaging/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt b/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt index b65c5db..e027fc1 100644 --- a/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.EventDriven/README.md b/.nuget/Savvyio.EventDriven/README.md index 176761e..2cdf257 100644 --- a/.nuget/Savvyio.EventDriven/README.md +++ b/.nuget/Savvyio.EventDriven/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt index 95cc5de..bfc2f73 100644 --- a/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.Dapper/README.md b/.nuget/Savvyio.Extensions.Dapper/README.md index fbdbb84..1f3a372 100644 --- a/.nuget/Savvyio.Extensions.Dapper/README.md +++ b/.nuget/Savvyio.Extensions.Dapper/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt index ef512d9..5e5ede2 100644 --- a/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DapperExtensions/README.md b/.nuget/Savvyio.Extensions.DapperExtensions/README.md index 6f93fbd..a07a040 100644 --- a/.nuget/Savvyio.Extensions.DapperExtensions/README.md +++ b/.nuget/Savvyio.Extensions.DapperExtensions/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt index d32056d..6555a89 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md index 7e224db..cf5da7d 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt index 7ae0399..d377d9f 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md index 2b671b6..9ca1dab 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt index 50bb940..61e8168 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md index 439c5ad..ca771e1 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt index 27c7c5e..cddb586 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md index d886616..a72d4ba 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt index 1bb70e9..c02b6bb 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md index 62c24ee..f0ca5c5 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt index 5a93fac..b19526a 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md index e5df7f4..1c3211a 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt new file mode 100644 index 0000000..fd2597b --- /dev/null +++ b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt @@ -0,0 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# New Features +- ADDED NatsCommandQueue{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.Commands namespace that provides default implementation of the NatsMessage class for messages holding an ICommand implementation +- ADDED NatsCommandQueueOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.Commands namespace that provides configuration options for NatsCommandQueue{TMarker} +- ADDED NatsEventBus{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.EventDriven namespace that provides a default implementation of the NatsMessage class for messages holding an IIntegrationEvent implementation +- ADDED NatsEventBusOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.EventDriven namespace that provides configuration options for NatsEventBus{TMarker} +- ADDED ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.NATS namespace that consist of extension methods for the IServiceCollection interface: AddNatsCommandQueue, AddNatsEventBus diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md new file mode 100644 index 0000000..917ea19 --- /dev/null +++ b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md @@ -0,0 +1,47 @@ +# Savvyio.Extensions.DependencyInjection.NATS + +Extend the Savvy I/O support for Microsoft Dependency Injection with NATS Work-Queue Stream and NATS Core Publish-Subscribe implementations. + +## About + +An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. + +![Savvy I/O Flow](https://raw.githubusercontent.com/codebeltnet/savvyio/main/.assets/savvyio.png) + +It is, by heart, free, flexible and built to extend and boost your agile codebelt. + +## Related Packages + +* [Savvyio.App](https://www.nuget.org/packages/Savvyio.App/) 🏭 +* [Savvyio.Commands](https://www.nuget.org/packages/Savvyio.Commands/) 📦 +* [Savvyio.Commands.Messaging](https://www.nuget.org/packages/Savvyio.Commands.Messaging/) 📦 +* [Savvyio.Core](https://www.nuget.org/packages/Savvyio.Core/) 📦 +* [Savvyio.Domain](https://www.nuget.org/packages/Savvyio.Domain/) 📦 +* [Savvyio.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Domain.EventSourcing/) 📦 +* [Savvyio.EventDriven](https://www.nuget.org/packages/Savvyio.EventDriven/) 📦 +* [Savvyio.EventDriven.Messaging](https://www.nuget.org/packages/Savvyio.EventDriven.Messaging/) 📦 +* [Savvyio.Extensions.Dapper](https://www.nuget.org/packages/Savvyio.Extensions.Dapper/) 📦 +* [Savvyio.Extensions.DapperExtensions](https://www.nuget.org/packages/Savvyio.Extensions.DapperExtensions/) 📦 +* [Savvyio.Extensions.DependencyInjection](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection/) 📦 +* [Savvyio.Extensions.DependencyInjection.Dapper](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.Dapper/) 📦 +* [Savvyio.Extensions.DependencyInjection.DapperExtensions](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.DapperExtensions/) 📦 +* [Savvyio.Extensions.DependencyInjection.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.Domain/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 +* [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 +* [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 +* [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 +* [Savvyio.Extensions.Dispatchers](https://www.nuget.org/packages/Savvyio.Extensions.Dispatchers/) 📦 +* [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 +* [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 +* [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 +* [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 +* [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 +* [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 +* [Savvyio.Extensions.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.SimpleQueueService/) 📦 +* [Savvyio.Extensions.Text.Json](https://www.nuget.org/packages/Savvyio.Extensions.Text.Json/) 📦 +* [Savvyio.Messaging](https://www.nuget.org/packages/Savvyio.Messaging/) 📦 +* [Savvyio.Queries](https://www.nuget.org/packages/Savvyio.Queries/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/icon.png b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/icon.png new file mode 100644 index 0000000..39600ea Binary files /dev/null and b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/icon.png differ diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt index f62d24d..1889089 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md index 6c24396..dfdfc8f 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt index 9d1c50c..e17efae 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md index 2d47050..0abbd98 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt index a8b2a9f..e43fb70 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md index d8c3784..3ada28a 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt index 999fac9..06d0217 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.DependencyInjection/README.md b/.nuget/Savvyio.Extensions.DependencyInjection/README.md index 4cddff4..5883830 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt index d118392..b7ecd7e 100644 --- a/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.Dispatchers/README.md b/.nuget/Savvyio.Extensions.Dispatchers/README.md index 5766f27..ba058d7 100644 --- a/.nuget/Savvyio.Extensions.Dispatchers/README.md +++ b/.nuget/Savvyio.Extensions.Dispatchers/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt index efac562..fac9ad4 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md index fc4d0a0..6a2e97d 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt index 0eb09a1..872341d 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain/README.md b/.nuget/Savvyio.Extensions.EFCore.Domain/README.md index 0317917..228a9ca 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain/README.md +++ b/.nuget/Savvyio.Extensions.EFCore.Domain/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt index 4cbfdad..b4aba2a 100644 --- a/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.EFCore/README.md b/.nuget/Savvyio.Extensions.EFCore/README.md index 90570cd..a935ed4 100644 --- a/.nuget/Savvyio.Extensions.EFCore/README.md +++ b/.nuget/Savvyio.Extensions.EFCore/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt new file mode 100644 index 0000000..ab4741a --- /dev/null +++ b/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt @@ -0,0 +1,14 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  +# New Features +- ADDED NatsCommandQueue class in the Savvyio.Extensions.NATS.Commands namespace that provides a default implementation of the NatsMessage class for messages holding an ICommand implementation +- ADDED NatsCommandQueueOptions class in the Savvyio.Extensions.NATS.Commands namespace that provides configuration options for NatsCommandQueue +- ADDED NatsEventBus class in the Savvyio.Extensions.NATS.EventDriven namespace that provides a default implementation of the NatsMessage class for messages holding an IIntegrationEvent implementation +- ADDED NatsEventBusOptions class in the Savvyio.Extensions.NATS.EventDriven namespace that provides configuration options for NatsEventBus +- ADDED NatsMessage class in the Savvyio.Extensions.NATS namespace that provides a base class for NATS message operations, supporting asynchronous disposal and message serialization +- ADDED NatsMessageOptions class in the Savvyio.Extensions.NATS namespace that provides configuration options related to NATS +  \ No newline at end of file diff --git a/.nuget/Savvyio.Extensions.NATS/README.md b/.nuget/Savvyio.Extensions.NATS/README.md new file mode 100644 index 0000000..b23baea --- /dev/null +++ b/.nuget/Savvyio.Extensions.NATS/README.md @@ -0,0 +1,47 @@ +# Savvyio.Extensions.NATS + +Extend the Savvy I/O core assemblies with support for NATS Work-Queue Stream and NATS Core Publish-Subscribe. + +## About + +An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. + +![Savvy I/O Flow](https://raw.githubusercontent.com/codebeltnet/savvyio/main/.assets/savvyio.png) + +It is, by heart, free, flexible and built to extend and boost your agile codebelt. + +## Related Packages + +* [Savvyio.App](https://www.nuget.org/packages/Savvyio.App/) 🏭 +* [Savvyio.Commands](https://www.nuget.org/packages/Savvyio.Commands/) 📦 +* [Savvyio.Commands.Messaging](https://www.nuget.org/packages/Savvyio.Commands.Messaging/) 📦 +* [Savvyio.Core](https://www.nuget.org/packages/Savvyio.Core/) 📦 +* [Savvyio.Domain](https://www.nuget.org/packages/Savvyio.Domain/) 📦 +* [Savvyio.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Domain.EventSourcing/) 📦 +* [Savvyio.EventDriven](https://www.nuget.org/packages/Savvyio.EventDriven/) 📦 +* [Savvyio.EventDriven.Messaging](https://www.nuget.org/packages/Savvyio.EventDriven.Messaging/) 📦 +* [Savvyio.Extensions.Dapper](https://www.nuget.org/packages/Savvyio.Extensions.Dapper/) 📦 +* [Savvyio.Extensions.DapperExtensions](https://www.nuget.org/packages/Savvyio.Extensions.DapperExtensions/) 📦 +* [Savvyio.Extensions.DependencyInjection](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection/) 📦 +* [Savvyio.Extensions.DependencyInjection.Dapper](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.Dapper/) 📦 +* [Savvyio.Extensions.DependencyInjection.DapperExtensions](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.DapperExtensions/) 📦 +* [Savvyio.Extensions.DependencyInjection.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.Domain/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 +* [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 +* [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 +* [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 +* [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 +* [Savvyio.Extensions.Dispatchers](https://www.nuget.org/packages/Savvyio.Extensions.Dispatchers/) 📦 +* [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 +* [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 +* [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 +* [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 +* [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 +* [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 +* [Savvyio.Extensions.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.SimpleQueueService/) 📦 +* [Savvyio.Extensions.Text.Json](https://www.nuget.org/packages/Savvyio.Extensions.Text.Json/) 📦 +* [Savvyio.Messaging](https://www.nuget.org/packages/Savvyio.Messaging/) 📦 +* [Savvyio.Queries](https://www.nuget.org/packages/Savvyio.Queries/) 📦 diff --git a/.nuget/Savvyio.Extensions.NATS/icon.png b/.nuget/Savvyio.Extensions.NATS/icon.png new file mode 100644 index 0000000..39600ea Binary files /dev/null and b/.nuget/Savvyio.Extensions.NATS/icon.png differ diff --git a/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt index 692ed34..625a751 100644 --- a/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md b/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md index 8e6f29a..83c631c 100644 --- a/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md +++ b/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt index 0c97daa..9f6822f 100644 --- a/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.QueueStorage/README.md b/.nuget/Savvyio.Extensions.QueueStorage/README.md index ba7689c..a77deda 100644 --- a/.nuget/Savvyio.Extensions.QueueStorage/README.md +++ b/.nuget/Savvyio.Extensions.QueueStorage/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt index 871ac57..993c311 100644 --- a/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   @@ -16,5 +22,5 @@ Availability: .NET 9 and .NET 8 - ADDED RabbitMqEventBus class in the Savvyio.Extensions.RabbitMQ.EventDriven namespace that provides a default implementation of the RabbitMqMessage class for messages holding an IIntegrationEvent implementation - ADDED RabbitMqEventBusOptions class in the Savvyio.Extensions.RabbitMQ.EventDriven namespace that provides configuration options for RabbitMqEventBus - ADDED RabbitMqMessage class in the Savvyio.Extensions.RabbitMQ namespace that provides a base class for RabbitMQ message operations, including connection and channel management, marshalling, and resource disposal while ensuring thread-safe initialization of RabbitMQ connectivity -- ADDED RabbitMqMessageOptions class in the Savvyio.Extensions.RabbitMQ namespace that provides configuration options for RabbitMqMessage +- ADDED RabbitMqMessageOptions class in the Savvyio.Extensions.RabbitMQ namespace that provides configuration options related to RabbitMQ   \ No newline at end of file diff --git a/.nuget/Savvyio.Extensions.RabbitMQ/README.md b/.nuget/Savvyio.Extensions.RabbitMQ/README.md index 767da05..333208b 100644 --- a/.nuget/Savvyio.Extensions.RabbitMQ/README.md +++ b/.nuget/Savvyio.Extensions.RabbitMQ/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt index 09d053a..89486f8 100644 --- a/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.SimpleQueueService/README.md b/.nuget/Savvyio.Extensions.SimpleQueueService/README.md index 8d5b943..2235152 100644 --- a/.nuget/Savvyio.Extensions.SimpleQueueService/README.md +++ b/.nuget/Savvyio.Extensions.SimpleQueueService/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt index 9a0b789..e7a15bb 100644 --- a/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Extensions.Text.Json/README.md b/.nuget/Savvyio.Extensions.Text.Json/README.md index 424cdd6..c6519d7 100644 --- a/.nuget/Savvyio.Extensions.Text.Json/README.md +++ b/.nuget/Savvyio.Extensions.Text.Json/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt index 45f8158..d968ab5 100644 --- a/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Messaging/README.md b/.nuget/Savvyio.Messaging/README.md index e3eaab4..a3e4036 100644 --- a/.nuget/Savvyio.Messaging/README.md +++ b/.nuget/Savvyio.Messaging/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/.nuget/Savvyio.Queries/PackageReleaseNotes.txt b/.nuget/Savvyio.Queries/PackageReleaseNotes.txt index 527c266..a3ab997 100644 --- a/.nuget/Savvyio.Queries/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Queries/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 4.2.0 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) +  Version: 4.1.1 Availability: .NET 9 and .NET 8   diff --git a/.nuget/Savvyio.Queries/README.md b/.nuget/Savvyio.Queries/README.md index 3993fe3..1299546 100644 --- a/.nuget/Savvyio.Queries/README.md +++ b/.nuget/Savvyio.Queries/README.md @@ -29,6 +29,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) 📦 * [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) 📦 * [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) 📦 * [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) 📦 * [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) 📦 @@ -36,6 +37,7 @@ It is, by heart, free, flexible and built to extend and boost your agile codebel * [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) 📦 * [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) 📦 * [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) 📦 +* [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) 📦 * [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) 📦 * [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) 📦 * [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) 📦 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f5ee93..9750e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder. +## [4.2.0] - 2025-08-26 + +This is a feature release that offers support for NATS as a message broker in the context of NATS Work-Queue Stream (Command) and NATS Core Publish-Subscribe (Integration Event). + +Also includes a service update that primarily focuses on bumping package dependencies. + +### Added + +#### Savvyio.Extensions.DependencyInjection.NATS + +- NatsCommandQueue{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.Commands namespace that provides default implementation of the NatsMessage class for messages holding an ICommand implementation +- NatsCommandQueueOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.Commands namespace that provides configuration options for NatsCommandQueue{TMarker} +- NatsEventBus{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.EventDriven namespace that provides a default implementation of the NatsMessage class for messages holding an IIntegrationEvent implementation +- NatsEventBusOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.NATS.EventDriven namespace that provides configuration options for NatsEventBus{TMarker} +- ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.NATS namespace that consist of extension methods for the IServiceCollection interface: AddNatsCommandQueue, AddNatsEventBus + +#### Savvyio.Extensions.NATS + +- NatsCommandQueue class in the Savvyio.Extensions.NATS.Commands namespace that provides a default implementation of the NatsMessage class for messages holding an ICommand implementation +- NatsCommandQueueOptions class in the Savvyio.Extensions.NATS.Commands namespace that provides configuration options for NatsCommandQueue +- NatsEventBus class in the Savvyio.Extensions.NATS.EventDriven namespace that provides a default implementation of the NatsMessage class for messages holding an IIntegrationEvent implementation +- NatsEventBusOptions class in the Savvyio.Extensions.NATS.EventDriven namespace that provides configuration options for NatsEventBus +- NatsMessage class in the Savvyio.Extensions.NATS namespace that provides a base class for NATS message operations, supporting asynchronous disposal and message serialization +- NatsMessageOptions class in the Savvyio.Extensions.NATS namespace that provides configuration options related to NATS + ## [4.1.1] - 2025-06-16 This is a service update that focuses on package dependencies. diff --git a/Directory.Packages.props b/Directory.Packages.props index 30d00d4..f1cc3b4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,47 +4,50 @@ true - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + + + + - + - + - - - - + + + + - - - + + + diff --git a/README.md b/README.md index 7110442..5e231e1 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ Provides a focused API for building various types of modern .NET applications su | [Savvyio.Extensions.DependencyInjection.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.EFCore?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.EFCore?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.EFCore?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.DependencyInjection.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.EFCore.Domain?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.EFCore.Domain?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.EFCore.Domain?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing?color=blueviolet&logo=nuget) | +| [Savvyio.Extensions.DependencyInjection.NATS](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.NATS/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.NATS?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.NATS?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.NATS?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.DependencyInjection.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.QueueStorage/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.QueueStorage?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.QueueStorage?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.QueueStorage?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.DependencyInjection.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.RabbitMQ/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.RabbitMQ?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.RabbitMQ?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.RabbitMQ?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.DependencyInjection.SimpleQueueService](https://www.nuget.org/packages/Savvyio.Extensions.DependencyInjection.SimpleQueueService/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.DependencyInjection.SimpleQueueService?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.DependencyInjection.SimpleQueueService?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.DependencyInjection.SimpleQueueService?color=blueviolet&logo=nuget) | @@ -94,6 +95,7 @@ Provides a focused API for building various types of modern .NET applications su | [Savvyio.Extensions.EFCore](https://www.nuget.org/packages/Savvyio.Extensions.EFCore/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.EFCore?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.EFCore?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.EFCore?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.EFCore.Domain](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.EFCore.Domain?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.EFCore.Domain?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.EFCore.Domain?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.EFCore.Domain.EventSourcing](https://www.nuget.org/packages/Savvyio.Extensions.EFCore.Domain.EventSourcing/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.EFCore.Domain.EventSourcing?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.EFCore.Domain.EventSourcing?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.EFCore.Domain.EventSourcing?color=blueviolet&logo=nuget) | +| [Savvyio.Extensions.NATS](https://www.nuget.org/packages/Savvyio.Extensions.NATS/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.NATS?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.NATS?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.NATS?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.Newtonsoft.Json](https://www.nuget.org/packages/Savvyio.Extensions.Newtonsoft.Json/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.Newtonsoft.Json?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.Newtonsoft.Json?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.Newtonsoft.Json?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.QueueStorage](https://www.nuget.org/packages/Savvyio.Extensions.QueueStorage/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.QueueStorage?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.QueueStorage?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.QueueStorage?color=blueviolet&logo=nuget) | | [Savvyio.Extensions.RabbitMQ](https://www.nuget.org/packages/Savvyio.Extensions.RabbitMQ/) | ![vNext](https://img.shields.io/nuget/vpre/Savvyio.Extensions.RabbitMQ?logo=nuget) | ![Stable](https://img.shields.io/nuget/v/Savvyio.Extensions.RabbitMQ?logo=nuget) | ![Downloads](https://img.shields.io/nuget/dt/Savvyio.Extensions.RabbitMQ?color=blueviolet&logo=nuget) | @@ -104,7 +106,7 @@ Provides a focused API for building various types of modern .NET applications su ### 🏭 Productivity Packages -Provides a convenient set of default API additions for building complete DDD, CQRS and Event Sourcing enabled .NET applications using Microsoft Dependency Injection, Microsoft Entity Framework Core, Dapper and AWS SNS/SQS. +Provides a convenient set of default API additions for building complete DDD, CQRS and Event Sourcing enabled .NET applications using Microsoft Dependency Injection, Microsoft Entity Framework Core, Dapper, AWS SNS/SQS, Azure Queue Storage/Event Grid, RabbitMQ and NATS. |Package|vNext|Stable|Downloads| |:--|:-:|:-:|:-:| diff --git a/Savvyio.sln b/Savvyio.sln index e47ffad..be39590 100644 --- a/Savvyio.sln +++ b/Savvyio.sln @@ -129,6 +129,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.Dependen EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.RabbitMQ.Tests", "test\Savvyio.Extensions.RabbitMQ.Tests\Savvyio.Extensions.RabbitMQ.Tests.csproj", "{0AE5B8A9-228D-4A7E-A931-FDF84A4217D3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.NATS", "src\Savvyio.Extensions.NATS\Savvyio.Extensions.NATS.csproj", "{A684DE92-380A-CCCE-442F-A7F96B437F85}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.NATS.Tests", "test\Savvyio.Extensions.NATS.Tests\Savvyio.Extensions.NATS.Tests.csproj", "{C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.NATS.FunctionalTests", "test\Savvyio.Extensions.NATS.FunctionalTests\Savvyio.Extensions.NATS.FunctionalTests.csproj", "{030BB5FC-BB8B-4349-B8BD-93DBFE887D18}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.DependencyInjection.NATS", "src\Savvyio.Extensions.DependencyInjection.NATS\Savvyio.Extensions.DependencyInjection.NATS.csproj", "{D4E7613F-FBF6-451A-AEA4-D46907CC9C78}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Savvyio.Extensions.DependencyInjection.NATS.Tests", "test\Savvyio.Extensions.DependencyInjection.NATS.Tests\Savvyio.Extensions.DependencyInjection.NATS.Tests.csproj", "{B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -379,6 +389,26 @@ Global {0AE5B8A9-228D-4A7E-A931-FDF84A4217D3}.Debug|Any CPU.Build.0 = Debug|Any CPU {0AE5B8A9-228D-4A7E-A931-FDF84A4217D3}.Release|Any CPU.ActiveCfg = Release|Any CPU {0AE5B8A9-228D-4A7E-A931-FDF84A4217D3}.Release|Any CPU.Build.0 = Release|Any CPU + {A684DE92-380A-CCCE-442F-A7F96B437F85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A684DE92-380A-CCCE-442F-A7F96B437F85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A684DE92-380A-CCCE-442F-A7F96B437F85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A684DE92-380A-CCCE-442F-A7F96B437F85}.Release|Any CPU.Build.0 = Release|Any CPU + {C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3}.Release|Any CPU.Build.0 = Release|Any CPU + {030BB5FC-BB8B-4349-B8BD-93DBFE887D18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {030BB5FC-BB8B-4349-B8BD-93DBFE887D18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {030BB5FC-BB8B-4349-B8BD-93DBFE887D18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {030BB5FC-BB8B-4349-B8BD-93DBFE887D18}.Release|Any CPU.Build.0 = Release|Any CPU + {D4E7613F-FBF6-451A-AEA4-D46907CC9C78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4E7613F-FBF6-451A-AEA4-D46907CC9C78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4E7613F-FBF6-451A-AEA4-D46907CC9C78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4E7613F-FBF6-451A-AEA4-D46907CC9C78}.Release|Any CPU.Build.0 = Release|Any CPU + {B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -445,6 +475,11 @@ Global {03FA8A80-ADD3-41CC-B55F-E435120D6DA9} = {0E75F0C5-DBEB-4B6D-AC52-98656CA79A7D} {5424475B-B2EB-4CF2-B7D5-D23CDE9A8D59} = {407762FB-26D8-435F-AE16-C76791EC9FEC} {0AE5B8A9-228D-4A7E-A931-FDF84A4217D3} = {407762FB-26D8-435F-AE16-C76791EC9FEC} + {A684DE92-380A-CCCE-442F-A7F96B437F85} = {0E75F0C5-DBEB-4B6D-AC52-98656CA79A7D} + {C33D2F96-D7DC-41FD-A5DB-3B4C349B9FB3} = {407762FB-26D8-435F-AE16-C76791EC9FEC} + {030BB5FC-BB8B-4349-B8BD-93DBFE887D18} = {407762FB-26D8-435F-AE16-C76791EC9FEC} + {D4E7613F-FBF6-451A-AEA4-D46907CC9C78} = {0E75F0C5-DBEB-4B6D-AC52-98656CA79A7D} + {B38EFDB0-58A2-4C6F-B46E-9B5F01E23F15} = {407762FB-26D8-435F-AE16-C76791EC9FEC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D8DDAD51-08E6-42B5-970B-2DC88D44297B} diff --git a/src/Savvyio.App/Savvyio.App.csproj b/src/Savvyio.App/Savvyio.App.csproj index 5e2aed4..09102a4 100644 --- a/src/Savvyio.App/Savvyio.App.csproj +++ b/src/Savvyio.App/Savvyio.App.csproj @@ -23,6 +23,7 @@ + @@ -31,6 +32,7 @@ + diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs new file mode 100644 index 0000000..7b8580f --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs @@ -0,0 +1,32 @@ +using System; +using Savvyio.Commands; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS; +using Savvyio.Extensions.NATS.Commands; + +namespace Savvyio.Extensions.DependencyInjection.NATS.Commands +{ + /// + /// Provides a default implementation of the class for messages holding an implementation. + /// + /// + /// + public class NatsCommandQueue : NatsCommandQueue, IPointToPointChannel + { + /// + /// Initializes a new instance of the class. + /// + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the NATS command queue. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public NatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options) : base(marshaller, options) + { + } + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs new file mode 100644 index 0000000..d92ae34 --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs @@ -0,0 +1,14 @@ +using Cuemon.Extensions.DependencyInjection; +using Savvyio.Extensions.NATS.Commands; + +namespace Savvyio.Extensions.DependencyInjection.NATS.Commands +{ + /// + /// Configuration options for . + /// + /// + /// + public class NatsCommandQueueOptions : NatsCommandQueueOptions, IDependencyInjectionMarker + { + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs new file mode 100644 index 0000000..4249545 --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs @@ -0,0 +1,33 @@ +using System; +using Savvyio.EventDriven; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS; +using Savvyio.Extensions.NATS.EventDriven; + +namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven +{ + /// + /// Provides a default implementation of the class for messages holding an implementation. + /// + /// + /// + public class NatsEventBus : NatsEventBus, IPublishSubscribeChannel + { + + /// + /// Initializes a new instance of the class. + /// + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the NATS event bus. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public NatsEventBus(IMarshaller marshaller, NatsEventBusOptions options) : base(marshaller, options) + { + } + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs new file mode 100644 index 0000000..12a6f12 --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs @@ -0,0 +1,14 @@ +using Cuemon.Extensions.DependencyInjection; +using Savvyio.Extensions.NATS.EventDriven; + +namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven +{ + /// + /// Configuration options for . + /// + /// + /// + public class NatsEventBusOptions : NatsEventBusOptions, IDependencyInjectionMarker + { + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj b/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj new file mode 100644 index 0000000..9ed94a2 --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj @@ -0,0 +1,13 @@ + + + + Extend the Savvy I/O support for Microsoft Dependency Injection with NATS Work-Queue Stream and NATS Core Publish-Subscribe implementations. + nats jetstream publish subscribe bus di depedency-injection + + + + + + + + diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..55edeb6 --- /dev/null +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs @@ -0,0 +1,79 @@ +using Cuemon.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.Extensions.DependencyInjection.Messaging; +using System; +using Savvyio.Commands; +using Savvyio.EventDriven; +using Savvyio.Extensions.DependencyInjection.NATS.Commands; +using Savvyio.Extensions.DependencyInjection.NATS.EventDriven; +using Savvyio.Extensions.NATS.Commands; +using Savvyio.Extensions.NATS.EventDriven; + +namespace Savvyio.Extensions.DependencyInjection.NATS +{ + /// + /// Extension methods for the interface. + /// + public static class ServiceCollectionExtensions + { + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) + { + return services + .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(natsSetup); + } + + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) + { + return services + .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(natsSetup); + } + + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) + { + return services + .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(natsSetup); + } + + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) + { + return services + .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(natsSetup); + } + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs index 8666044..89acf90 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs @@ -10,7 +10,7 @@ namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven /// Provides a default implementation of the class for messages holding an implementation. /// /// - /// + /// public class RabbitMqEventBus : RabbitMqEventBus, IPublishSubscribeChannel { diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs new file mode 100644 index 0000000..289eb64 --- /dev/null +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs @@ -0,0 +1,123 @@ +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.IO; +using Cuemon.Extensions.Reflection; +using Cuemon.Threading; +using NATS.Client.Core; +using NATS.Client.JetStream; +using NATS.Client.JetStream.Models; +using NATS.Net; +using Savvyio.Commands; +using Savvyio.Messaging; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Savvyio.Extensions.NATS.Commands +{ + /// + /// Provides a NATS JetStream implementation of the for command messages. + /// + /// + /// + public class NatsCommandQueue : NatsMessage, IPointToPointChannel + { + private readonly NatsCommandQueueOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// The marshaller used for serializing and deserializing messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public NatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options) : base(marshaller, options) + { + Validator.ThrowIfInvalidOptions(options); + _options = options; + } + + /// + /// Sends the specified command messages asynchronously to the configured NATS JetStream subject. + /// + /// The messages to send. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task SendAsync(IEnumerable> messages, Action setup = null) + { + var js = NatsClient.CreateJetStreamContext(); + foreach (var message in messages) + { + await js.PublishAsync(_options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), headers: new NatsHeaders() + { + { "type", message.GetType().ToFullNameIncludingAssemblyName() } + }); + } + } + + /// + /// Receives command messages asynchronously from the configured NATS JetStream consumer. + /// + /// The which may be configured. + /// + /// An that yields instances as they are received. + /// + public async IAsyncEnumerable> ReceiveAsync(Action setup = null) + { + Validator.ThrowIfInvalidConfigurator(setup, out var options); + + var streamName = _options.StreamName; + var consumerName = _options.ConsumerName; + + var js = NatsClient.CreateJetStreamContext(); + var stream = await js.CreateOrUpdateStreamAsync(new StreamConfig(streamName, [_options.Subject]) + { + Retention = StreamConfigRetention.Workqueue + }, options.CancellationToken).ConfigureAwait(false); + + var consumer = await stream.CreateOrUpdateConsumerAsync(new ConsumerConfig(consumerName) + { + }, options.CancellationToken).ConfigureAwait(false); + + await foreach (var message in consumer.FetchAsync(opts: new NatsJSFetchOpts() + { + Expires = _options.Expires == TimeSpan.Zero ? null : _options.Expires, + MaxMsgs = _options.MaxMessages, + IdleHeartbeat = _options.Heartbeat == TimeSpan.Zero ? null : _options.Heartbeat + }, cancellationToken: options.CancellationToken)) + { + options.CancellationToken.ThrowIfCancellationRequested(); + var messageType = Type.GetType(message.Headers["type"]); + var deserialized = Marshaller.Deserialize(await message.Data.FromBase64().ToStreamAsync().ConfigureAwait(false), messageType) as IMessage; + deserialized!.Properties.Add(nameof(CancellationToken), options.CancellationToken); + deserialized.Properties.Add(nameof(NatsJSMsg), message); + deserialized.Acknowledged += OnMessageAcknowledgedAsync; + if (_options.AutoAcknowledge) + { + await deserialized.AcknowledgeAsync().ConfigureAwait(false); + } + yield return deserialized; + } + } + + /// + /// Handles the acknowledgment of a message by sending an acknowledgment to the NATS JetStream server. + /// + /// The message that was acknowledged. + /// The event arguments containing properties of the acknowledged message. + /// A that represents the asynchronous operation. + private async Task OnMessageAcknowledgedAsync(object sender, AcknowledgedEventArgs e) + { + var ct = (CancellationToken)e.Properties[nameof(CancellationToken)]; + var message = (NatsJSMsg)e.Properties[nameof(NatsJSMsg)]; + await message.AckAsync(cancellationToken: ct).ConfigureAwait(false); + if (sender is IAcknowledgeable ack) { ack.Acknowledged -= OnMessageAcknowledgedAsync; } + } + } +} diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs new file mode 100644 index 0000000..7b636e1 --- /dev/null +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs @@ -0,0 +1,118 @@ +using System; +using Cuemon; + +namespace Savvyio.Extensions.NATS.Commands +{ + /// + /// Configuration options for . + /// + /// + public class NatsCommandQueueOptions : NatsMessageOptions + { + private int _maxMessages; + private TimeSpan _expires; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// 100 + /// + /// + /// + /// false + /// + /// + /// + /// TimeSpan.Zero + /// + /// + /// + /// TimeSpan.Zero + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + public NatsCommandQueueOptions() + { + MaxMessages = 25; + Heartbeat = TimeSpan.Zero; + Expires = TimeSpan.Zero; + } + + /// + /// Gets or sets the maximum number of messages to process. + /// + public int MaxMessages + { + get => _maxMessages; + set => _maxMessages = Math.Clamp(value, 1, short.MaxValue); + } + + /// + /// Gets or sets the expiration time for messages in the queue. + /// + /// If set to a value greater than or equal to 30 seconds, the property is automatically set to 5 seconds. + public TimeSpan Expires + { + get => _expires; + set + { + _expires = value; + if (_expires >= TimeSpan.FromSeconds(30)) + { + Heartbeat = TimeSpan.FromSeconds(5); + } + } + } + + /// + /// Gets or sets the interval for the heartbeat signal sent from the NATS server. + /// + /// If is set to a value greater than or equal to 30 seconds, this property is automatically set to 5 seconds. + public TimeSpan Heartbeat { get; set; } + + /// + /// Gets or sets the name of the NATS stream. + /// + public string StreamName { get; set; } + + /// + /// Gets or sets the name of the NATS consumer. + /// + public string ConsumerName { get; set; } + + /// + /// Gets or sets a value indicating whether messages should be automatically acknowledged. + /// + public bool AutoAcknowledge { get; set; } + + /// + /// Validates the options for the NATS command queue. + /// + /// + /// or is null or whitespace. + /// + public override void ValidateOptions() + { + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(StreamName)); + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(ConsumerName)); + base.ValidateOptions(); + } + } +} diff --git a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs new file mode 100644 index 0000000..e41f5ab --- /dev/null +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs @@ -0,0 +1,76 @@ +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.IO; +using Cuemon.Extensions.Reflection; +using Cuemon.Threading; +using NATS.Client.Core; +using Savvyio.EventDriven; +using Savvyio.Messaging; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Savvyio.Extensions.NATS.EventDriven +{ + /// + /// Provides a NATS implementation of the for integration event messages. + /// + /// + /// + public class NatsEventBus : NatsMessage, IPublishSubscribeChannel + { + private readonly NatsEventBusOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// The marshaller used for serializing and deserializing messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public NatsEventBus(IMarshaller marshaller, NatsEventBusOptions options) : base(marshaller, options) + { + Validator.ThrowIfInvalidOptions(options); + _options = options; + } + + /// + /// Publishes the specified integration event message asynchronously to the configured NATS subject. + /// + /// The message to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task PublishAsync(IMessage message, Action setup = null) + { + Validator.ThrowIfInvalidConfigurator(setup, out var options); + await NatsClient.PublishAsync(_options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), headers: new NatsHeaders() + { + { "type", message.GetType().ToFullNameIncludingAssemblyName() } + }, cancellationToken: options.CancellationToken); + } + + /// + /// Subscribes to integration event messages from the configured NATS subject and invokes the specified asynchronous handler for each received message. + /// + /// The function delegate that will handle the message. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + { + Validator.ThrowIfInvalidConfigurator(setup, out var options); + await foreach (var message in NatsClient.SubscribeAsync(_options.Subject, opts: new NatsSubOpts() + { + }, cancellationToken: options.CancellationToken)) + { + var messageType = Type.GetType(message.Headers["type"]); + var deserialized = Marshaller.Deserialize(await message.Data.FromBase64().ToStreamAsync().ConfigureAwait(false), messageType) as IMessage; + await asyncHandler.Invoke(deserialized, options.CancellationToken).ConfigureAwait(false); + } + } + } +} diff --git a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs new file mode 100644 index 0000000..9174ae4 --- /dev/null +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs @@ -0,0 +1,10 @@ +namespace Savvyio.Extensions.NATS.EventDriven +{ + /// + /// Configuration options for . + /// + /// + public class NatsEventBusOptions : NatsMessageOptions + { + } +} diff --git a/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs b/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs new file mode 100644 index 0000000..5a435af --- /dev/null +++ b/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Minor Code Smell", "S2094:Classes should not be empty", Justification = "Consistency.", Scope = "type", Target = "~T:Savvyio.Extensions.NATS.EventDriven.NatsEventBusOptions")] diff --git a/src/Savvyio.Extensions.NATS/NatsMessage.cs b/src/Savvyio.Extensions.NATS/NatsMessage.cs new file mode 100644 index 0000000..cd507ab --- /dev/null +++ b/src/Savvyio.Extensions.NATS/NatsMessage.cs @@ -0,0 +1,54 @@ +using System; +using Cuemon.Extensions; +using NATS.Net; +using System.Threading.Tasks; +using Cuemon; + +namespace Savvyio.Extensions.NATS +{ + /// + /// Provides a base class for NATS message operations, supporting asynchronous disposal and message serialization. + /// + public abstract class NatsMessage : AsyncDisposable + { + /// + /// Initializes a new instance of the class with the specified marshaller and options. + /// + /// The marshaller used for serializing and deserializing messages. + /// The configuration options for the NATS message. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected NatsMessage(IMarshaller marshaller, NatsMessageOptions options) + { + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidOptions(options); + Marshaller = marshaller; + NatsClient = new NatsClient(options.NatsUrl.OriginalString); + } + + /// + /// Gets the NATS client provided by the constructor for communication with the NATS server. + /// + protected NatsClient NatsClient { get; } + + /// + /// Gets the marshaller provided by the constructor for serializing and deserializing messages. + /// + /// The marshaller used for message serialization and deserialization. + protected IMarshaller Marshaller { get; } + + /// + /// Releases the managed resources used by the asynchronously. + /// + /// A that represents the asynchronous dispose operation. + protected override async ValueTask OnDisposeManagedResourcesAsync() + { + if (NatsClient != null) { await NatsClient.DisposeAsync().ConfigureAwait(false); } + } + } +} diff --git a/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs new file mode 100644 index 0000000..7e52f35 --- /dev/null +++ b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs @@ -0,0 +1,61 @@ +using System; +using Cuemon; +using Cuemon.Configuration; + +namespace Savvyio.Extensions.NATS +{ + /// + /// Configuration options that is related to NATS. + /// + /// + public class NatsMessageOptions : IValidatableParameterObject + { + /// + /// Initializes a new instance of the class with default values. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// new Uri("nats://127.0.0.1:4222") + /// + /// + /// + /// null + /// + /// + /// + public NatsMessageOptions() + { + NatsUrl = new Uri("nats://127.0.0.1:4222"); + } + + /// + /// Gets or sets the URI of the NATS server. + /// + public Uri NatsUrl { get; set; } + + /// + /// Gets or sets the subject to publish or subscribe to in NATS. + /// + public string Subject { get; set; } + + /// + /// Validates the current options and throws an exception if the state is invalid. + /// + /// + /// is null or whitespace - or - + /// is null. + /// + public virtual void ValidateOptions() + { + Validator.ThrowIfInvalidState(NatsUrl == null); + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(Subject)); + } + } +} diff --git a/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj b/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj new file mode 100644 index 0000000..0dcd2a3 --- /dev/null +++ b/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj @@ -0,0 +1,24 @@ + + + + Extend the Savvy I/O core assemblies with support for NATS Work-Queue Stream and NATS Core Publish-Subscribe. + nats jetstream worker queue publish subscribe bus + + + + + + + + + + + + + + + + + + + diff --git a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs index 5ea45d4..806351e 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs @@ -118,6 +118,7 @@ private async Task OnMessageAcknowledgedAsync(object sender, AcknowledgedEventAr var queueName = e.Properties[nameof(QueueDeclareOk.QueueName)] as string; await RabbitMqChannel.QueueDeclareAsync(queueName, _options.Durable, _options.Exclusive, _options.AutoDelete, cancellationToken: ct).ConfigureAwait(false); await RabbitMqChannel.BasicAckAsync((ulong)e.Properties[nameof(BasicDeliverEventArgs.DeliveryTag)], false, ct).ConfigureAwait(false); + if (sender is IAcknowledgeable ack) { ack.Acknowledged -= OnMessageAcknowledgedAsync; } } } } diff --git a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs index ca35fbe..120305b 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs @@ -97,7 +97,7 @@ public RabbitMqCommandQueueOptions() /// public override void ValidateOptions() { - Validator.ThrowIfInvalidState(string.IsNullOrEmpty(QueueName)); + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(QueueName)); base.ValidateOptions(); } } diff --git a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs index ace4d2e..6e1c516 100644 --- a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs +++ b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs @@ -105,8 +105,8 @@ protected async Task EnsureConnectivityAsync(CancellationToken ct) /// A representing the asynchronous dispose operation. protected override async ValueTask OnDisposeManagedResourcesAsync() { - if (RabbitMqChannel != null) { await RabbitMqChannel.DisposeAsync(); } - if (RabbitMqConnection != null) { await RabbitMqConnection.DisposeAsync(); } + if (RabbitMqChannel != null) { await RabbitMqChannel.DisposeAsync().ConfigureAwait(false); } + if (RabbitMqConnection != null) { await RabbitMqConnection.DisposeAsync().ConfigureAwait(false); } } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs new file mode 100644 index 0000000..2ce1a04 --- /dev/null +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs @@ -0,0 +1,7 @@ +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets +{ + public struct BusMarker + { + + } +} \ No newline at end of file diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs new file mode 100644 index 0000000..0c0bfe7 --- /dev/null +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs @@ -0,0 +1,7 @@ +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets +{ + public struct QueueMarker + { + + } +} \ No newline at end of file diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Savvyio.Extensions.DependencyInjection.NATS.Tests.csproj b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Savvyio.Extensions.DependencyInjection.NATS.Tests.csproj new file mode 100644 index 0000000..7ad77eb --- /dev/null +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Savvyio.Extensions.DependencyInjection.NATS.Tests.csproj @@ -0,0 +1,12 @@ + + + + Savvyio.Extensions.DependencyInjection.NATS + + + + + + + + diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs new file mode 100644 index 0000000..6ae9e68 --- /dev/null +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs @@ -0,0 +1,137 @@ +using Codebelt.Extensions.Xunit; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.Commands; +using Savvyio.EventDriven; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.DependencyInjection.NATS.Assets; +using Savvyio.Extensions.DependencyInjection.NATS.Commands; +using Savvyio.Extensions.DependencyInjection.NATS.EventDriven; +using Savvyio.Extensions.NATS.Commands; +using Savvyio.Extensions.NATS.EventDriven; +using Savvyio.Extensions.Text.Json; +using Savvyio.Messaging; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.DependencyInjection.NATS +{ + public class ServiceCollectionExtensionsTest : Test + { + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddNatsCommandQueue_ShouldRegisterNatsCommandQueueAndConfigureOptions() + { + // Arrange + var services = new ServiceCollection(); + bool natsSetupCalled = false; + + // Act + services.AddMarshaller(); + services.AddNatsCommandQueue(options => + { + natsSetupCalled = true; + options.StreamName = "stream"; + options.ConsumerName = "consumer"; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + var queue = provider.GetService(); + + + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + + Assert.NotNull(queue); + } + + [Fact] + public void AddNatsCommandQueue_Generic_ShouldRegisterNatsCommandQueueAndConfigureOptions() + { + // Arrange + var services = new ServiceCollection(); + bool natsSetupCalled = false; + + // Act + services.AddMarshaller(); + services.AddNatsCommandQueue(options => + { + natsSetupCalled = true; + options.StreamName = "stream"; + options.ConsumerName = "consumer"; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + var queue = provider.GetService>(); + + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + + Assert.NotNull(queue); + } + + [Fact] + public void AddNatsEventBus_ShouldRegisterNatsEventBusAndConfigureOptions() + { + // Arrange + var services = new ServiceCollection(); + bool natsSetupCalled = false; + + // Act + services.AddMarshaller(); + services.AddNatsEventBus(options => + { + natsSetupCalled = true; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + var bus = provider.GetService(); + + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + + Assert.NotNull(bus); + } + + [Fact] + public void AddNatsEventBus_Generic_ShouldRegisterNatsEventBusAndConfigureOptions() + { + // Arrange + var services = new ServiceCollection(); + bool natsSetupCalled = false; + + // Act + services.AddMarshaller(); + services.AddNatsEventBus(options => + { + natsSetupCalled = true; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + var bus = provider.GetService>(); + + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + + Assert.NotNull(bus); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs new file mode 100644 index 0000000..48481a7 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs @@ -0,0 +1,20 @@ +using Savvyio.Commands; + +namespace Savvyio.Extensions.NATS.Assets +{ + internal record CreateMemberCommand : Command + { + public CreateMemberCommand(string name, byte age, string emailAddress) + { + Name = name; + Age = age; + EmailAddress = emailAddress; + } + + public string Name { get; } + + public byte Age { get; } + + public string EmailAddress { get; } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs new file mode 100644 index 0000000..a8bc248 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs @@ -0,0 +1,17 @@ +using Savvyio.EventDriven; + +namespace Savvyio.Extensions.NATS.Assets +{ + public record MemberCreated : IntegrationEvent + { + public MemberCreated(string name, string emailAddress) + { + Name = name; + EmailAddress = emailAddress; + } + + public string Name { get; } + + public string EmailAddress { get; } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs new file mode 100644 index 0000000..61cf422 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs @@ -0,0 +1,208 @@ +using System.Linq; +using System.Threading.Channels; +using System.Threading.Tasks; +using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit.Hosting; +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.Collections.Generic; +using Cuemon.Extensions.IO; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.Commands; +using Savvyio.Commands.Messaging; +using Savvyio.Extensions.DependencyInjection; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS.Assets; +using Savvyio.Extensions.Text.Json; +using Savvyio.Messaging; +using Savvyio.Messaging.Cryptography; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS.Commands +{ + public class NatsCommandQueueJsonSerializerContextTest : Test + { + public NatsCommandQueueJsonSerializerContextTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.AutoAcknowledge = true; + o.Subject = Generate.RandomString(10); + o.StreamName = "queue1"; + o.ConsumerName = "client1"; + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var urn = "https://fancy.io/members".ToUri(); + var message = member.ToMessage(urn, nameof(CreateMemberCommand)); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(message.Yield()).ConfigureAwait(false); + + await Task.Delay(500); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync(); + + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.AutoAcknowledge = true; + o.Subject = Generate.RandomString(10); + o.StreamName = "streamSigned"; + o.ConsumerName = "clientSigned"; + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var urn = "https://fancy.io/members/signed".ToUri(); + var message = member.ToMessage(urn, nameof(CreateMemberCommand)).Sign(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(message.Yield()).ConfigureAwait(false); + + await Task.Delay(500); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = (await receivedMessages.Reader.ReadAsync()) as ISignedMessage; + received.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.StreamName = "stream2"; + o.ConsumerName = "client2"; + o.Subject = Generate.RandomString(10); + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var messages = Generate.RangeOf(100, i => + { + var email = $"{Generate.RandomString(5)}@outlook.com"; + var message = new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); + return message; + }).ToList(); + + var receivedMessages = Channel.CreateUnbounded>(); + + var count1 = 0; + Task.Run(async () => + { + while (count1 < messages.Count) + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + count1++; + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); + } + } + }); + + var count2 = 0; + Task.Run(async () => + { + while (count2 < messages.Count) + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + count2++; + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); + } + } + }); + + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(messages).ConfigureAwait(false); + + await Task.Delay(750); + + TestOutput.WriteLine(count1.ToString()); + TestOutput.WriteLine(count2.ToString()); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAllAsync().ToListAsync(); + + TestOutput.WriteLine(received.Count.ToString()); + TestOutput.WriteLines(received.Take(10)); + + Assert.Equivalent(messages.Count, received.Count); + Assert.Equivalent(messages, received); + Assert.Equivalent(messages.Select(message => message.Data), received.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received.Select(message => message.Data.Metadata)); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs new file mode 100644 index 0000000..223beb9 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -0,0 +1,190 @@ +using System.Linq; +using System.Threading.Channels; +using System.Threading.Tasks; +using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit.Hosting; +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.Collections.Generic; +using Cuemon.Extensions.IO; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.Commands; +using Savvyio.Commands.Messaging; +using Savvyio.Extensions.DependencyInjection; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS.Assets; +using Savvyio.Extensions.Newtonsoft.Json; +using Savvyio.Messaging; +using Savvyio.Messaging.Cryptography; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS.Commands +{ + public class NatsCommandQueueNewtonsoftJsonSerializerContextTest : Test + { + public NatsCommandQueueNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.AutoAcknowledge = true; + o.Subject = "queue2"; + o.StreamName = "stream"; + o.ConsumerName = "client"; + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var urn = "https://fancy.io/members".ToUri(); + var message = member.ToMessage(urn, nameof(CreateMemberCommand)); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(message.Yield()).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync(); + + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.AutoAcknowledge = true; + o.Subject = Generate.RandomString(10); + o.StreamName = Generate.RandomString(10); + o.ConsumerName = Generate.RandomString(10); + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var urn = "https://fancy.io/members/signed".ToUri(); + var message = member.ToMessage(urn, nameof(CreateMemberCommand)).Sign(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(message.Yield()).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = (await receivedMessages.Reader.ReadAsync()) as ISignedMessage; + received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => + { + o.StreamName = "stream"; + o.ConsumerName = "client"; + o.Subject = Generate.RandomString(10); + }); + }); + + var queue = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var messages = Generate.RangeOf(100, i => + { + var email = $"{Generate.RandomString(5)}@outlook.com"; + var message = new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); + return message; + }).ToList(); + + var receivedMessages = Channel.CreateUnbounded>(); + + var count = 0; + Task.Run(async () => + { + while (count < messages.Count) + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) + { + count++; + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); + } + } + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await queue.SendAsync(messages).ConfigureAwait(false); + + await Task.Delay(750); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAllAsync().ToListAsync(); + + TestOutput.WriteLine(received.Count.ToString()); + TestOutput.WriteLines(received.Take(10)); + + Assert.Equivalent(messages.Count, received.Count); + Assert.Equivalent(messages, received); + Assert.Equivalent(messages.Select(message => message.Data), received.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received.Select(message => message.Data.Metadata)); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs new file mode 100644 index 0000000..ad0aedc --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs @@ -0,0 +1,298 @@ +using System.Linq; +using System.Threading.Channels; +using System.Threading.Tasks; +using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit.Hosting; +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.IO; +using Cuemon.Threading; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.EventDriven; +using Savvyio.EventDriven.Messaging; +using Savvyio.EventDriven.Messaging.CloudEvents; +using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; +using Savvyio.Extensions.DependencyInjection; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS.Assets; +using Savvyio.Extensions.Text.Json; +using Savvyio.Messaging; +using Savvyio.Messaging.Cryptography; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS.EventDriven +{ + public class NatsEventBusJsonSerializerContextTest : Test + { + public NatsEventBusJsonSerializerContextTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event"); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync(); + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.signed").Sign(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ISignedMessage; + received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Signature, received.Signature); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-cloud-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.cloud-event").ToCloudEvent(); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ICloudEvent; + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Specversion, received.Specversion); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ISignedCloudEvent; + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Specversion, received.Specversion); + Assert.Equivalent(message.Signature, received.Signature); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var messages = Generate.RangeOf(100, _ => + { + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}"); + }).ToList(); + var receivedMessages1 = Channel.CreateUnbounded>(); + var receivedMessages2 = Channel.CreateUnbounded>(); + + var handlerInvocations1 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + await Task.Delay(750); + + receivedMessages1.Writer.Complete(); // mark channel write is complete + receivedMessages2.Writer.Complete(); // mark channel write is complete + + var received1 = await receivedMessages1.Reader.ReadAllAsync().ToListAsync(); + var received2 = await receivedMessages2.Reader.ReadAllAsync().ToListAsync(); + + TestOutput.WriteLine(received1.Count.ToString()); + TestOutput.WriteLines(received1.Take(10).Select(m => marshaller.Serialize(m).ToEncodedString())); + + Assert.Equal(100, handlerInvocations1); + Assert.Equal(100, handlerInvocations2); + Assert.Equivalent(messages.Count, received1.Count); + Assert.Equivalent(messages, received1); + Assert.Equivalent(messages, received2); + Assert.Equivalent(messages.Select(message => message.Data), received1.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received1.Select(message => message.Data.Metadata)); + Assert.Equivalent(messages.Select(message => message.Data), received2.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received2.Select(message => message.Data.Metadata)); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs new file mode 100644 index 0000000..b7562bd --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs @@ -0,0 +1,298 @@ +using System.Linq; +using System.Threading.Channels; +using System.Threading.Tasks; +using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit.Hosting; +using Cuemon; +using Cuemon.Extensions; +using Cuemon.Extensions.IO; +using Cuemon.Threading; +using Microsoft.Extensions.DependencyInjection; +using Savvyio.EventDriven; +using Savvyio.EventDriven.Messaging; +using Savvyio.EventDriven.Messaging.CloudEvents; +using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; +using Savvyio.Extensions.DependencyInjection; +using Savvyio.Extensions.DependencyInjection.Messaging; +using Savvyio.Extensions.NATS.Assets; +using Savvyio.Extensions.Newtonsoft.Json; +using Savvyio.Messaging; +using Savvyio.Messaging.Cryptography; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS.EventDriven +{ + public class NatsEventBusNewtonsoftJsonSerializerContextTest : Test + { + public NatsEventBusNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event"); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync(); + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.signed").Sign(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message).ConfigureAwait(false); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ISignedMessage; + received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Signature, received.Signature); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.cloud-event").ToCloudEvent(); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ICloudEvent; + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Specversion, received.Specversion); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var member = new MemberCreated("John Doe", "jd@outlook.com"); + var urn = "urn:member-events-one".ToUri(); + var message = member.ToMessage(urn, $"{nameof(MemberCreated)}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var receivedMessages = Channel.CreateUnbounded>(); + + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); + + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await bus.PublishAsync(message); + + await Task.Delay(200); + + receivedMessages.Writer.Complete(); // mark channel write is complete + + var received = await receivedMessages.Reader.ReadAsync() as ISignedCloudEvent; + + Assert.Equal(1, handlerInvocations); + Assert.Equivalent(message.Data, received.Data); + Assert.Equivalent(message.Time, received.Time); + Assert.Equivalent(message.Source, received.Source); + Assert.Equivalent(message.Id, received.Id); + Assert.Equivalent(message.Type, received.Type); + Assert.Equivalent(message.Specversion, received.Specversion); + Assert.Equivalent(message.Signature, received.Signature); + } + + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => + { + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => o.Subject = Generate.RandomString(10)); + }); + + var bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); + + var messages = Generate.RangeOf(100, _ => + { + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}"); + }).ToList(); + var receivedMessages1 = Channel.CreateUnbounded>(); + var receivedMessages2 = Channel.CreateUnbounded>(); + + var handlerInvocations1 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => + { + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + await Task.Delay(200); // wait briefly to ensure subscription setup + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + await Task.Delay(750); + + receivedMessages1.Writer.Complete(); // mark channel write is complete + receivedMessages2.Writer.Complete(); // mark channel write is complete + + var received1 = await receivedMessages1.Reader.ReadAllAsync().ToListAsync(); + var received2 = await receivedMessages2.Reader.ReadAllAsync().ToListAsync(); + + TestOutput.WriteLine(received1.Count.ToString()); + TestOutput.WriteLines(received1.Take(10)); + + Assert.Equal(100, handlerInvocations1); + Assert.Equal(100, handlerInvocations2); + Assert.Equivalent(messages.Count, received1.Count); + Assert.Equivalent(messages, received1); + Assert.Equivalent(messages, received2); + Assert.Equivalent(messages.Select(message => message.Data), received1.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received1.Select(message => message.Data.Metadata)); + Assert.Equivalent(messages.Select(message => message.Data), received2.Select(message => message.Data)); + Assert.Equivalent(messages.Select(message => message.Data.Metadata), received2.Select(message => message.Data.Metadata)); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Savvyio.Extensions.NATS.FunctionalTests.csproj b/test/Savvyio.Extensions.NATS.FunctionalTests/Savvyio.Extensions.NATS.FunctionalTests.csproj new file mode 100644 index 0000000..bdeefd8 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Savvyio.Extensions.NATS.FunctionalTests.csproj @@ -0,0 +1,21 @@ + + + + Savvyio.Extensions.NATS + + + + + + + + + + + + + + + + + diff --git a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs new file mode 100644 index 0000000..2d864fc --- /dev/null +++ b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs @@ -0,0 +1,165 @@ +using Codebelt.Extensions.Xunit; +using System; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS.Commands +{ + public class NatsCommandQueueOptionsTest : Test + { + public NatsCommandQueueOptionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Constructor_Sets_Default_Values() + { + var options = new NatsCommandQueueOptions(); + + Assert.Equal(25, options.MaxMessages); + Assert.Equal(TimeSpan.Zero, options.Heartbeat); + Assert.Equal(TimeSpan.Zero, options.Expires); + Assert.Null(options.StreamName); + Assert.Null(options.ConsumerName); + Assert.False(options.AutoAcknowledge); + } + + [Theory] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(25, 25)] + [InlineData(32767, 32767)] + [InlineData(40000, 32767)] + public void MaxMessages_Clamps_Value(int input, int expected) + { + var options = new NatsCommandQueueOptions + { + MaxMessages = input + }; + + Assert.Equal(expected, options.MaxMessages); + } + + [Fact] + public void Expires_Sets_Heartbeat_When_Expires_AtLeast_30Seconds() + { + var options = new NatsCommandQueueOptions(); + + options.Expires = TimeSpan.FromSeconds(29); + Assert.Equal(TimeSpan.FromSeconds(29), options.Expires); + Assert.Equal(TimeSpan.Zero, options.Heartbeat); + + options.Expires = TimeSpan.FromSeconds(30); + Assert.Equal(TimeSpan.FromSeconds(30), options.Expires); + Assert.Equal(TimeSpan.FromSeconds(5), options.Heartbeat); + + options.Expires = TimeSpan.FromSeconds(60); + Assert.Equal(TimeSpan.FromSeconds(60), options.Expires); + Assert.Equal(TimeSpan.FromSeconds(5), options.Heartbeat); + } + + [Fact] + public void Heartbeat_Can_Be_Set_Manually() + { + var options = new NatsCommandQueueOptions + { + Heartbeat = TimeSpan.FromSeconds(10) + }; + + Assert.Equal(TimeSpan.FromSeconds(10), options.Heartbeat); + } + + [Fact] + public void StreamName_And_ConsumerName_Can_Be_Set_And_Gotten() + { + var options = new NatsCommandQueueOptions + { + StreamName = "stream", + ConsumerName = "consumer" + }; + + Assert.Equal("stream", options.StreamName); + Assert.Equal("consumer", options.ConsumerName); + } + + [Fact] + public void AutoAcknowledge_Can_Be_Set_And_Gotten() + { + var options = new NatsCommandQueueOptions + { + AutoAcknowledge = true + }; + + Assert.True(options.AutoAcknowledge); + } + + [Fact] + public void ValidateOptions_Throws_If_StreamName_Is_Null_Or_Whitespace() + { + var options = new NatsCommandQueueOptions + { + StreamName = null, + ConsumerName = "consumer" + }; + + Assert.Throws(() => options.ValidateOptions()); + + options.StreamName = ""; + Assert.Throws(() => options.ValidateOptions()); + + options.StreamName = " "; + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_Throws_If_ConsumerName_Is_Null_Or_Whitespace() + { + var options = new NatsCommandQueueOptions + { + StreamName = "stream", + ConsumerName = null + }; + + Assert.Throws(() => options.ValidateOptions()); + + options.ConsumerName = ""; + Assert.Throws(() => options.ValidateOptions()); + + options.ConsumerName = " "; + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_Throws_If_Base_Options_Invalid() + { + var options = new NatsCommandQueueOptions + { + StreamName = "stream", + ConsumerName = "consumer", + Subject = null // base class property + }; + + // NatsMessageOptions.ValidateOptions throws if Subject is null or whitespace + Assert.Throws(() => options.ValidateOptions()); + + options.Subject = "subject"; + options.NatsUrl = null; // base class property + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_Does_Not_Throw_If_Valid() + { + var options = new NatsCommandQueueOptions + { + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject", + NatsUrl = new Uri("nats://localhost:4222") + }; + + var ex = Record.Exception(() => options.ValidateOptions()); + Assert.Null(ex); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs new file mode 100644 index 0000000..39d0981 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs @@ -0,0 +1,63 @@ +using System; +using Codebelt.Extensions.Xunit; +using Xunit; +using Xunit.Abstractions; + +namespace Savvyio.Extensions.NATS +{ + public class NatsMessageOptionsTest : Test + { + public NatsMessageOptionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Constructor_Sets_Default_Values() + { + var options = new NatsMessageOptions(); + + Assert.Equal(new Uri("nats://127.0.0.1:4222"), options.NatsUrl); + Assert.Null(options.Subject); + } + + [Fact] + public void ValidateOptions_Throws_When_NatsUrl_Is_Null() + { + var options = new NatsMessageOptions + { + NatsUrl = null, + Subject = "subject" + }; + + Assert.Throws(() => options.ValidateOptions()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void ValidateOptions_Throws_When_Subject_Is_Null_Or_Whitespace(string subject) + { + var options = new NatsMessageOptions + { + NatsUrl = new Uri("nats://localhost:4222"), + Subject = subject + }; + + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_Does_Not_Throw_When_Valid() + { + var options = new NatsMessageOptions + { + NatsUrl = new Uri("nats://localhost:4222"), + Subject = "valid-subject" + }; + + var ex = Record.Exception(() => options.ValidateOptions()); + Assert.Null(ex); + } + } +} diff --git a/test/Savvyio.Extensions.NATS.Tests/Savvyio.Extensions.NATS.Tests.csproj b/test/Savvyio.Extensions.NATS.Tests/Savvyio.Extensions.NATS.Tests.csproj new file mode 100644 index 0000000..753ce51 --- /dev/null +++ b/test/Savvyio.Extensions.NATS.Tests/Savvyio.Extensions.NATS.Tests.csproj @@ -0,0 +1,15 @@ + + + + Savvyio.Extensions.NATS + + + + + + + + + + + diff --git a/testenvironments.json b/testenvironments.json index 896dbee..70bd2ed 100644 --- a/testenvironments.json +++ b/testenvironments.json @@ -9,7 +9,7 @@ { "name": "Docker-Ubuntu", "type": "docker", - "dockerImage": "gimlichael/ubuntu-testrunner:net8.0.411-9.0.301", + "dockerImage": "gimlichael/ubuntu-testrunner:net8.0.413-9.0.304", "dockerArgs": "-e AWS__CallerIdentity -e AWS__IAM__AccessKey -e AWS__IAM__SecretKey" } ]