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.
+
+
+
+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.
+
+
+
+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/) |  |  |  |
| [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/) |  |  |  |
@@ -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/) |  |  |  |
| [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/) |  |  |  |
@@ -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"
}
]