From a37ac666142fd9d7929176bd71c4a218aa5683ea Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:42 +0200 Subject: [PATCH 01/36] =?UTF-8?q?=F0=9F=94=A7=20target=20net11.0=20and=20d?= =?UTF-8?q?rop=20net9.0=20baseline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves the shared build baseline from net9.0 and net10.0 to net11.0 and net10.0, including the test target selection in CI. The net9.0-only System.Linq.Async reference in Savvyio.Messaging is removed because both remaining targets provide async LINQ. --- Directory.Build.props | 6 +++--- src/Savvyio.Messaging/Savvyio.Messaging.csproj | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8ce7f192..f60da6f7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ - net10.0;net9.0 + net11.0;net10.0 Copyright © Geekle 2021-2026. All rights reserved. gimlichael Geekle @@ -51,11 +51,11 @@ - net10.0 + net11.0 - net10.0;net9.0 + net11.0;net10.0 diff --git a/src/Savvyio.Messaging/Savvyio.Messaging.csproj b/src/Savvyio.Messaging/Savvyio.Messaging.csproj index 949f1787..cc7dbfce 100644 --- a/src/Savvyio.Messaging/Savvyio.Messaging.csproj +++ b/src/Savvyio.Messaging/Savvyio.Messaging.csproj @@ -5,10 +5,6 @@ messaging signed acknowledgeable asyncenumerable asyncenumerator - - - - From 95097e2c735737dec930f9ee48c01370de08fc80 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:47 +0200 Subject: [PATCH 02/36] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20package=20?= =?UTF-8?q?versions=20for=20net11=20baseline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds net11 package versions for the Entity Framework Core, SQLite, logging, and cryptography dependencies, moves the net9-specific pins out, and refreshes AWS SDK, Dapper, and Coverlet versions to their latest stable releases. --- Directory.Packages.props | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index d33419e8..c96d061a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,8 +4,8 @@ true - - + + @@ -20,12 +20,10 @@ - - + - - + @@ -39,15 +37,18 @@ - - - - - + + + + + + + - + + From 156da9c73af6fc3cb3fe4919f508e45f69c7cdd5 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:47 +0200 Subject: [PATCH 03/36] =?UTF-8?q?=F0=9F=91=B7=20provision=20preview=20sdk?= =?UTF-8?q?=20and=20test=20net11=20in=20ci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CI pipeline now installs preview .NET SDKs so the net11.0 target can build and test before it is generally available across all runners. --- .github/workflows/ci-pipeline.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 2cfd30bf..46a3a37c 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -86,6 +86,7 @@ jobs: configuration: [Debug, Release] uses: codebeltnet/jobs-dotnet-build/.github/workflows/default.yml@v3 with: + include-preview: true runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} configuration: ${{ matrix.configuration }} strong-name-key-filename: ${{ needs.init.outputs.strong-name-key-filename }} @@ -101,6 +102,7 @@ jobs: configuration: [Debug, Release] uses: codebeltnet/jobs-dotnet-pack/.github/workflows/default.yml@v3 with: + include-preview: true configuration: ${{ matrix.configuration }} version: ${{ needs.build.outputs.version }} download-build-artifact-pattern: build-${{ matrix.configuration }}-X64 @@ -116,6 +118,7 @@ jobs: project: ${{ fromJson(needs.prepare_test.outputs.json) }} uses: codebeltnet/jobs-dotnet-test/.github/workflows/default.yml@v3 with: + include-preview: true runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} configuration: ${{ matrix.configuration }} projects: ${{ matrix.project }} @@ -135,6 +138,7 @@ jobs: project: ${{ fromJson(needs.prepare_test.outputs.json) }} uses: codebeltnet/jobs-dotnet-test/.github/workflows/default.yml@v3 with: + include-preview: true runs-on: ${{ matrix.arch == 'ARM64' && 'windows-11-arm' || 'windows-2025' }} configuration: ${{ matrix.configuration }} projects: ${{ matrix.project }} @@ -155,6 +159,7 @@ jobs: project: ${{ fromJson(needs.prepare_test.outputs.json) }} uses: codebeltnet/jobs-dotnet-test/.github/workflows/default.yml@v3 with: + include-preview: true runs-on: ${{ matrix.arch == 'ARM64' && 'macos-26' || 'macos-26-intel' }} configuration: ${{ matrix.configuration }} projects: ${{ matrix.project }} @@ -224,6 +229,8 @@ jobs: - name: Install .NET uses: codebeltnet/install-dotnet@v3 + with: + includePreview: true - name: Install .NET Tool - Report Generator uses: codebeltnet/dotnet-tool-install-reportgenerator@v1 @@ -262,6 +269,8 @@ jobs: - name: Install .NET uses: codebeltnet/install-dotnet@v3 + with: + includePreview: true - name: Install .NET Tool - Report Generator uses: codebeltnet/dotnet-tool-install-reportgenerator@v1 @@ -311,6 +320,8 @@ jobs: - name: Install .NET uses: codebeltnet/install-dotnet@v3 + with: + includePreview: true - name: Install .NET Tool - Report Generator uses: codebeltnet/dotnet-tool-install-reportgenerator@v1 @@ -351,6 +362,7 @@ jobs: needs: [init, build, test_qualitygate, integration_test, integration_test_rabbitmq, integration_test_nats] uses: codebeltnet/jobs-sonarcloud/.github/workflows/default.yml@v3 with: + include-preview: true organization: geekle projectKey: savvyio version: ${{ needs.build.outputs.version }} @@ -370,6 +382,8 @@ jobs: name: call-codeql needs: [init, build, test_qualitygate, integration_test, integration_test_rabbitmq, integration_test_nats] uses: codebeltnet/jobs-codeql/.github/workflows/default.yml@v3 + with: + include-preview: true permissions: security-events: write From 0c67aae022e9db7ebb251e1c06f56638c1a8c96d Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:47 +0200 Subject: [PATCH 04/36] =?UTF-8?q?=F0=9F=91=B7=20preserve=20pending=20relea?= =?UTF-8?q?se=20versions=20in=20service=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The service update automation now keeps an explicitly planned TBD minor or major version instead of resetting it to the next patch, and avoids duplicating an existing pending release block in PackageReleaseNotes.txt. --- .github/workflows/service-update.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/service-update.yml b/.github/workflows/service-update.yml index 1f695860..3a0877fa 100644 --- a/.github/workflows/service-update.yml +++ b/.github/workflows/service-update.yml @@ -83,9 +83,11 @@ jobs: print(f"::error::Unsupported CHANGELOG.md version status: {current_status}") sys.exit(1) - if current_version == next_version and current_status.upper() == "TBD": - # Reuse an already pending next release, such as [5.0.13] - TBD. - new_version = next_version + pending_version = tuple(int(part) for part in current_version.split(".")) + released_version = (major, minor, patch) + if pending_version > released_version and current_status.upper() == "TBD": + # Preserve an explicitly planned patch, minor, or major release. + new_version = current_version elif current_version == latest_version and current_status.upper() != "TBD": # The changelog is at the latest released tag; start the next patch release. new_version = next_version @@ -93,7 +95,7 @@ jobs: print( f"::error::CHANGELOG.md starts at {current_version} ({current_status}), " f"but the latest stable Git tag is {latest_tag}. Expected either " - f"[{latest_version}] with a release date or [{next_version}] - TBD." + f"[{latest_version}] with a release date or a newer version marked TBD." ) sys.exit(1) @@ -125,7 +127,9 @@ jobs: NEW="${{ steps.newver.outputs.new }}" for f in .nuget/*/PackageReleaseNotes.txt; do [ -f "$f" ] || continue - TFM=$(grep -m1 "^Availability:" "$f" | sed 's/Availability: //' || echo ".NET 10, .NET 9 and .NET Standard 2.0") + # Preserve an existing pending release block instead of duplicating it. + if [ "$(head -n1 "$f" | tr -d '\r')" = "Version: ${NEW}" ]; then continue; fi + TFM=$(grep -m1 "^Availability:" "$f" | sed 's/Availability: //' || echo ".NET 11 and .NET 10") ENTRY="Version: ${NEW}\nAvailability: ${TFM}\n\n# ALM\n- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs)\n\n" { printf "$ENTRY"; cat "$f"; } > "$f.tmp" && mv "$f.tmp" "$f" done From 6860c8e0290fb98ab4f0e84d1a022dcdb75d8022 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:48 +0200 Subject: [PATCH 05/36] =?UTF-8?q?=F0=9F=94=A5=20remove=20legacy=20test=20c?= =?UTF-8?q?ontainer=20dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Dockerfile used to run tests against the .NET 10 SDK with a .NET 9 runtime, which is no longer needed once net9.0 support is dropped. --- Dockerfile.tests | 54 ------------------------------------------------ 1 file changed, 54 deletions(-) delete mode 100644 Dockerfile.tests diff --git a/Dockerfile.tests b/Dockerfile.tests deleted file mode 100644 index 644c40dc..00000000 --- a/Dockerfile.tests +++ /dev/null @@ -1,54 +0,0 @@ -# syntax=docker/dockerfile:1.7 - -ARG DOTNET_VERSION=10.0 -ARG UBUNTU_FLAVOR=noble - -FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-${UBUNTU_FLAVOR} - -ARG DOTNET_VERSION - -ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \ - DOTNET_NOLOGO=1 \ - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 \ - NUGET_XMLDOC_MODE=skip \ - CI=false - -WORKDIR /work - -# The .NET 10 SDK can build net9.0, but it does not include the net9.0 runtime. -# Your local test projects target both net10.0 and net9.0 when CI != true. -RUN if [ "${DOTNET_VERSION}" = "10.0" ]; then \ - apt-get update \ - && apt-get install -y --no-install-recommends curl ca-certificates git \ - && curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh \ - && chmod +x /tmp/dotnet-install.sh \ - && /tmp/dotnet-install.sh --channel 9.0 --runtime dotnet --install-dir /usr/share/dotnet \ - && rm -rf /tmp/dotnet-install.sh /var/lib/apt/lists/*; \ - else \ - apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates git \ - && rm -rf /var/lib/apt/lists/*; \ - fi - -COPY . . - -ENTRYPOINT ["/bin/bash", "-lc"] - -CMD [ "\ - set -euo pipefail; \ - project=\"${TEST_PROJECT:-Savvyio.slnx}\"; \ - configuration=\"${CONFIGURATION:-Debug}\"; \ - framework=\"${TEST_FRAMEWORK:-}\"; \ - filter=\"${TEST_FILTER:-}\"; \ - echo \"Architecture: $(uname -m)\"; \ - echo \"Project: $project\"; \ - echo \"Configuration: $configuration\"; \ - echo \"Framework: ${framework:-all}\"; \ - dotnet --info; \ - dotnet restore \"$project\"; \ - args=(dotnet test \"$project\" --no-restore --configuration \"$configuration\" -p:SkipSignAssembly=true --logger \"console;verbosity=normal\"); \ - if [ -n \"$framework\" ]; then args+=(--framework \"$framework\"); fi; \ - if [ -n \"$filter\" ]; then args+=(--filter \"$filter\"); fi; \ - printf 'Command: '; printf '%q ' \"${args[@]}\"; echo; \ - \"${args[@]}\" \ -" ] From f1746cc9392d2a95f8b34e7301d245d4f428112c Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:48 +0200 Subject: [PATCH 06/36] =?UTF-8?q?=F0=9F=93=9A=20update=20docfx=20availabil?= =?UTF-8?q?ity=20and=20namespace=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates the modern availability include to .NET 11 and .NET 10, and renders namespace child types as definition lists so each type summary reads as a single entry. --- .docfx/includes/availability-modern.md | 2 +- .docfx/templates/savvyio/partials/namespace.tmpl.partial | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.docfx/includes/availability-modern.md b/.docfx/includes/availability-modern.md index af5cf4b9..db9549d4 100644 --- a/.docfx/includes/availability-modern.md +++ b/.docfx/includes/availability-modern.md @@ -1 +1 @@ -Availability: .NET 10 and .NET 9 \ No newline at end of file +Availability: .NET 11 and .NET 10 \ No newline at end of file diff --git a/.docfx/templates/savvyio/partials/namespace.tmpl.partial b/.docfx/templates/savvyio/partials/namespace.tmpl.partial index 173b006c..53bd779d 100644 --- a/.docfx/templates/savvyio/partials/namespace.tmpl.partial +++ b/.docfx/templates/savvyio/partials/namespace.tmpl.partial @@ -8,7 +8,9 @@ {{#children}}

{{>partials/namespaceSubtitle}}

{{#children}} -

-
{{{summary}}}
+
+
+
{{{summary}}}
+
{{/children}} -{{/children}} \ No newline at end of file +{{/children}} From 42e4f008525731dd324c15bc4fc6f9186f7e42da Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:52 +0200 Subject: [PATCH 07/36] =?UTF-8?q?=F0=9F=93=9D=20update=20readme=20and=20ag?= =?UTF-8?q?ents=20guidance=20for=20net11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The root README and agent guidance describe the library as targeting .NET 10 and .NET 11, matching the new target framework baseline. --- AGENTS.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 32523016..b23aba2c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ This document provides guidance for AI agents working in the Savvy I/O repositor **Savvy I/O** is an open-source .NET class library (MIT license) providing a SOLID and clean foundation for writing DDD (Domain-Driven Design), CQRS (Command Query Responsibility Segregation), and Event Sourcing applications. It is designed to be intuitive and removes the complexity normally associated with these architectural patterns. -The solution targets .NET 10.0 and .NET 9.0. It comprises: +The solution targets .NET 11.0 and .NET 10.0. It comprises: - **Core Libraries** — DDD, CQRS, Commands, Queries, Event-Driven, and Domain Event Sourcing - **Data Access Extensions** — Support for Dapper, Entity Framework Core diff --git a/README.md b/README.md index 8e99610a..95a5c235 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. From 9c8f29730dacea757d6e77ab23900945defda854 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:52 +0200 Subject: [PATCH 08/36] =?UTF-8?q?=F0=9F=92=AC=20record=206.0.0=20changelog?= =?UTF-8?q?=20and=20contributing=20targets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the .NET 11 baseline change, the removal of .NET 9 support, and the service automation changes in the changelog, and updates contributor guidance to list net11.0 as the CI target. --- .github/CONTRIBUTING.md | 4 ++-- CHANGELOG.md | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a4506aca..6c72b7d1 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -5,7 +5,7 @@ This repository is part of the Codebelt .NET library estate. The instructions be ## Before you start - Read the repository `README.md` and open an issue before starting a non-trivial feature or behavioral change. -- Use an installed .NET SDK that can build the target frameworks listed below. This repository currently targets: **net10.0, net9.0**. +- Use an installed .NET SDK that can build the target frameworks listed below. This repository currently targets: **net11.0, net10.0**. - The solution is `Savvyio.slnx`. Central package versions are maintained in `Directory.Packages.props`. - The shared build behavior is in `Directory.Build.props` and `Directory.Build.targets`; repository-specific TFMs, package references and metadata remain local to this library. @@ -40,7 +40,7 @@ foreach ($project in $testProjects) { } ``` -The CI test plan currently runs **28** project(s) and excludes **8** project(s). The workflow also has an optional macOS test job. +The CI test plan currently runs **28** project(s) and excludes **8** project(s). The workflow also has an optional macOS test job. CI tests the newest supported framework (net11.0); local runs cover both net11.0 and net10.0. Run cloud integration projects one framework at a time with `--framework` because their queues are shared across targets. ## Integration and infrastructure diff --git a/CHANGELOG.md b/CHANGELOG.md index 72312a73..0b688596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ 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. +## [6.0.0] - 2026-11-10 + +### Added + +- .NET 11 support alongside .NET 10 across packages and tests, with matching .NET 11 Entity Framework Core, SQLite, logging abstractions, and cryptography dependencies for net11.0. + +### Changed + +- CI provisions preview SDKs and tests .NET 11, preserving the single-target CI policy; local tests cover both supported targets; the local test container uses the .NET 11 SDK with the .NET 10 runtime and Microsoft Testing Platform arguments. +- Updated Codebelt.Coverlet.MTP from 10.1.0 to 10.1.1. +- Updated framework availability in contributor guidance, package READMEs, and DocFX includes; retained .NET 10 for DocFX metadata generation. +- Service-update automation preserves pending major/minor release versions and uses the modern framework availability fallback. +- Set the MinVer minimum major/minor to 6.0 for the breaking framework baseline change; release versions remain Git-tag derived. + +### Removed + +- .NET 9 support. Consumers must target .NET 10 or later. +- The .NET 9-only System.Linq.Async reference; both supported frameworks provide async LINQ. + ## [5.0.13] - 2026-10-18 This is a patch release focused on DocFX publishing pipeline hardening, expanded test coverage for configured options, discovery, and JSON converters, shared dependency and Entity Framework Core updates, documentation sitemap correction, and consolidated repository agent guidance. From 1b7fa2f47cee9c426fd9d70915b146b47637017b Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:55 +0200 Subject: [PATCH 09/36] =?UTF-8?q?=F0=9F=93=A6=20add=20net11=20release=20no?= =?UTF-8?q?tes=20for=206.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a 6.0.0 release notes block to each package describing the .NET 11 target addition and the .NET 9 removal, so consumers see the breaking framework baseline in NuGet package notes. --- .nuget/Savvyio.App/PackageReleaseNotes.txt | 9 +++++++++ .../Savvyio.Commands.Messaging/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Commands/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Core/PackageReleaseNotes.txt | 9 +++++++++ .../Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Domain/PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.EventDriven/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt | 9 +++++++++ .../PackageReleaseNotes.txt | 9 +++++++++ .../Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Messaging/PackageReleaseNotes.txt | 9 +++++++++ .nuget/Savvyio.Queries/PackageReleaseNotes.txt | 9 +++++++++ 35 files changed, 315 insertions(+) diff --git a/.nuget/Savvyio.App/PackageReleaseNotes.txt b/.nuget/Savvyio.App/PackageReleaseNotes.txt index 06429e8d..f1b4ba23 100644 --- a/.nuget/Savvyio.App/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.App/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt index 0d457acb..de1ca3d6 100644 --- a/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Commands.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Commands/PackageReleaseNotes.txt b/.nuget/Savvyio.Commands/PackageReleaseNotes.txt index 6107ea05..a0b74ec5 100644 --- a/.nuget/Savvyio.Commands/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Commands/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Core/PackageReleaseNotes.txt b/.nuget/Savvyio.Core/PackageReleaseNotes.txt index c34b63cd..0f0aab1a 100644 --- a/.nuget/Savvyio.Core/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Core/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt index 96ec7730..66c86bc4 100644 --- a/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Domain/PackageReleaseNotes.txt index ac7af682..e75f2bc6 100644 --- a/.nuget/Savvyio.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Domain/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt index 98cec1d2..33894e0b 100644 --- a/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.EventDriven.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt b/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt index 21e05e49..54a0904a 100644 --- a/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.EventDriven/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt index 6ba8ad2c..b78d1555 100644 --- a/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Dapper/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt index 8ea9bf9c..54ad54e6 100644 --- a/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DapperExtensions/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt index d885004e..5e2d6b84 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt index 75e8ca63..230e946c 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt index b3766401..c875694e 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt index 99b26e3b..4318d76d 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt index 3002b88d..205a21e3 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt index cad7c222..438d7d51 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt index f5236bae..0c5f7722 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt index f45c4e3b..d555ef0c 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt index 256a1e61..995b45b9 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt index b41f3958..68edd787 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt index e428c4e6..3a25a7a8 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt index aad94f70..de5d5f6a 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt index ada4f33d..c5bea99e 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.DependencyInjection/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt index c35cc40a..b8833ecb 100644 --- a/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Dispatchers/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt index 609cf14c..a00e3bcd 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt index 49b842d8..30fab542 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore.Domain/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt index 858e0aa4..2e6aaaa0 100644 --- a/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.EFCore/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt index e1ae9091..e412c5e1 100644 --- a/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.NATS/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt index cc90732d..173236fe 100644 --- a/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Newtonsoft.Json/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt index 26ec1111..2aa6cbc9 100644 --- a/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.QueueStorage/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt index 9038c93c..c43c3f61 100644 --- a/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.RabbitMQ/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt index dacd111e..b0125890 100644 --- a/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.SimpleQueueService/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt b/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt index 9d9062e0..fcfa76f0 100644 --- a/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Extensions.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt b/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt index b5464532..8fcc4e67 100644 --- a/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Messaging/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Savvyio.Queries/PackageReleaseNotes.txt b/.nuget/Savvyio.Queries/PackageReleaseNotes.txt index f53efd74..924b3641 100644 --- a/.nuget/Savvyio.Queries/PackageReleaseNotes.txt +++ b/.nuget/Savvyio.Queries/PackageReleaseNotes.txt @@ -1,3 +1,12 @@ +Version: 6.0.0 +Availability: .NET 11 and .NET 10 + +# ALM +- CHANGED Target frameworks by adding .NET 11 (net11.0) and removing .NET 9 (net9.0), so the package now targets .NET 11 and .NET 10 + +# Breaking Changes +- REMOVED .NET 9 support; consumers must target .NET 10 or later + Version: 5.0.13 Availability: .NET 10 and .NET 9 From 1428e0d42a60a4fb70289cba427ed7484ba334fc Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:28:58 +0200 Subject: [PATCH 10/36] =?UTF-8?q?=F0=9F=93=9D=20update=20package=20readmes?= =?UTF-8?q?=20for=20net11=20targets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Package README files now describe the supported runtime as .NET 10 and .NET 11 instead of .NET 9 and .NET 10, so the NuGet landing pages match the new target framework baseline. --- .nuget/Savvyio.App/README.md | 2 +- .nuget/Savvyio.Commands.Messaging/README.md | 2 +- .nuget/Savvyio.Commands/README.md | 2 +- .nuget/Savvyio.Core/README.md | 2 +- .nuget/Savvyio.Domain.EventSourcing/README.md | 2 +- .nuget/Savvyio.Domain/README.md | 2 +- .nuget/Savvyio.EventDriven.Messaging/README.md | 2 +- .nuget/Savvyio.EventDriven/README.md | 2 +- .nuget/Savvyio.Extensions.Dapper/README.md | 2 +- .nuget/Savvyio.Extensions.DapperExtensions/README.md | 2 +- .nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md | 2 +- .../README.md | 2 +- .nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md | 2 +- .nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md | 2 +- .../README.md | 2 +- .../Savvyio.Extensions.DependencyInjection.Text.Json/README.md | 2 +- .nuget/Savvyio.Extensions.DependencyInjection/README.md | 2 +- .nuget/Savvyio.Extensions.Dispatchers/README.md | 2 +- .nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md | 2 +- .nuget/Savvyio.Extensions.EFCore.Domain/README.md | 2 +- .nuget/Savvyio.Extensions.EFCore/README.md | 2 +- .nuget/Savvyio.Extensions.NATS/README.md | 2 +- .nuget/Savvyio.Extensions.Newtonsoft.Json/README.md | 2 +- .nuget/Savvyio.Extensions.QueueStorage/README.md | 2 +- .nuget/Savvyio.Extensions.RabbitMQ/README.md | 2 +- .nuget/Savvyio.Extensions.SimpleQueueService/README.md | 2 +- .nuget/Savvyio.Extensions.Text.Json/README.md | 2 +- .nuget/Savvyio.Messaging/README.md | 2 +- .nuget/Savvyio.Queries/README.md | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.nuget/Savvyio.App/README.md b/.nuget/Savvyio.App/README.md index b4ab6516..f1f265bd 100644 --- a/.nuget/Savvyio.App/README.md +++ b/.nuget/Savvyio.App/README.md @@ -6,7 +6,7 @@ Provides a complete and convenient set of API additions for building a DDD, CQRS An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Commands.Messaging/README.md b/.nuget/Savvyio.Commands.Messaging/README.md index 756c5395..bad40645 100644 --- a/.nuget/Savvyio.Commands.Messaging/README.md +++ b/.nuget/Savvyio.Commands.Messaging/README.md @@ -6,7 +6,7 @@ Provides ways to scale out Commands using distributed subsystems. An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Commands/README.md b/.nuget/Savvyio.Commands/README.md index 1de46c47..8397652d 100644 --- a/.nuget/Savvyio.Commands/README.md +++ b/.nuget/Savvyio.Commands/README.md @@ -6,7 +6,7 @@ Provides the fundamental classes to work with the Command part of the CQRS patte An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Core/README.md b/.nuget/Savvyio.Core/README.md index fb0d9634..e0605f47 100644 --- a/.nuget/Savvyio.Core/README.md +++ b/.nuget/Savvyio.Core/README.md @@ -6,7 +6,7 @@ Provides the fundamental abstractions and classes for supporting a complete flow An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Domain.EventSourcing/README.md b/.nuget/Savvyio.Domain.EventSourcing/README.md index 03da228a..066fd146 100644 --- a/.nuget/Savvyio.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Domain.EventSourcing/README.md @@ -6,7 +6,7 @@ Provides the default implementation of an Aggregate Root that is Event Sourced e An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Domain/README.md b/.nuget/Savvyio.Domain/README.md index 87c63fbd..7d293032 100644 --- a/.nuget/Savvyio.Domain/README.md +++ b/.nuget/Savvyio.Domain/README.md @@ -6,7 +6,7 @@ Provides the fundamental classes and interfaces to work with the concepts of DDD An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.EventDriven.Messaging/README.md b/.nuget/Savvyio.EventDriven.Messaging/README.md index 9b4b9e2b..d6216d17 100644 --- a/.nuget/Savvyio.EventDriven.Messaging/README.md +++ b/.nuget/Savvyio.EventDriven.Messaging/README.md @@ -6,7 +6,7 @@ Provides ways to scale out Integration Events for a distributed architecture. An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.EventDriven/README.md b/.nuget/Savvyio.EventDriven/README.md index 04eb69a6..5502a25c 100644 --- a/.nuget/Savvyio.EventDriven/README.md +++ b/.nuget/Savvyio.EventDriven/README.md @@ -6,7 +6,7 @@ Provides the fundamental classes to work with the concepts of Integration Events An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.Dapper/README.md b/.nuget/Savvyio.Extensions.Dapper/README.md index 0517da3b..2c1eff2c 100644 --- a/.nuget/Savvyio.Extensions.Dapper/README.md +++ b/.nuget/Savvyio.Extensions.Dapper/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for [Dapper](https://github.co An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DapperExtensions/README.md b/.nuget/Savvyio.Extensions.DapperExtensions/README.md index 9608fe03..809945ed 100644 --- a/.nuget/Savvyio.Extensions.DapperExtensions/README.md +++ b/.nuget/Savvyio.Extensions.DapperExtensions/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for [Dapper](https://github.co An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md index c0147411..5fb6ae52 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Dapper/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with [Dapper](ht An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md index f0851129..cf35db3f 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.DapperExtensions/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with [DapperExte An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md index b7e65e91..9dbe6309 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Domain/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection - optimized for An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md index 73dba87a..f9b4505d 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with [Microsoft An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md index 9ce63f34..ae7ed71f 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore.Domain/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with [Microsoft An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md index 483fbba4..0954bfdb 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.EFCore/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with [Microsoft An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md index b9901ff6..eece543a 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.NATS/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with NATS Work-Q An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/README.md index a7887e59..58afa44c 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with Newtonsoft An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md index 6146bd60..d93ec92d 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.QueueStorage/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with Azure Queue An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md index 9937e37c..b02833bd 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.RabbitMQ/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with RabbitMQ Wo An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md index 029736ae..ae89c6d5 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.SimpleQueueService/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with Amazon Simp An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/README.md b/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/README.md index 6eaf64f6..1fb50281 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection.Text.Json/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for Microsoft Dependency Injection with official bu An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.DependencyInjection/README.md b/.nuget/Savvyio.Extensions.DependencyInjection/README.md index 8b7bd9f2..5a0297bc 100644 --- a/.nuget/Savvyio.Extensions.DependencyInjection/README.md +++ b/.nuget/Savvyio.Extensions.DependencyInjection/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for Microsoft Dependency Injec An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.Dispatchers/README.md b/.nuget/Savvyio.Extensions.Dispatchers/README.md index 6a7e5500..c640f36a 100644 --- a/.nuget/Savvyio.Extensions.Dispatchers/README.md +++ b/.nuget/Savvyio.Extensions.Dispatchers/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with Mediator support to provide a uniform An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md index 024a71b0..66c99632 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md +++ b/.nuget/Savvyio.Extensions.EFCore.Domain.EventSourcing/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for [Microsoft Entity Framework Core](https://githu An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.EFCore.Domain/README.md b/.nuget/Savvyio.Extensions.EFCore.Domain/README.md index 932c393d..3d2790a4 100644 --- a/.nuget/Savvyio.Extensions.EFCore.Domain/README.md +++ b/.nuget/Savvyio.Extensions.EFCore.Domain/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O support for [Microsoft Entity Framework Core](https://githu An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.EFCore/README.md b/.nuget/Savvyio.Extensions.EFCore/README.md index 7b1d9ed3..4edba0f7 100644 --- a/.nuget/Savvyio.Extensions.EFCore/README.md +++ b/.nuget/Savvyio.Extensions.EFCore/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for [Microsoft Entity Framewor An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.NATS/README.md b/.nuget/Savvyio.Extensions.NATS/README.md index f2b6ff77..937117c7 100644 --- a/.nuget/Savvyio.Extensions.NATS/README.md +++ b/.nuget/Savvyio.Extensions.NATS/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for NATS Work-Queue Stream and An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md b/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md index 0b0472dc..ed23d917 100644 --- a/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md +++ b/.nuget/Savvyio.Extensions.Newtonsoft.Json/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for Newtonsoft JSON. An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.QueueStorage/README.md b/.nuget/Savvyio.Extensions.QueueStorage/README.md index 5777dc2f..bf1b9605 100644 --- a/.nuget/Savvyio.Extensions.QueueStorage/README.md +++ b/.nuget/Savvyio.Extensions.QueueStorage/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for Azure Queue Storage paired An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.RabbitMQ/README.md b/.nuget/Savvyio.Extensions.RabbitMQ/README.md index cd33162a..8f8227ac 100644 --- a/.nuget/Savvyio.Extensions.RabbitMQ/README.md +++ b/.nuget/Savvyio.Extensions.RabbitMQ/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for RabbitMQ Work Queue and Ra An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.SimpleQueueService/README.md b/.nuget/Savvyio.Extensions.SimpleQueueService/README.md index bb537325..438c1df5 100644 --- a/.nuget/Savvyio.Extensions.SimpleQueueService/README.md +++ b/.nuget/Savvyio.Extensions.SimpleQueueService/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for Amazon Simple Queue Servic An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Extensions.Text.Json/README.md b/.nuget/Savvyio.Extensions.Text.Json/README.md index 518222c8..a114a261 100644 --- a/.nuget/Savvyio.Extensions.Text.Json/README.md +++ b/.nuget/Savvyio.Extensions.Text.Json/README.md @@ -6,7 +6,7 @@ Extend the Savvy I/O core assemblies with support for official built-in JSON. An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Messaging/README.md b/.nuget/Savvyio.Messaging/README.md index a1024a65..a75d08a4 100644 --- a/.nuget/Savvyio.Messaging/README.md +++ b/.nuget/Savvyio.Messaging/README.md @@ -6,7 +6,7 @@ Provides the fundamental classes to work with Messaging in a distributed archite An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Savvyio.Queries/README.md b/.nuget/Savvyio.Queries/README.md index 747c9d53..769acc05 100644 --- a/.nuget/Savvyio.Queries/README.md +++ b/.nuget/Savvyio.Queries/README.md @@ -6,7 +6,7 @@ Provides the fundamental classes and interfaces to work with the Query part of t An open-source project (MIT license) that provides a SOLID and clean .NET class library for writing DDD, CQRS and Event Sourcing applications. -Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 9` and `.NET 10`. +Your versatile DDD, CQRS and Event Sourcing companion for modern development with `.NET 10` and `.NET 11`. It is, by heart, free, flexible and built to extend and boost your agile codebelt. From a9906fd92d349cde7f0946198775f0ffd011c69a Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:37:08 +0200 Subject: [PATCH 11/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20convert=20namespaces?= =?UTF-8?q?=20to=20file-scoped=20syntax?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Namespace declarations across the solution now use file-scoped syntax, matching the repository style. This is a mechanical change with no behavior impact, and it prepares the codebase for enforcing the rule in .editorconfig. --- .../CommandExtensions.cs | 53 +- .../InMemoryCommandQueue.cs | 57 +- src/Savvyio.Commands/Command.cs | 27 +- src/Savvyio.Commands/CommandDispatcher.cs | 63 ++- src/Savvyio.Commands/CommandHandler.cs | 43 +- .../SavvyioOptionsExtensions.cs | 45 +- src/Savvyio.Core/AsyncEventHandler.cs | 21 +- src/Savvyio.Core/Commands/ICommand.cs | 13 +- .../Commands/ICommandDispatcher.cs | 35 +- src/Savvyio.Core/Commands/ICommandHandler.cs | 15 +- src/Savvyio.Core/Data/IDataStore.cs | 15 +- src/Savvyio.Core/Data/IDeletableDataStore.cs | 27 +- src/Savvyio.Core/Data/IPersistentDataStore.cs | 29 +- src/Savvyio.Core/Data/IReadableDataStore.cs | 28 +- src/Savvyio.Core/Data/ISearchableDataStore.cs | 31 +- src/Savvyio.Core/Data/IWritableDataStore.cs | 41 +- .../Diagnostics/IAsyncHealthCheckProvider.cs | 23 +- .../Diagnostics/IHealthCheckProvider.cs | 21 +- src/Savvyio.Core/Dispatchers/Dispatcher.cs | 37 +- .../Dispatchers/FireForgetDispatcher.cs | 113 ++-- src/Savvyio.Core/Dispatchers/IDispatcher.cs | 13 +- .../Dispatchers/IServiceLocator.cs | 21 +- .../Dispatchers/RequestReplyDispatcher.cs | 119 ++-- .../Dispatchers/ServiceLocator.cs | 45 +- src/Savvyio.Core/Domain/DomainException.cs | 47 +- .../ITracedAggregateRepository.cs | 21 +- .../EventSourcing/ITracedAggregateRoot.cs | 25 +- .../EventSourcing/ITracedDomainEvent.cs | 13 +- .../Domain/IAggregateRepository.cs | 19 +- src/Savvyio.Core/Domain/IAggregateRoot.cs | 61 +- .../Domain/IDeletableRepository.cs | 35 +- src/Savvyio.Core/Domain/IDomainEvent.cs | 13 +- .../Domain/IDomainEventDispatcher.cs | 35 +- .../Domain/IDomainEventHandler.cs | 15 +- src/Savvyio.Core/Domain/IEntity.cs | 17 +- .../Domain/IPersistentRepository.cs | 25 +- .../Domain/IReadableRepository.cs | 29 +- src/Savvyio.Core/Domain/IRepository.cs | 17 +- .../Domain/ISearchableRepository.cs | 29 +- src/Savvyio.Core/Domain/IUnitOfWork.cs | 21 +- .../Domain/IWritableRepository.cs | 35 +- .../EventDriven/IIntegrationEvent.cs | 13 +- .../IIntegrationEventDispatcher.cs | 35 +- .../EventDriven/IIntegrationEventHandler.cs | 15 +- .../Cryptography/ISignedCloudEvent.cs | 19 +- .../Messaging/CloudEvents/ICloudEvent.cs | 27 +- src/Savvyio.Core/HandlerDiscoveryModel.cs | 311 ++++++----- src/Savvyio.Core/HandlerFactory.cs | 57 +- src/Savvyio.Core/HandlerServicesDescriptor.cs | 177 +++--- .../Handlers/FireForgetManager.cs | 67 ++- .../Handlers/FireForgetRegistryExtensions.cs | 25 +- .../Handlers/IFireForgetActivator.cs | 39 +- .../Handlers/IFireForgetHandler.cs | 23 +- .../Handlers/IFireForgetRegistry.cs | 37 +- .../Handlers/IRequestReplyActivator.cs | 45 +- .../Handlers/IRequestReplyHandler.cs | 23 +- .../Handlers/IRequestReplyRegistry.cs | 41 +- .../Handlers/OrphanedHandlerException.cs | 55 +- .../Handlers/RequestReplyManager.cs | 69 ++- .../RequestReplyRegistryExtensions.cs | 27 +- src/Savvyio.Core/IDataSource.cs | 19 +- src/Savvyio.Core/IHandler.cs | 27 +- .../IHandlerServicesDescriptor.cs | 19 +- src/Savvyio.Core/IIdentity.cs | 21 +- src/Savvyio.Core/IMarshaller.cs | 63 ++- src/Savvyio.Core/IMetadata.cs | 19 +- src/Savvyio.Core/IMetadataDictionary.cs | 15 +- src/Savvyio.Core/IRequest.cs | 15 +- .../Messaging/AcknowledgedEventArgs.cs | 51 +- .../Messaging/Cryptography/ISignedMessage.cs | 21 +- .../Messaging/IAcknowledgeable.cs | 37 +- src/Savvyio.Core/Messaging/IMessage.cs | 65 ++- .../Messaging/IPointToPointChannel.cs | 19 +- .../Messaging/IPublishSubscribeChannel.cs | 19 +- src/Savvyio.Core/Messaging/IPublisher.cs | 25 +- src/Savvyio.Core/Messaging/IReceiver.cs | 23 +- src/Savvyio.Core/Messaging/ISender.cs | 25 +- src/Savvyio.Core/Messaging/ISubscriber.cs | 25 +- .../Messaging/SubscribeAsyncOptions.cs | 57 +- src/Savvyio.Core/MetadataDictionary.cs | 371 +++++++------ src/Savvyio.Core/MetadataExtensions.cs | 317 ++++++----- src/Savvyio.Core/MetadataFactory.cs | 81 ++- src/Savvyio.Core/Queries/IQuery.cs | 27 +- src/Savvyio.Core/Queries/IQueryDispatcher.cs | 41 +- src/Savvyio.Core/Queries/IQueryHandler.cs | 15 +- .../Reflection/AssemblyContext.cs | 18 +- src/Savvyio.Core/Request.cs | 35 +- src/Savvyio.Core/SavvyioOptions.cs | 351 ++++++------ src/Savvyio.Core/SavvyioOptionsExtensions.cs | 103 ++-- src/Savvyio.Core/TaskExtensions.cs | 27 +- .../TracedAggregateRoot.cs | 141 +++-- .../TracedDomainEvent.cs | 59 +- .../TracedDomainEventExtensions.cs | 67 ++- src/Savvyio.Domain/Aggregate.cs | 105 ++-- src/Savvyio.Domain/AggregateRoot.cs | 37 +- src/Savvyio.Domain/DomainEvent.cs | 65 ++- src/Savvyio.Domain/DomainEventDispatcher.cs | 63 ++- .../DomainEventDispatcherExtensions.cs | 61 +- src/Savvyio.Domain/DomainEventExtensions.cs | 45 +- src/Savvyio.Domain/DomainEventHandler.cs | 43 +- src/Savvyio.Domain/Entity.cs | 59 +- .../SavvyioOptionsExtensions.cs | 43 +- src/Savvyio.Domain/SingleValueObject.cs | 69 ++- src/Savvyio.Domain/ValueObject.cs | 113 ++-- .../CloudEvents/CloudEvent.cs | 345 ++++++------ .../Cryptography/CloudEventExtensions.cs | 53 +- .../Cryptography/SignedCloudEvent.cs | 49 +- .../SignedCloudEventExtensions.cs | 61 +- .../CloudEvents/MessageExtensions.cs | 35 +- .../InMemoryEventBus.cs | 89 ++- .../IntegrationEventExtensions.cs | 53 +- src/Savvyio.EventDriven/IntegrationEvent.cs | 65 ++- .../IntegrationEventDispatcher.cs | 63 ++- .../IntegrationEventExtensions.cs | 65 ++- .../IntegrationEventHandler.cs | 43 +- .../SavvyioOptionsExtensions.cs | 45 +- .../DapperDataSource.cs | 205 ++++--- .../DapperDataSourceOptions.cs | 49 +- .../DapperDataStore.cs | 125 +++-- .../DapperQueryOptions.cs | 157 +++--- .../IDapperDataSource.cs | 15 +- .../DapperExtensionsDataStore.cs | 123 ++--- .../DapperExtensionsQueryOptions.cs | 181 +++--- .../DapperDataSource.cs | 37 +- .../DapperDataSourceOptions.cs | 17 +- .../IDapperDataSource.cs | 19 +- .../ServiceCollectionExtensions.cs | 149 +++-- .../DapperExtensionsDataStore.cs | 27 +- .../ServiceCollectionExtensions.cs | 63 ++- .../ITracedAggregateRepository.cs | 25 +- .../ServiceCollectionExtensions.cs | 61 +- .../IAggregateRepository.cs | 23 +- .../ServiceCollectionExtensions.cs | 63 ++- .../EfCoreTracedAggregateRepository.cs | 35 +- .../ServiceCollectionExtensions.cs | 79 ++- .../EfCoreAggregateDataSource.cs | 23 +- .../EfCoreAggregateRepository.cs | 29 +- .../ServiceCollectionExtensions.cs | 151 +++-- .../EfCoreDataSource.cs | 25 +- .../EfCoreDataSourceOptions.cs | 19 +- .../EfCoreDataStore.cs | 27 +- .../EfCoreDbContext.cs | 25 +- .../EfCoreRepository.cs | 29 +- .../IEfCoreDataSource.cs | 19 +- .../ServiceCollectionExtensions.cs | 215 ++++---- .../Commands/NatsCommandQueue.cs | 39 +- .../Commands/NatsCommandQueueOptions.cs | 17 +- .../EventDriven/NatsEventBus.cs | 41 +- .../EventDriven/NatsEventBusOptions.cs | 17 +- .../ServiceCollectionExtensions.cs | 149 +++-- .../ServiceCollectionExtensions.cs | 41 +- .../AzureQueueOptions.cs | 17 +- .../Commands/AzureCommandQueue.cs | 39 +- .../EventDriven/AzureEventBus.cs | 41 +- .../EventDriven/AzureEventBusOptions.cs | 17 +- .../ServiceCollectionExtensions.cs | 157 +++--- .../Commands/RabbitMqCommandQueue.cs | 39 +- .../Commands/RabbitMqCommandQueueOptions.cs | 17 +- .../EventDriven/RabbitMqEventBus.cs | 41 +- .../EventDriven/RabbitMqEventBusOptions.cs | 17 +- .../ServiceCollectionExtensions.cs | 149 +++-- .../Commands/AmazonCommandQueue.cs | 39 +- .../Commands/AmazonCommandQueueOptions.cs | 17 +- .../EventDriven/AmazonEventBus.cs | 39 +- .../EventDriven/AmazonEventBusOptions.cs | 17 +- .../ServiceCollectionExtensions.cs | 149 +++-- .../ServiceCollectionExtensions.cs | 41 +- .../Data/IDataStore.cs | 21 +- .../Data/IDeletableDataStore.cs | 21 +- .../Data/IPersistentDataStore.cs | 33 +- .../Data/IReadableDataStore.cs | 21 +- .../Data/ISearchableDataStore.cs | 27 +- .../Data/IWritableDataStore.cs | 21 +- .../Data/ServiceCollectionExtensions.cs | 115 ++-- .../Domain/IDeletableRepository.cs | 23 +- .../Domain/IPersistentRepository.cs | 27 +- .../Domain/IReadableRepository.cs | 23 +- .../Domain/IRepository.cs | 23 +- .../Domain/ISearchableRepository.cs | 23 +- .../Domain/IUnitOfWork.cs | 19 +- .../Domain/IWritableRepository.cs | 23 +- .../Domain/ServiceCollectionExtensions.cs | 109 ++-- .../IDataSource.cs | 19 +- .../Messaging/IPointToPointChannel.cs | 23 +- .../Messaging/IPublishSubscribeChannel.cs | 23 +- .../Messaging/IPublisher.cs | 21 +- .../Messaging/IReceiver.cs | 21 +- .../Messaging/ISender.cs | 21 +- .../Messaging/ISubscriber.cs | 21 +- .../Messaging/ServiceCollectionExtensions.cs | 85 ++- .../SavvyioDependencyInjectionOptions.cs | 203 ++++--- .../ServiceCollectionExtensions.cs | 411 +++++++------- .../ServiceLocatorOptions.cs | 59 +- .../ServiceProviderExtensions.cs | 27 +- .../IMediator.cs | 21 +- .../Mediator.cs | 189 ++++--- .../SavvyioOptionsExtensions.cs | 105 ++-- .../EfCoreTracedAggregateEntity.cs | 129 +++-- .../EfCoreTracedAggregateEntityExtensions.cs | 31 +- .../EfCoreTracedAggregateEntityOptions.cs | 411 +++++++------- .../EfCoreTracedAggregateRepository.cs | 115 ++-- .../ModelBuilderExtensions.cs | 67 ++- .../TracedDomainEventExtensions.cs | 27 +- .../DomainEventDispatcherExtensions.cs | 73 ++- .../EfCoreAggregateDataSource.cs | 71 ++- .../EfCoreAggregateRepository.cs | 25 +- .../EfCoreDataSource.cs | 97 ++-- .../EfCoreDataSourceOptions.cs | 49 +- .../EfCoreDataStore.cs | 159 +++--- .../EfCoreDbContext.cs | 145 +++-- .../EfCoreQueryOptions.cs | 65 ++- .../EfCoreRepository.cs | 147 +++-- .../IEfCoreDataSource.cs | 23 +- .../Commands/NatsCommandQueue.cs | 319 ++++++----- .../Commands/NatsCommandQueueOptions.cs | 195 ++++--- .../EventDriven/NatsEventBus.cs | 189 ++++--- .../EventDriven/NatsEventBusOptions.cs | 15 +- src/Savvyio.Extensions.NATS/NatsMessage.cs | 93 ++-- .../NatsMessageOptions.cs | 95 ++-- .../Bootstrapper.cs | 35 +- .../Converters/AggregateRootConverter.cs | 211 ++++--- .../Converters/MessageConverter.cs | 273 +++++---- .../Converters/RequestConverter.cs | 151 +++-- .../Converters/SingleValueObjectConverter.cs | 143 +++-- .../Converters/ValueObjectConverter.cs | 225 ++++---- .../JsonConverterExtensions.cs | 191 ++++--- .../JsonSerializerExtensions.cs | 49 +- .../NewtonsoftJsonMarshaller.cs | 99 ++-- .../AzureQueue.cs | 397 +++++++------- .../AzureQueueOptions.cs | 335 ++++++----- .../AzureQueueReceiveOptions.cs | 81 ++- .../AzureQueueSendOptions.cs | 69 ++- .../Commands/AzureCommandQueue.cs | 95 ++-- .../EventDriven/AzureEventBus.cs | 239 ++++---- .../EventDriven/AzureEventBusOptions.cs | 199 ++++--- .../Commands/RabbitMqCommandQueue.cs | 167 +++--- .../Commands/RabbitMqCommandQueueOptions.cs | 179 +++--- .../EventDriven/RabbitMqEventBus.cs | 149 +++-- .../EventDriven/RabbitMqEventBusOptions.cs | 79 ++- .../RabbitMqMessage.cs | 191 ++++--- .../RabbitMqMessageOptions.cs | 109 ++-- .../AmazonBus.cs | 71 ++- .../AmazonMessage.cs | 279 +++++----- .../AmazonMessageOptions.cs | 233 ++++---- .../AmazonMessageReceiveOptions.cs | 187 ++++--- .../AmazonQueue.cs | 69 ++- .../AmazonResourceNameOptions.cs | 119 ++-- .../ClientConfigExtensions.cs | 63 ++- .../Commands/AmazonCommandQueue.cs | 145 +++-- .../Commands/AmazonCommandQueueOptions.cs | 15 +- .../EventDriven/AmazonEventBus.cs | 175 +++--- .../EventDriven/AmazonEventBusOptions.cs | 15 +- .../EventDriven/StringExtensions.cs | 31 +- .../Bootstrapper.cs | 39 +- .../Converters/DateTimeConverter.cs | 65 ++- .../Converters/DateTimeOffsetConverter.cs | 67 ++- .../Converters/MessageConverter.cs | 279 +++++----- .../Converters/MetadataDictionaryConverter.cs | 147 +++-- .../Converters/RequestConverter.cs | 119 ++-- .../Converters/SingleValueObjectConverter.cs | 99 ++-- .../JsonConverterExtensions.cs | 235 ++++---- .../JsonMarshaller.cs | 99 ++-- .../JsonSerializerOptionsExtensions.cs | 37 +- src/Savvyio.Messaging/Acknowledgeable.cs | 55 +- .../Cryptography/MessageExtensions.cs | 53 +- .../Cryptography/SignedMessage.cs | 97 ++-- .../Cryptography/SignedMessageExtensions.cs | 59 +- .../Cryptography/SignedMessageOptions.cs | 91 ++- src/Savvyio.Messaging/Message.cs | 101 ++-- .../MessageAsyncEnumerable.cs | 87 ++- .../MessageAsyncEnumerableOptions.cs | 105 ++-- .../MessageAsyncEnumerator.cs | 65 ++- src/Savvyio.Messaging/MessageExtensions.cs | 47 +- src/Savvyio.Messaging/MessageOptions.cs | 95 ++-- src/Savvyio.Queries/Query.cs | 27 +- src/Savvyio.Queries/QueryDispatcher.cs | 69 ++- src/Savvyio.Queries/QueryHandler.cs | 43 +- .../SavvyioOptionsExtensions.cs | 45 +- .../DbConnectionExtensions.cs | 51 +- .../GuidHandler.cs | 11 +- .../CustomEfCoreDataSource.cs | 23 +- .../LongValueGenerator.cs | 15 +- .../ModelBuilderExtensions.cs | 91 ++- .../AccountCommandHandler.cs | 77 ++- .../AccountEventHandler.cs | 73 ++- .../AccountQueryHandler.cs | 49 +- .../Commands/CreateAccount.cs | 23 +- .../Commands/CreateAccountWithValueObjects.cs | 23 +- .../Commands/CreateMemberCommand.cs | 23 +- .../Commands/CreatePlatformProvider.cs | 23 +- .../Commands/UpdateAccount.cs | 23 +- .../Commands/UpdatePlatformProvider.cs | 27 +- .../UpdatePlatformProviderAccountPolicy.cs | 47 +- test/Savvyio.Assets.Tests/DbMarker.cs | 13 +- test/Savvyio.Assets.Tests/Domain/Account.cs | 115 ++-- test/Savvyio.Assets.Tests/Domain/AccountId.cs | 19 +- .../Domain/Coordinates.cs | 27 +- .../Domain/Credentials.cs | 35 +- .../Domain/Description.cs | 23 +- .../Domain/EmailAddress.cs | 21 +- .../Domain/EventSourcing/TracedAccount.cs | 101 ++-- .../Events/AccountEmailAddressChanged.cs | 15 +- .../Domain/Events/AccountFullNameChanged.cs | 15 +- .../Domain/Events/AccountInitiated.cs | 29 +- .../Domain/Events/AccountInitiatedChained.cs | 9 +- .../PlatformProviderAccountPolicyChanged.cs | 25 +- .../PlatformProviderDescriptionChanged.cs | 25 +- .../Events/PlatformProviderInitiated.cs | 37 +- .../Events/PlatformProviderNameChanged.cs | 25 +- ...formProviderThirdLevelDomainNameChanged.cs | 25 +- .../TracedAccountEmailAddressChanged.cs | 15 +- .../Events/TracedAccountFullNameChanged.cs | 15 +- .../Domain/Events/TracedAccountInitiated.cs | 27 +- .../UserAccountFailedLogonAttemptCreated.cs | 25 +- .../Domain/Events/UserAccountInitiated.cs | 21 +- .../Events/UserAccountPasswordInitiated.cs | 29 +- .../Domain/Events/UserAccountRemoved.cs | 21 +- test/Savvyio.Assets.Tests/Domain/FullName.cs | 25 +- .../Handlers/AccountDomainEventHandler.cs | 131 +++-- .../PlatformProviderDomainEventHandler.cs | 81 ++- test/Savvyio.Assets.Tests/Domain/Name.cs | 19 +- .../Domain/PlatformProvider.cs | 101 ++-- .../Domain/PlatformProviderAccountPolicy.cs | 49 +- .../Domain/PlatformProviderId.cs | 19 +- .../Domain/ThirdLevelDomainName.cs | 21 +- test/Savvyio.Assets.Tests/Domain/Timestamp.cs | 19 +- .../Domain/TracedAccountId.cs | 19 +- .../Domain/UserAccount.cs | 33 +- .../Domain/UserAccountFailedLogonAttempt.cs | 23 +- .../Domain/UserAccountPassword.cs | 27 +- .../EventDriven/AccountCreated.cs | 29 +- .../EventDriven/AccountUpdated.cs | 29 +- .../EventDriven/MemberCreated.cs | 19 +- .../EventDriven/PlatformProviderCreated.cs | 37 +- .../EventDriven/PlatformProviderUpdated.cs | 37 +- .../PlatformProviderHandler.cs | 101 ++-- .../Queries/AccountProjection.cs | 39 +- .../Queries/GetAccount.cs | 15 +- .../Queries/GetFakeAccount.cs | 15 +- .../Queries/PlatformProviderProjection.cs | 35 +- .../Assets/DefaultCommand.cs | 7 +- .../Assets/DefaultCommandHandler.cs | 31 +- .../CommandDispatcherTest.cs | 57 +- .../CommandHandlerTest.cs | 31 +- test/Savvyio.Commands.Tests/CommandTest.cs | 31 +- .../Messaging/CommandExtensionsTest.cs | 41 +- .../SavvyioOptionsExtensionsTest.cs | 59 +- .../Assets/AccountHandlers.cs | 65 ++- .../Savvyio.Core.Tests/Assets/DummyRequest.cs | 7 +- test/Savvyio.Core.Tests/Assets/FakeCommand.cs | 27 +- test/Savvyio.Core.Tests/Assets/FakeQuery.cs | 7 +- .../Assets/RootDummyRequest.cs | 7 +- .../Dispatchers/FireForgetDispatcherTest.cs | 101 ++-- .../Dispatchers/RequestReplyDispatcherTest.cs | 101 ++-- test/Savvyio.Core.Tests/HandlerFactoryTest.cs | 265 +++++---- .../Cryptography/SignedMessageOptionsTest.cs | 59 +- .../Cryptography/SignedMessageTest.cs | 151 +++-- .../Messaging/MessageOptionsTest.cs | 83 ++- .../Messaging/MessageTest.cs | 93 ++-- .../MetadataDictionaryTest.cs | 305 +++++----- .../MetadataExtensionsTest.cs | 239 ++++---- .../OrphanedHandlerExceptionTest.cs | 33 +- .../Reflection/AssemblyContextTest.cs | 269 +++++---- .../SavvyioOptionsExtensionsTest.cs | 189 ++++--- test/Savvyio.Core.Tests/SavvyioOptionsTest.cs | 33 +- .../EfCoreModelBuilderExtensionsTest.cs | 53 +- .../EfCoreTracedAggregateEntityOptionsTest.cs | 97 ++-- .../EfCoreTracedDomainEventExtensionsTest.cs | 27 +- .../TracedAggregateRootTest.cs | 427 +++++++------- .../TracedDomainEventExtensionsTest.cs | 41 +- .../Savvyio.Domain.Tests/AggregateRootTest.cs | 213 ++++--- .../Assets/AccountHandlers.cs | 81 ++- test/Savvyio.Domain.Tests/Assets/Mixed.cs | 17 +- test/Savvyio.Domain.Tests/Assets/Money.cs | 31 +- .../DomainEventDispatcherExtensionsTest.cs | 309 ++++++----- test/Savvyio.Domain.Tests/DomainEventTest.cs | 97 ++-- test/Savvyio.Domain.Tests/EntityTest.cs | 41 +- .../SavvyioOptionsExtensionsTest.cs | 59 +- .../SingleValueObjectTest.cs | 79 ++- test/Savvyio.Domain.Tests/ValueObjectTest.cs | 139 +++-- .../IntegrationEventDispatcherTest.cs | 57 +- .../IntegrationEventTest.cs | 103 ++-- .../Messaging/AcknowledgeableTest.cs | 39 +- .../CloudEvents/CloudEventDictionaryTest.cs | 109 ++-- .../Messaging/CloudEvents/CloudEventTest.cs | 47 +- .../Cryptography/CloudEventExtensionsTest.cs | 81 ++- .../Cryptography/SignedMessageOptionsTest.cs | 45 +- .../Cryptography/SignedMessageTest.cs | 79 ++- .../Messaging/InMemoryEventBusTest.cs | 123 ++--- .../IntegrationEventExtensionsTest.cs | 37 +- .../MessageAsyncEnumerableOptionsTest.cs | 75 ++- .../Messaging/MessageAsyncEnumerableTest.cs | 79 ++- .../Messaging/MessageOptionsTest.cs | 45 +- .../SavvyioOptionsExtensionsTest.cs | 59 +- .../Assets/AccountData.cs | 51 +- .../DapperDataSourceOptionsTest.cs | 39 +- .../DapperDataSourceTest.cs | 173 +++--- .../DapperDataStoreTest.cs | 147 +++-- .../DapperQueryOptionsTest.cs | 99 ++-- .../DapperExtensionsDataStoreTest.cs | 145 +++-- .../DapperExtensionsQueryOptionsTest.cs | 35 +- .../ServiceCollectionExtensionsTest.cs | 53 +- .../ServiceCollectionRegistrationTest.cs | 77 ++- .../ServiceCollectionExtensionsTest.cs | 67 ++- .../ServiceCollectionExtensionsTest.cs | 57 +- .../AggregateDataSourceRegistrationTest.cs | 71 ++- .../ServiceCollectionExtensionsTest.cs | 65 ++- .../ServiceCollectionExtensionsTest.cs | 183 +++--- .../Assets/BusMarker.cs | 9 +- .../Assets/QueueMarker.cs | 9 +- .../ServiceCollectionExtensionsTest.cs | 233 ++++---- .../ServiceCollectionExtensionsTest.cs | 127 +++-- .../Assets/BusMarker.cs | 7 +- .../Assets/QueueMarker.cs | 7 +- .../ServiceCollectionExtensionsTest.cs | 329 ++++++----- .../Assets/BusMarker.cs | 9 +- .../Assets/QueueMarker.cs | 9 +- .../ServiceCollectionExtensionsTest.cs | 215 ++++---- .../Assets/BusMarker.cs | 9 +- .../Assets/QueueMarker.cs | 9 +- .../ServiceCollectionExtensionsTest.cs | 271 +++++---- .../Assets/FakeDataSource.cs | 13 +- .../Assets/FakeDataStore.cs | 65 ++- .../Assets/FakeRepository.cs | 73 ++- .../Assets/TestCommand.cs | 7 +- .../Assets/TestCommandHandler.cs | 17 +- .../Assets/TestDomainEvent.cs | 7 +- .../Assets/TestDomainEventHandler.cs | 11 +- .../Assets/TestIntegrationEvent.cs | 7 +- .../Assets/TestIntegrationEventHandler.cs | 19 +- .../Assets/TestQuery.cs | 7 +- .../Assets/TestQueryHandler.cs | 19 +- .../Data/ServiceCollectionExtensionsTest.cs | 221 ++++---- .../SavvyioDependencyInjectionOptionsTest.cs | 41 +- .../ServiceCollectionExtensionsTest.cs | 439 ++++++++------- .../ServiceCollectionRegistrationTest.cs | 143 +++-- .../ServiceCollectionExtensionsTest.cs | 127 +++-- .../MediatorSyncTest.cs | 171 +++--- .../MediatorTest.cs | 257 +++++---- .../SavvyioOptionsExtensionsTest.cs | 111 ++-- .../DomainEventDispatcherExtensionsTest.cs | 99 ++-- .../EfCoreDataSourceOptionsTest.cs | 25 +- .../EfCoreDataSourceTest.cs | 91 ++- .../EfCoreDataStoreTest.cs | 191 ++++--- .../EfCoreRepositoryTest.cs | 263 +++++---- .../ServiceCollectionExtensionsTest.cs | 275 +++++----- .../Assets/CreateMemberCommand.cs | 23 +- .../Assets/MemberCreated.cs | 19 +- ...tsCommandQueueJsonSerializerContextTest.cs | 253 +++++---- ...ueueNewtonsoftJsonSerializerContextTest.cs | 253 +++++---- .../Commands/ObservableNatsCommandQueue.cs | 33 +- .../NatsEventBusJsonSerializerContextTest.cs | 419 +++++++------- ...tBusNewtonsoftJsonSerializerContextTest.cs | 419 +++++++------- .../EventDriven/ObservableNatsEventBus.cs | 101 ++-- .../MessageTestHelper.cs | 19 +- .../NatsTestEnvironment.cs | 9 +- .../Commands/NatsCommandQueueOptionsTest.cs | 275 +++++----- .../Commands/NatsCommandQueueTest.cs | 519 +++++++++--------- .../EventDriven/NatsEventBusOptionsTest.cs | 37 +- .../EventDriven/NatsEventBusTest.cs | 267 +++++---- .../NatsMessageOptionsTest.cs | 101 ++-- .../NatsMessageTest.cs | 135 +++-- .../AggregateRootConverterTest.cs | 143 +++-- .../Commands/CommandTest.cs | 49 +- .../Messaging/CommandExtensionsTest.cs | 41 +- .../Cryptography/MessageExtensionsTest.cs | 97 ++-- .../Messaging/InMemoryCommandQueueTest.cs | 109 ++-- .../Converters/ValueObjectConverterTest.cs | 237 ++++---- .../Domain/DomainTest.cs | 75 ++- .../IntegrationEventExtensionsTest.cs | 137 +++-- .../IntegrationEventExtensionsTest.cs | 111 ++-- .../IntegrationEventExtensionsTest.cs | 109 ++-- .../IntegrationEventExtensionsTest.cs | 73 ++- .../JsonConverterExtensionsTest.cs | 77 ++- .../JsonSerializerExtensionsTest.cs | 45 +- .../MetadataDictionaryTest.cs | 47 +- .../NewtonsoftJsonMarshallerTest.cs | 77 ++- .../RequestConverterTest.cs | 145 +++-- .../Assets/CreateMemberCommand.cs | 23 +- .../Assets/MarkerStructs.cs | 25 +- .../Assets/MemberCreated.cs | 19 +- ...reCommandQueueJsonSerializerContextTest.cs | 229 ++++---- ...ueueNewtonsoftJsonSerializerContextTest.cs | 229 ++++---- .../AzureEventBusJsonSerializerContextTest.cs | 509 +++++++++-------- ...tBusNewtonsoftJsonSerializerContextTest.cs | 509 +++++++++-------- .../AzureQueueOptionsTest.cs | 247 +++++---- .../AzureQueueReceiveOptionsTest.cs | 95 ++-- .../AzureQueueSendOptionsTest.cs | 75 ++- .../Commands/AzureCommandQueueTest.cs | 251 +++++---- .../EventDriven/AzureEventBusOptionsTest.cs | 131 +++-- .../EventDriven/AzureEventBusTest.cs | 385 +++++++------ .../Assets/CreateMemberCommand.cs | 23 +- .../Assets/MemberCreated.cs | 19 +- ...MqCommandQueueJsonSerializerContextTest.cs | 229 ++++---- ...ueueNewtonsoftJsonSerializerContextTest.cs | 203 ++++--- ...bbitMqEventBusJsonSerializerContextTest.cs | 419 +++++++------- ...tBusNewtonsoftJsonSerializerContextTest.cs | 419 +++++++------- .../MessageTestHelper.cs | 19 +- .../RabbitMqTestEnvironment.cs | 111 ++-- .../RabbitMqCommandQueueOptionsTest.cs | 89 ++- .../Commands/RabbitMqCommandQueueTest.cs | 243 ++++---- .../RabbitMqEventBusOptionsTest.cs | 81 ++- .../EventDriven/RabbitMqEventBusTest.cs | 219 ++++---- .../RabbitMqMessageOptionsTest.cs | 77 ++- .../RabbitMqMessageTest.cs | 229 ++++---- .../Assets/CreateMemberCommand.cs | 23 +- .../Assets/MemberCreated.cs | 19 +- ...onCommandQueueJsonSerializerContextTest.cs | 233 ++++---- ...ueueNewtonsoftJsonSerializerContextTest.cs | 233 ++++---- ...AmazonEventBusJsonSerializerContextTest.cs | 367 ++++++------- ...tBusNewtonsoftJsonSerializerContextTest.cs | 365 ++++++------ .../AmazonMessageOptionsTest.cs | 253 +++++---- .../AmazonMessageReceiveOptionsTest.cs | 107 ++-- .../AmazonMessageTest.cs | 85 ++- .../AmazonResourceNameOptionsTest.cs | 121 ++-- .../ClientConfigExtensionsTest.cs | 41 +- .../Commands/AmazonCommandQueueTest.cs | 387 +++++++------ .../EventDriven/AmazonEventBusTest.cs | 309 ++++++----- .../EventDriven/StringExtensionsTest.cs | 51 +- .../Commands/CommandTest.cs | 49 +- .../Messaging/CommandExtensionsTest.cs | 41 +- .../Cryptography/MessageExtensionsTest.cs | 59 +- .../Messaging/InMemoryCommandQueueTest.cs | 109 ++-- .../Converters/DateTimeConverterTest.cs | 103 ++-- .../Converters/DateTimeOffsetConverterTest.cs | 89 ++- .../Converters/MessageConverterTest.cs | 139 +++-- .../MetadataDictionaryConverterTest.cs | 255 +++++---- .../Converters/RequestConverterTest.cs | 123 ++--- .../Domain/DomainTest.cs | 75 ++- .../IntegrationEventExtensionsTest.cs | 89 ++- .../IntegrationEventExtensionsTest.cs | 73 ++- .../IntegrationEventExtensionsTest.cs | 133 +++-- .../IntegrationEventExtensionsTest.cs | 73 ++- .../JsonConverterExtensionsTest.cs | 211 ++++--- .../JsonSerializerOptionsExtensionsTest.cs | 53 +- .../MetadataDictionaryTest.cs | 47 +- .../Assets/AccountData.cs | 49 +- .../DistributedMediatorTest.cs | 249 +++++---- .../ServiceCollectionExtensionsTest.cs | 75 ++- test/Savvyio.FunctionalTests/MediatorTest.cs | 189 ++++--- .../Assets/DefaultQuery.cs | 7 +- .../Assets/DefaultQueryHandler.cs | 19 +- .../QueryDispatcherTest.cs | 55 +- .../Savvyio.Queries.Tests/QueryHandlerTest.cs | 31 +- test/Savvyio.Queries.Tests/QueryTest.cs | 41 +- .../SavvyioOptionsExtensionsTest.cs | 59 +- 546 files changed, 23826 insertions(+), 24372 deletions(-) diff --git a/src/Savvyio.Commands.Messaging/CommandExtensions.cs b/src/Savvyio.Commands.Messaging/CommandExtensions.cs index 4be5a781..bad6e1ed 100644 --- a/src/Savvyio.Commands.Messaging/CommandExtensions.cs +++ b/src/Savvyio.Commands.Messaging/CommandExtensions.cs @@ -2,36 +2,35 @@ using Cuemon; using Savvyio.Messaging; -namespace Savvyio.Commands.Messaging +namespace Savvyio.Commands.Messaging; + +/// +/// Extension methods for the interface. +/// +public static class CommandExtensions { /// - /// Extension methods for the interface. + /// Encloses the specified to an instance of . /// - public static class CommandExtensions + /// The type of the payload constraint to the interface. + /// The payload to attach within the message. + /// The context that describes the origin of the message. + /// The type that describes the type of related to the originating occurrence. + /// The which may be configured. + /// An instance of constraint to the interface. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + public static IMessage ToMessage(this T command, Uri source, string type, Action setup = null) where T : ICommand { - /// - /// Encloses the specified to an instance of . - /// - /// The type of the payload constraint to the interface. - /// The payload to attach within the message. - /// The context that describes the origin of the message. - /// The type that describes the type of related to the originating occurrence. - /// The which may be configured. - /// An instance of constraint to the interface. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - public static IMessage ToMessage(this T command, Uri source, string type, Action setup = null) where T : ICommand - { - Validator.ThrowIfNull(command); - Validator.ThrowIfNull(source); - Validator.ThrowIfNullOrWhitespace(type); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - return new Message(options.MessageId, source, type, command, options.Time); - } + Validator.ThrowIfNull(command); + Validator.ThrowIfNull(source); + Validator.ThrowIfNullOrWhitespace(type); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + return new Message(options.MessageId, source, type, command, options.Time); } } diff --git a/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs b/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs index 3aae3ad3..ed8c6c75 100644 --- a/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs +++ b/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs @@ -6,43 +6,42 @@ using Cuemon.Threading; using Savvyio.Messaging; -namespace Savvyio.Commands.Messaging +namespace Savvyio.Commands.Messaging; + +/// +/// Provides an in-memory implementation of the interface useful for unit testing and the likes thereof. +/// +public class InMemoryCommandQueue : IPointToPointChannel { + private readonly Channel> _channel = Channel.CreateUnbounded>(); + /// - /// Provides an in-memory implementation of the interface useful for unit testing and the likes thereof. + /// Sends the specified whose generic type argument is asynchronous using Point-to-Point Channel/P2P MEP. /// - public class InMemoryCommandQueue : IPointToPointChannel + /// The enclosed messages to send. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task SendAsync(IEnumerable> messages, Action setup = null) { - private readonly Channel> _channel = Channel.CreateUnbounded>(); - - /// - /// Sends the specified whose generic type argument is asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The enclosed messages to send. - /// The which may be configured. - /// A that represents the asynchronous operation. - public async Task SendAsync(IEnumerable> messages, Action setup = null) + var options = setup.Configure(); + foreach (var command in messages) { - var options = setup.Configure(); - foreach (var command in messages) - { - await _channel.Writer.WriteAsync(command, options.CancellationToken).ConfigureAwait(false); - } + await _channel.Writer.WriteAsync(command, options.CancellationToken).ConfigureAwait(false); } + } - /// - /// Receive one or more command(s) asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - public async IAsyncEnumerable> ReceiveAsync(Action setup = null) + /// + /// Receive one or more command(s) asynchronous using Point-to-Point Channel/P2P MEP. + /// + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + public async IAsyncEnumerable> ReceiveAsync(Action setup = null) + { + var options = setup.Configure(); + await foreach (var message in _channel.Reader.ReadAllAsync(options.CancellationToken).ConfigureAwait(false)) { - var options = setup.Configure(); - await foreach (var message in _channel.Reader.ReadAllAsync(options.CancellationToken).ConfigureAwait(false)) - { - yield return message; - if (_channel.Reader.Count == 0) { yield break; } - } + yield return message; + if (_channel.Reader.Count == 0) { yield break; } } } } diff --git a/src/Savvyio.Commands/Command.cs b/src/Savvyio.Commands/Command.cs index f660e90f..2a489b71 100644 --- a/src/Savvyio.Commands/Command.cs +++ b/src/Savvyio.Commands/Command.cs @@ -1,22 +1,21 @@ using System; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Provides a default implementation of the interface. +/// +/// +/// +public abstract record Command : Request, ICommand { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public abstract record Command : Request, ICommand + /// The optional metadata to merge with this instance. + protected Command(IMetadata metadata = null) { - /// - /// Initializes a new instance of the class. - /// - /// The optional metadata to merge with this instance. - protected Command(IMetadata metadata = null) - { - this.SetCorrelationId(Guid.NewGuid().ToString("N")); - this.MergeMetadata(metadata); - } + this.SetCorrelationId(Guid.NewGuid().ToString("N")); + this.MergeMetadata(metadata); } } diff --git a/src/Savvyio.Commands/CommandDispatcher.cs b/src/Savvyio.Commands/CommandDispatcher.cs index 0f986c37..8948e854 100644 --- a/src/Savvyio.Commands/CommandDispatcher.cs +++ b/src/Savvyio.Commands/CommandDispatcher.cs @@ -4,43 +4,42 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Provides a default implementation of of the interface. +/// +/// +/// +public class CommandDispatcher : FireForgetDispatcher, ICommandDispatcher { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public class CommandDispatcher : FireForgetDispatcher, ICommandDispatcher + /// The provider of service implementations. + public CommandDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - public CommandDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Commits the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - public void Commit(ICommand request) - { - Validator.ThrowIfNull(request); - Dispatch(request, handler => handler.Delegates); - } + /// + /// Commits the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to commit. + public void Commit(ICommand request) + { + Validator.ThrowIfNull(request); + Dispatch(request, handler => handler.Delegates); + } - /// - /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task CommitAsync(ICommand request, Action setup = null) - { - Validator.ThrowIfNull(request); - return DispatchAsync(request, handler => handler.Delegates, setup); - } + /// + /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to commit. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task CommitAsync(ICommand request, Action setup = null) + { + Validator.ThrowIfNull(request); + return DispatchAsync(request, handler => handler.Delegates, setup); } } diff --git a/src/Savvyio.Commands/CommandHandler.cs b/src/Savvyio.Commands/CommandHandler.cs index 048d5a19..a4eb5c99 100644 --- a/src/Savvyio.Commands/CommandHandler.cs +++ b/src/Savvyio.Commands/CommandHandler.cs @@ -1,31 +1,30 @@ using Savvyio.Handlers; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Provides a generic and consistent way of handling Command objects that implements the interface. This is an abstract class. +/// +/// +public abstract class CommandHandler : ICommandHandler { /// - /// Provides a generic and consistent way of handling Command objects that implements the interface. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class CommandHandler : ICommandHandler + protected CommandHandler() { - /// - /// Initializes a new instance of the class. - /// - protected CommandHandler() - { - Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); - } + Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); + } - /// - /// Registers the delegates responsible for handling types that implements the interface. - /// - /// The registry that store the delegates of type . - protected abstract void RegisterDelegates(IFireForgetRegistry handlers); + /// + /// Registers the delegates responsible for handling types that implements the interface. + /// + /// The registry that store the delegates of type . + protected abstract void RegisterDelegates(IFireForgetRegistry handlers); - /// - /// Gets the activator responsible for invoking delegates that handles . - /// - /// The activator responsible for invoking delegates that handles . - public IFireForgetActivator Delegates { get; } - } + /// + /// Gets the activator responsible for invoking delegates that handles . + /// + /// The activator responsible for invoking delegates that handles . + public IFireForgetActivator Delegates { get; } } diff --git a/src/Savvyio.Commands/SavvyioOptionsExtensions.cs b/src/Savvyio.Commands/SavvyioOptionsExtensions.cs index 5c89d93a..41e66552 100644 --- a/src/Savvyio.Commands/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Commands/SavvyioOptionsExtensions.cs @@ -1,30 +1,29 @@ -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds an implementation of the interface to (if not already registered). /// - public static class SavvyioOptionsExtensions + /// The type that implements the interface. + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddCommandHandler(this SavvyioOptions options) where TImplementation : class, ICommandHandler { - /// - /// Adds an implementation of the interface to (if not already registered). - /// - /// The type that implements the interface. - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddCommandHandler(this SavvyioOptions options) where TImplementation : class, ICommandHandler - { - options.AddHandler(); - return options; - } + options.AddHandler(); + return options; + } - /// - /// Adds a default implementation of the interface. - /// - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddCommandDispatcher(this SavvyioOptions options) - { - return options.AddDispatcher(); - } + /// + /// Adds a default implementation of the interface. + /// + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddCommandDispatcher(this SavvyioOptions options) + { + return options.AddDispatcher(); } } diff --git a/src/Savvyio.Core/AsyncEventHandler.cs b/src/Savvyio.Core/AsyncEventHandler.cs index 01b76aab..404f512e 100644 --- a/src/Savvyio.Core/AsyncEventHandler.cs +++ b/src/Savvyio.Core/AsyncEventHandler.cs @@ -1,14 +1,13 @@ using System; using System.Threading.Tasks; -namespace Savvyio -{ - /// - /// Represents the method that will handle an event when the event provides data asynchronously. - /// - /// The type of the event data generated by the event. - /// The source of the event. - /// An object that contains the event data. - /// A task that represents the asynchronous operation. - public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; -} +namespace Savvyio; + +/// +/// Represents the method that will handle an event when the event provides data asynchronously. +/// +/// The type of the event data generated by the event. +/// The source of the event. +/// An object that contains the event data. +/// A task that represents the asynchronous operation. +public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; diff --git a/src/Savvyio.Core/Commands/ICommand.cs b/src/Savvyio.Core/Commands/ICommand.cs index 86d4bd90..96694566 100644 --- a/src/Savvyio.Core/Commands/ICommand.cs +++ b/src/Savvyio.Core/Commands/ICommand.cs @@ -1,9 +1,8 @@ -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// A marker interface that specifies an intention to do something (e.g. change the state). +/// +public interface ICommand : IRequest, IMetadata { - /// - /// A marker interface that specifies an intention to do something (e.g. change the state). - /// - public interface ICommand : IRequest, IMetadata - { - } } diff --git a/src/Savvyio.Core/Commands/ICommandDispatcher.cs b/src/Savvyio.Core/Commands/ICommandDispatcher.cs index 502b5ac9..f10128d4 100644 --- a/src/Savvyio.Core/Commands/ICommandDispatcher.cs +++ b/src/Savvyio.Core/Commands/ICommandDispatcher.cs @@ -3,26 +3,25 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Defines a Command dispatcher that uses Fire-and-Forget/In-Only MEP. +/// +/// +public interface ICommandDispatcher : IDispatcher { /// - /// Defines a Command dispatcher that uses Fire-and-Forget/In-Only MEP. + /// Commits the specified using Fire-and-Forget/In-Only MEP. /// - /// - public interface ICommandDispatcher : IDispatcher - { - /// - /// Commits the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - void Commit(ICommand request); + /// The to commit. + void Commit(ICommand request); - /// - /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task CommitAsync(ICommand request, Action setup = null); - } + /// + /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to commit. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task CommitAsync(ICommand request, Action setup = null); } diff --git a/src/Savvyio.Core/Commands/ICommandHandler.cs b/src/Savvyio.Core/Commands/ICommandHandler.cs index 694e4a44..05022d8d 100644 --- a/src/Savvyio.Core/Commands/ICommandHandler.cs +++ b/src/Savvyio.Core/Commands/ICommandHandler.cs @@ -1,12 +1,11 @@ using Savvyio.Handlers; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +/// +/// Specifies a handler responsible for objects that implements the interface. +/// +/// +public interface ICommandHandler : IFireForgetHandler { - /// - /// Specifies a handler responsible for objects that implements the interface. - /// - /// - public interface ICommandHandler : IFireForgetHandler - { - } } diff --git a/src/Savvyio.Core/Data/IDataStore.cs b/src/Savvyio.Core/Data/IDataStore.cs index 83114967..87a49c4c 100644 --- a/src/Savvyio.Core/Data/IDataStore.cs +++ b/src/Savvyio.Core/Data/IDataStore.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Data +namespace Savvyio.Data; + +/// +/// A marker interface that specifies an abstraction of data persistence based on the Data Access Object pattern aka DAO. +/// +/// The type of the DTO. +public interface IDataStore where T : class { - /// - /// A marker interface that specifies an abstraction of data persistence based on the Data Access Object pattern aka DAO. - /// - /// The type of the DTO. - public interface IDataStore where T : class - { - } } diff --git a/src/Savvyio.Core/Data/IDeletableDataStore.cs b/src/Savvyio.Core/Data/IDeletableDataStore.cs index ec422a50..c443867e 100644 --- a/src/Savvyio.Core/Data/IDeletableDataStore.cs +++ b/src/Savvyio.Core/Data/IDeletableDataStore.cs @@ -2,21 +2,20 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Data +namespace Savvyio.Data; + +/// +/// Defines a generic way of abstracting deletable data access objects (cruD). +/// +/// The type of the DTO. +/// +public interface IDeletableDataStore : IDataStore where T : class { /// - /// Defines a generic way of abstracting deletable data access objects (cruD). + /// Deletes the specified asynchronous. /// - /// The type of the DTO. - /// - public interface IDeletableDataStore : IDataStore where T : class - { - /// - /// Deletes the specified asynchronous. - /// - /// The object to delete. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task DeleteAsync(T dto, Action setup = null); - } + /// The object to delete. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task DeleteAsync(T dto, Action setup = null); } diff --git a/src/Savvyio.Core/Data/IPersistentDataStore.cs b/src/Savvyio.Core/Data/IPersistentDataStore.cs index 8ffc5168..5866ff80 100644 --- a/src/Savvyio.Core/Data/IPersistentDataStore.cs +++ b/src/Savvyio.Core/Data/IPersistentDataStore.cs @@ -1,19 +1,18 @@ using Cuemon.Threading; -namespace Savvyio.Data +namespace Savvyio.Data; + +/// +/// Defines a generic way of abstracting persistent data access objects (CRUD). +/// +/// The type of the DTO. +/// The type of options associated with this DTO. +/// +/// +/// +/// +public interface IPersistentDataStore : IWritableDataStore, IReadableDataStore, ISearchableDataStore, IDeletableDataStore + where T : class + where TOptions : AsyncOptions, new() { - /// - /// Defines a generic way of abstracting persistent data access objects (CRUD). - /// - /// The type of the DTO. - /// The type of options associated with this DTO. - /// - /// - /// - /// - public interface IPersistentDataStore : IWritableDataStore, IReadableDataStore, ISearchableDataStore, IDeletableDataStore - where T : class - where TOptions : AsyncOptions, new() - { - } } diff --git a/src/Savvyio.Core/Data/IReadableDataStore.cs b/src/Savvyio.Core/Data/IReadableDataStore.cs index 9b24b85d..967138df 100644 --- a/src/Savvyio.Core/Data/IReadableDataStore.cs +++ b/src/Savvyio.Core/Data/IReadableDataStore.cs @@ -2,22 +2,20 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Data -{ +namespace Savvyio.Data; + +/// +/// Defines a generic way of abstracting readable data access objects (cRud). +/// +/// The type of the DTO. +public interface IReadableDataStore : IDataStore where T : class +{ /// - /// Defines a generic way of abstracting readable data access objects (cRud). + /// Loads the object from the specified asynchronous. /// - /// The type of the DTO. - public interface IReadableDataStore : IDataStore where T : class - - { - /// - /// Loads the object from the specified asynchronous. - /// - /// The key that uniquely identifies the object. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. - Task GetByIdAsync(object id, Action setup = null); - } + /// The key that uniquely identifies the object. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. + Task GetByIdAsync(object id, Action setup = null); } diff --git a/src/Savvyio.Core/Data/ISearchableDataStore.cs b/src/Savvyio.Core/Data/ISearchableDataStore.cs index b8ec0380..909e86d2 100644 --- a/src/Savvyio.Core/Data/ISearchableDataStore.cs +++ b/src/Savvyio.Core/Data/ISearchableDataStore.cs @@ -3,23 +3,22 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Data +namespace Savvyio.Data; + +/// +/// Defines a generic way of abstracting searchable data access objects (cRud). +/// +/// The type of the DTO. +/// The type of the options associated with this DTO. +/// +public interface ISearchableDataStore : IDataStore + where T : class + where TOptions : AsyncOptions, new() { /// - /// Defines a generic way of abstracting searchable data access objects (cRud). + /// Finds all objects matching the specified asynchronous. /// - /// The type of the DTO. - /// The type of the options associated with this DTO. - /// - public interface ISearchableDataStore : IDataStore - where T : class - where TOptions : AsyncOptions, new() - { - /// - /// Finds all objects matching the specified asynchronous. - /// - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. - Task> FindAllAsync(Action setup = null); - } + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. + Task> FindAllAsync(Action setup = null); } diff --git a/src/Savvyio.Core/Data/IWritableDataStore.cs b/src/Savvyio.Core/Data/IWritableDataStore.cs index c99ff9e6..b3cad147 100644 --- a/src/Savvyio.Core/Data/IWritableDataStore.cs +++ b/src/Savvyio.Core/Data/IWritableDataStore.cs @@ -2,29 +2,28 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Data +namespace Savvyio.Data; + +/// +/// Defines a generic way of abstracting writable data access objects (CrUd). +/// +/// The type of the DTO. +/// +public interface IWritableDataStore : IDataStore where T : class { /// - /// Defines a generic way of abstracting writable data access objects (CrUd). + /// Creates the specified asynchronous. /// - /// The type of the DTO. - /// - public interface IWritableDataStore : IDataStore where T : class - { - /// - /// Creates the specified asynchronous. - /// - /// The object to create. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task CreateAsync(T dto, Action setup = null); + /// The object to create. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task CreateAsync(T dto, Action setup = null); - /// - /// Updates the specified asynchronous. - /// - /// The object to update. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task UpdateAsync(T dto, Action setup = null); - } + /// + /// Updates the specified asynchronous. + /// + /// The object to update. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task UpdateAsync(T dto, Action setup = null); } diff --git a/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs b/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs index f7513a65..74a9832e 100644 --- a/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs +++ b/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs @@ -1,19 +1,18 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Diagnostics +namespace Savvyio.Diagnostics; + +/// +/// Defines a contract for asynchronously providing an underlying target that can be probed to assess health status. +/// +/// The type of the underlying target used for health probing. +public interface IAsyncHealthCheckProvider { /// - /// Defines a contract for asynchronously providing an underlying target that can be probed to assess health status. + /// Asynchronously gets the underlying target used for probing health status. /// - /// The type of the underlying target used for health probing. - public interface IAsyncHealthCheckProvider - { - /// - /// Asynchronously gets the underlying target used for probing health status. - /// - /// A that can be used to cancel the asynchronous operation. - /// A task that represents the asynchronous operation. The task result contains the target instance of type used for health probing. - Task GetHealthCheckTargetAsync(CancellationToken cancellationToken); - } + /// A that can be used to cancel the asynchronous operation. + /// A task that represents the asynchronous operation. The task result contains the target instance of type used for health probing. + Task GetHealthCheckTargetAsync(CancellationToken cancellationToken); } diff --git a/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs b/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs index 6d47fff5..b901f01b 100644 --- a/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs +++ b/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs @@ -1,15 +1,14 @@ -namespace Savvyio.Diagnostics +namespace Savvyio.Diagnostics; + +/// +/// Defines a contract for providing an underlying target that can be probed to assess health status. +/// +/// The type of the underlying target used for health probing. +public interface IHealthCheckProvider { /// - /// Defines a contract for providing an underlying target that can be probed to assess health status. + /// Gets the underlying target used for probing health status. /// - /// The type of the underlying target used for health probing. - public interface IHealthCheckProvider - { - /// - /// Gets the underlying target used for probing health status. - /// - /// The target instance of type used for health probing. - T GetHealthCheckTarget(); - } + /// The target instance of type used for health probing. + T GetHealthCheckTarget(); } diff --git a/src/Savvyio.Core/Dispatchers/Dispatcher.cs b/src/Savvyio.Core/Dispatchers/Dispatcher.cs index 58ea5081..d75aa5d8 100644 --- a/src/Savvyio.Core/Dispatchers/Dispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/Dispatcher.cs @@ -2,28 +2,27 @@ using System.Collections.Generic; using Cuemon; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// Represents the base class from which all implementations of the dispatcher concept should derive. This is an abstract class. +/// +/// +public abstract class Dispatcher : IDispatcher { /// - /// Represents the base class from which all implementations of the dispatcher concept should derive. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class Dispatcher : IDispatcher + /// The provider of service implementations. + protected Dispatcher(IServiceLocator serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - protected Dispatcher(IServiceLocator serviceLocator) - { - Validator.ThrowIfNull(serviceLocator); - ServiceFactory = serviceLocator.GetServices; - } - - /// - /// Gets the function delegate that creates the services. - /// - /// The function delegate that creates the services. - protected Func> ServiceFactory { get; } + Validator.ThrowIfNull(serviceLocator); + ServiceFactory = serviceLocator.GetServices; } + + /// + /// Gets the function delegate that creates the services. + /// + /// The function delegate that creates the services. + protected Func> ServiceFactory { get; } } diff --git a/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs b/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs index 49bd412c..35339c78 100644 --- a/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs @@ -6,76 +6,75 @@ using Cuemon.Threading; using Savvyio.Handlers; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// Provides a generic dispatcher that uses Fire-and-Forget/In-Only MEP. This is an abstract class. +/// +/// +public abstract class FireForgetDispatcher : Dispatcher { /// - /// Provides a generic dispatcher that uses Fire-and-Forget/In-Only MEP. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class FireForgetDispatcher : Dispatcher + /// The provider of service implementations. + protected FireForgetDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - protected FireForgetDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Dispatches the specified using Fire-and-Forget/In-Only MEP. - /// - /// The type of the input model registered to a handler. - /// The type of the handler to locate the input model. - /// The model that is being handled by a registered delegate. - /// The function delegate that will locate and invoke the handler registered to the specified . - /// A can be a command, domain event, integration event, query etc. - protected virtual void Dispatch(TRequest request, Func> handlerFactory) - where TRequest : IRequest - where THandler : IHandler + /// + /// Dispatches the specified using Fire-and-Forget/In-Only MEP. + /// + /// The type of the input model registered to a handler. + /// The type of the handler to locate the input model. + /// The model that is being handled by a registered delegate. + /// The function delegate that will locate and invoke the handler registered to the specified . + /// A can be a command, domain event, integration event, query etc. + protected virtual void Dispatch(TRequest request, Func> handlerFactory) + where TRequest : IRequest + where THandler : IHandler + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(handlerFactory); + var handlerType = typeof(THandler); + var hasHandler = false; + if (ServiceFactory(handlerType) is IEnumerable handlers) { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(handlerFactory); - var handlerType = typeof(THandler); - var hasHandler = false; - if (ServiceFactory(handlerType) is IEnumerable handlers) + foreach (var handler in handlers) // allow multiple handlers for same model { - foreach (var handler in handlers) // allow multiple handlers for same model - { - hasHandler |= handlerFactory(handler).TryInvoke(request); - } + hasHandler |= handlerFactory(handler).TryInvoke(request); } - if (!hasHandler) { throw OrphanedHandlerException.Create(request, nameof(request)); } } + if (!hasHandler) { throw OrphanedHandlerException.Create(request, nameof(request)); } + } - /// - /// Dispatches the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The type of the input model registered to a handler. - /// The type of the handler to locate the input model. - /// The model that is being handled by a registered delegate. - /// The function delegate that will locate and invoke the handler registered to the specified . - /// The which may be configured. - /// A that represents the asynchronous operation. - /// A can be a command, domain event, integration event, query etc. - protected virtual async Task DispatchAsync(TRequest request, Func> handlerFactory, Action setup) - where TRequest : IRequest - where THandler : IHandler + /// + /// Dispatches the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The type of the input model registered to a handler. + /// The type of the handler to locate the input model. + /// The model that is being handled by a registered delegate. + /// The function delegate that will locate and invoke the handler registered to the specified . + /// The which may be configured. + /// A that represents the asynchronous operation. + /// A can be a command, domain event, integration event, query etc. + protected virtual async Task DispatchAsync(TRequest request, Func> handlerFactory, Action setup) + where TRequest : IRequest + where THandler : IHandler + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(handlerFactory); + var options = setup.Configure(); + var handlerType = typeof(THandler); + var hasHandler = false; + if (ServiceFactory(handlerType) is IEnumerable handlers) { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(handlerFactory); - var options = setup.Configure(); - var handlerType = typeof(THandler); - var hasHandler = false; - if (ServiceFactory(handlerType) is IEnumerable handlers) + foreach (var handler in handlers) // allow multiple handlers for same model { - foreach (var handler in handlers) // allow multiple handlers for same model - { - var operation = await handlerFactory(handler).TryInvokeAsync(request, options.CancellationToken).ConfigureAwait(false); - hasHandler |= operation.Succeeded; - } + var operation = await handlerFactory(handler).TryInvokeAsync(request, options.CancellationToken).ConfigureAwait(false); + hasHandler |= operation.Succeeded; } - if (!hasHandler) { throw OrphanedHandlerException.Create(request, nameof(request)); } } + if (!hasHandler) { throw OrphanedHandlerException.Create(request, nameof(request)); } } } diff --git a/src/Savvyio.Core/Dispatchers/IDispatcher.cs b/src/Savvyio.Core/Dispatchers/IDispatcher.cs index 6e1351b6..31d7399e 100644 --- a/src/Savvyio.Core/Dispatchers/IDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/IDispatcher.cs @@ -1,9 +1,8 @@ -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// A marker interface that specifies a dispatcher that encapsulates how a set of objects interact. +/// +public interface IDispatcher { - /// - /// A marker interface that specifies a dispatcher that encapsulates how a set of objects interact. - /// - public interface IDispatcher - { - } } diff --git a/src/Savvyio.Core/Dispatchers/IServiceLocator.cs b/src/Savvyio.Core/Dispatchers/IServiceLocator.cs index 9f29b699..0e559471 100644 --- a/src/Savvyio.Core/Dispatchers/IServiceLocator.cs +++ b/src/Savvyio.Core/Dispatchers/IServiceLocator.cs @@ -1,18 +1,17 @@ using System; using System.Collections.Generic; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// Provides a generic way to locate implementations of service objects. +/// +public interface IServiceLocator { /// - /// Provides a generic way to locate implementations of service objects. + /// Get an enumeration of services of type . /// - public interface IServiceLocator - { - /// - /// Get an enumeration of services of type . - /// - /// An object that specifies the type of service object to get. - /// An enumeration of services of type . - IEnumerable GetServices(Type serviceType); - } + /// An object that specifies the type of service object to get. + /// An enumeration of services of type . + IEnumerable GetServices(Type serviceType); } diff --git a/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs b/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs index aff8159f..655f829e 100644 --- a/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs @@ -6,83 +6,82 @@ using Cuemon.Threading; using Savvyio.Handlers; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// Provides a generic dispatcher that uses Request-Reply/In-Out MEP. This is an abstract class. +/// +/// +public abstract class RequestReplyDispatcher : Dispatcher { /// - /// Provides a generic dispatcher that uses Request-Reply/In-Out MEP. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class RequestReplyDispatcher : Dispatcher + /// The provider of service implementations. + protected RequestReplyDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - protected RequestReplyDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Dispatches the specified using Request-Reply/In-Out MEP. - /// - /// The type of the input model registered to a handler. - /// The type of the handler to locate the input model. - /// The type of the output model. - /// The model that is being handled by a registered delegate. - /// The function delegate that will locate and invoke the handler registered to the specified . - /// The response of the request. - /// A can be a command, domain event, integration event, query etc. - protected virtual TResponse Dispatch(TRequest request, Func> handlerFactory) - where TRequest : IRequest - where THandler : IHandler + /// + /// Dispatches the specified using Request-Reply/In-Out MEP. + /// + /// The type of the input model registered to a handler. + /// The type of the handler to locate the input model. + /// The type of the output model. + /// The model that is being handled by a registered delegate. + /// The function delegate that will locate and invoke the handler registered to the specified . + /// The response of the request. + /// A can be a command, domain event, integration event, query etc. + protected virtual TResponse Dispatch(TRequest request, Func> handlerFactory) + where TRequest : IRequest + where THandler : IHandler + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(handlerFactory); + var handlerType = typeof(THandler); + if (ServiceFactory(handlerType) is IEnumerable handlers) { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(handlerFactory); - var handlerType = typeof(THandler); - if (ServiceFactory(handlerType) is IEnumerable handlers) + foreach (var handler in handlers) { - foreach (var handler in handlers) + if (handlerFactory(handler).TryInvoke(request, out TResponse result)) { - if (handlerFactory(handler).TryInvoke(request, out TResponse result)) - { - return result; - } + return result; } } - throw OrphanedHandlerException.Create(request, nameof(request)); } + throw OrphanedHandlerException.Create(request, nameof(request)); + } - /// - /// Dispatches the specified asynchronous using Request-Reply/In-Out MEP. - /// - /// The type of the input model registered to a handler. - /// The type of the handler to locate the input model. - /// The type of the output model. - /// The model that is being handled by a registered delegate. - /// The function delegate that will locate and invoke the handler registered to the specified . - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains the response of the request. - /// A can be a command, domain event, integration event, query etc. - protected virtual async Task DispatchAsync(TRequest request, Func> handlerFactory, Action setup) - where TRequest : IRequest - where THandler : IHandler + /// + /// Dispatches the specified asynchronous using Request-Reply/In-Out MEP. + /// + /// The type of the input model registered to a handler. + /// The type of the handler to locate the input model. + /// The type of the output model. + /// The model that is being handled by a registered delegate. + /// The function delegate that will locate and invoke the handler registered to the specified . + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains the response of the request. + /// A can be a command, domain event, integration event, query etc. + protected virtual async Task DispatchAsync(TRequest request, Func> handlerFactory, Action setup) + where TRequest : IRequest + where THandler : IHandler + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(handlerFactory); + var options = setup.Configure(); + var handlerType = typeof(THandler); + if (ServiceFactory(handlerType) is IEnumerable handlers) { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(handlerFactory); - var options = setup.Configure(); - var handlerType = typeof(THandler); - if (ServiceFactory(handlerType) is IEnumerable handlers) + foreach (var handler in handlers) { - foreach (var handler in handlers) + var operation = await handlerFactory(handler).TryInvokeAsync(request, options.CancellationToken).ConfigureAwait(false); + if (operation.Succeeded) { - var operation = await handlerFactory(handler).TryInvokeAsync(request, options.CancellationToken).ConfigureAwait(false); - if (operation.Succeeded) - { - return operation.Result; - } + return operation.Result; } } - throw OrphanedHandlerException.Create(request, nameof(request)); } + throw OrphanedHandlerException.Create(request, nameof(request)); } } diff --git a/src/Savvyio.Core/Dispatchers/ServiceLocator.cs b/src/Savvyio.Core/Dispatchers/ServiceLocator.cs index 9030150f..57fd183b 100644 --- a/src/Savvyio.Core/Dispatchers/ServiceLocator.cs +++ b/src/Savvyio.Core/Dispatchers/ServiceLocator.cs @@ -1,33 +1,32 @@ using System; using System.Collections.Generic; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +/// +/// Provides a default implementation of the interface. +/// +/// +public class ServiceLocator : IServiceLocator { + private readonly Func> _serviceFactory; + /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// - public class ServiceLocator : IServiceLocator + /// The function delegate that provides the services. + public ServiceLocator(Func> serviceFactory) { - private readonly Func> _serviceFactory; - - /// - /// Initializes a new instance of the class. - /// - /// The function delegate that provides the services. - public ServiceLocator(Func> serviceFactory) - { - _serviceFactory = serviceFactory; - } + _serviceFactory = serviceFactory; + } - /// - /// Get an enumeration of services of type . - /// - /// An object that specifies the type of service object to get. - /// An enumeration of services of type . - public IEnumerable GetServices(Type serviceType) - { - return _serviceFactory?.Invoke(serviceType); - } + /// + /// Get an enumeration of services of type . + /// + /// An object that specifies the type of service object to get. + /// An enumeration of services of type . + public IEnumerable GetServices(Type serviceType) + { + return _serviceFactory?.Invoke(serviceType); } } diff --git a/src/Savvyio.Core/Domain/DomainException.cs b/src/Savvyio.Core/Domain/DomainException.cs index fbb3e2db..0b003a5f 100644 --- a/src/Savvyio.Core/Domain/DomainException.cs +++ b/src/Savvyio.Core/Domain/DomainException.cs @@ -1,34 +1,33 @@ using System; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// The exception that is thrown when a domain model is not in a valid state. +/// +public class DomainException : Exception { /// - /// The exception that is thrown when a domain model is not in a valid state. + /// Initializes a new instance of the class. /// - public class DomainException : Exception + public DomainException() : this(null) { - /// - /// Initializes a new instance of the class. - /// - public DomainException() : this(null) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The exception that is the cause of the current exception. - public DomainException(Exception innerException) : this(default, innerException) - { - } + /// + /// Initializes a new instance of the class. + /// + /// The exception that is the cause of the current exception. + public DomainException(Exception innerException) : this(default, innerException) + { + } - /// - /// Initializes a new instance of the class. - /// - /// The message that describes the invalid state of the domain model. - /// The exception that is the cause of the current exception. - public DomainException(string message, Exception innerException = null) : base(message, innerException) - { - } + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the invalid state of the domain model. + /// The exception that is the cause of the current exception. + public DomainException(string message, Exception innerException = null) : base(message, innerException) + { } } diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs index 97a5c164..9c5a28cd 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs @@ -1,13 +1,12 @@ -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Defines a generic way of abstracting traced read- and writable repositories (CRud) that is optimized for Domain Driven Design. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +/// +public interface ITracedAggregateRepository : IReadableRepository, IWritableRepository where TEntity : class, ITracedAggregateRoot { - /// - /// Defines a generic way of abstracting traced read- and writable repositories (CRud) that is optimized for Domain Driven Design. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - /// - public interface ITracedAggregateRepository : IReadableRepository, IWritableRepository where TEntity : class, ITracedAggregateRoot - { - } } diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs index ad21befe..23cfc2b4 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs @@ -1,17 +1,16 @@ -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Defines an Event Sourcing capable contract of an Aggregate as specified in Domain Driven Design. +/// Implements the +/// +/// The type of the key that uniquely identifies this aggregate. +/// +public interface ITracedAggregateRoot : IAggregateRoot, IEntity { /// - /// Defines an Event Sourcing capable contract of an Aggregate as specified in Domain Driven Design. - /// Implements the + /// Gets the version of the Aggregate. /// - /// The type of the key that uniquely identifies this aggregate. - /// - public interface ITracedAggregateRoot : IAggregateRoot, IEntity - { - /// - /// Gets the version of the Aggregate. - /// - /// The version of the Aggregate. - long Version { get; } - } + /// The version of the Aggregate. + long Version { get; } } diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs index cec62b75..251fa0a2 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs @@ -1,9 +1,8 @@ -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. +/// +public interface ITracedDomainEvent : IDomainEvent { - /// - /// Specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. - /// - public interface ITracedDomainEvent : IDomainEvent - { - } } diff --git a/src/Savvyio.Core/Domain/IAggregateRepository.cs b/src/Savvyio.Core/Domain/IAggregateRepository.cs index c27c29a2..6bfd8a67 100644 --- a/src/Savvyio.Core/Domain/IAggregateRepository.cs +++ b/src/Savvyio.Core/Domain/IAggregateRepository.cs @@ -1,12 +1,11 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting persistent repositories (CRUD) that is optimized for Domain Driven Design. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public interface IAggregateRepository : IPersistentRepository where TEntity : class, IAggregateRoot { - /// - /// Defines a generic way of abstracting persistent repositories (CRUD) that is optimized for Domain Driven Design. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public interface IAggregateRepository : IPersistentRepository where TEntity : class, IAggregateRoot - { - } } diff --git a/src/Savvyio.Core/Domain/IAggregateRoot.cs b/src/Savvyio.Core/Domain/IAggregateRoot.cs index bc858784..d242507b 100644 --- a/src/Savvyio.Core/Domain/IAggregateRoot.cs +++ b/src/Savvyio.Core/Domain/IAggregateRoot.cs @@ -1,41 +1,40 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a marker interface of an Aggregate as specified in Domain Driven Design. +/// +public interface IAggregateRoot : IMetadata { - /// - /// Defines a marker interface of an Aggregate as specified in Domain Driven Design. - /// - public interface IAggregateRoot : IMetadata - { - } +} +/// +/// Defines an Event based contract of an Aggregate as specified in Domain Driven Design. +/// +/// The type of the event that implements the interface. +/// +public interface IAggregateRoot : IAggregateRoot +{ /// - /// Defines an Event based contract of an Aggregate as specified in Domain Driven Design. + /// Gets the events that was added to the Aggregate. /// - /// The type of the event that implements the interface. - /// - public interface IAggregateRoot : IAggregateRoot - { - /// - /// Gets the events that was added to the Aggregate. - /// - /// The events added to the Aggregate. - IReadOnlyList Events { get; } - - /// - /// Removes all events from the Aggregate. - /// - void RemoveAllEvents(); - } + /// The events added to the Aggregate. + IReadOnlyList Events { get; } /// - /// Defines an Event and Entity based contract of an Aggregate as specified in Domain Driven Design. + /// Removes all events from the Aggregate. /// - /// The type of the event that implements the interface. - /// The type of the key that uniquely identifies this Aggregate. - /// - /// - public interface IAggregateRoot : IAggregateRoot, IEntity - { - } + void RemoveAllEvents(); +} + +/// +/// Defines an Event and Entity based contract of an Aggregate as specified in Domain Driven Design. +/// +/// The type of the event that implements the interface. +/// The type of the key that uniquely identifies this Aggregate. +/// +/// +public interface IAggregateRoot : IAggregateRoot, IEntity +{ } diff --git a/src/Savvyio.Core/Domain/IDeletableRepository.cs b/src/Savvyio.Core/Domain/IDeletableRepository.cs index 0bc3b92e..b7e9c12e 100644 --- a/src/Savvyio.Core/Domain/IDeletableRepository.cs +++ b/src/Savvyio.Core/Domain/IDeletableRepository.cs @@ -1,25 +1,24 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting deletable repositories (cruD). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public interface IDeletableRepository : IRepository where TEntity : class, IIdentity { /// - /// Defines a generic way of abstracting deletable repositories (cruD). + /// Marks the specified to be removed from the data store when is called. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public interface IDeletableRepository : IRepository where TEntity : class, IIdentity - { - /// - /// Marks the specified to be removed from the data store when is called. - /// - /// The entity to remove. - void Remove(TEntity entity); + /// The entity to remove. + void Remove(TEntity entity); - /// - /// Marks the specified to be removed from the data store when is called. - /// - /// The entities to remove. - void RemoveRange(IEnumerable entities); - } + /// + /// Marks the specified to be removed from the data store when is called. + /// + /// The entities to remove. + void RemoveRange(IEnumerable entities); } diff --git a/src/Savvyio.Core/Domain/IDomainEvent.cs b/src/Savvyio.Core/Domain/IDomainEvent.cs index 6027f046..87ab1074 100644 --- a/src/Savvyio.Core/Domain/IDomainEvent.cs +++ b/src/Savvyio.Core/Domain/IDomainEvent.cs @@ -1,9 +1,8 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// A marker interface that specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be made aware of. +/// +public interface IDomainEvent : IRequest, IMetadata { - /// - /// A marker interface that specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be made aware of. - /// - public interface IDomainEvent : IRequest, IMetadata - { - } } diff --git a/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs b/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs index 493becfd..37be0347 100644 --- a/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs +++ b/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs @@ -3,26 +3,25 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a Domain Event dispatcher that uses Fire-and-Forget/In-Only MEP. +/// +/// +public interface IDomainEventDispatcher : IDispatcher { /// - /// Defines a Domain Event dispatcher that uses Fire-and-Forget/In-Only MEP. + /// Invokes any domain event handlers that is assigned to the specified event. /// - /// - public interface IDomainEventDispatcher : IDispatcher - { - /// - /// Invokes any domain event handlers that is assigned to the specified event. - /// - /// The to raise. - void Raise(IDomainEvent request); + /// The to raise. + void Raise(IDomainEvent request); - /// - /// Invokes any domain event handlers that is assigned to the specified event. - /// - /// The to raise. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task RaiseAsync(IDomainEvent request, Action setup = null); - } + /// + /// Invokes any domain event handlers that is assigned to the specified event. + /// + /// The to raise. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task RaiseAsync(IDomainEvent request, Action setup = null); } diff --git a/src/Savvyio.Core/Domain/IDomainEventHandler.cs b/src/Savvyio.Core/Domain/IDomainEventHandler.cs index 67b12351..fd7c6a04 100644 --- a/src/Savvyio.Core/Domain/IDomainEventHandler.cs +++ b/src/Savvyio.Core/Domain/IDomainEventHandler.cs @@ -1,12 +1,11 @@ using Savvyio.Handlers; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Specifies a handler responsible for objects that implements the interface. +/// +/// +public interface IDomainEventHandler : IFireForgetHandler { - /// - /// Specifies a handler responsible for objects that implements the interface. - /// - /// - public interface IDomainEventHandler : IFireForgetHandler - { - } } diff --git a/src/Savvyio.Core/Domain/IEntity.cs b/src/Savvyio.Core/Domain/IEntity.cs index 2fd07698..60aa8d38 100644 --- a/src/Savvyio.Core/Domain/IEntity.cs +++ b/src/Savvyio.Core/Domain/IEntity.cs @@ -1,11 +1,10 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines an Entity as specified in Domain Driven Design. +/// +/// The type of the identifier. +/// +public interface IEntity : IIdentity { - /// - /// Defines an Entity as specified in Domain Driven Design. - /// - /// The type of the identifier. - /// - public interface IEntity : IIdentity - { - } } diff --git a/src/Savvyio.Core/Domain/IPersistentRepository.cs b/src/Savvyio.Core/Domain/IPersistentRepository.cs index fe92e468..e093e58f 100644 --- a/src/Savvyio.Core/Domain/IPersistentRepository.cs +++ b/src/Savvyio.Core/Domain/IPersistentRepository.cs @@ -1,15 +1,14 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting persistent repositories (CRUD). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +/// +/// +/// +public interface IPersistentRepository : IWritableRepository, IReadableRepository, ISearchableRepository, IDeletableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way of abstracting persistent repositories (CRUD). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - /// - /// - /// - public interface IPersistentRepository : IWritableRepository, IReadableRepository, ISearchableRepository, IDeletableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Core/Domain/IReadableRepository.cs b/src/Savvyio.Core/Domain/IReadableRepository.cs index c4371f5b..44687000 100644 --- a/src/Savvyio.Core/Domain/IReadableRepository.cs +++ b/src/Savvyio.Core/Domain/IReadableRepository.cs @@ -2,22 +2,21 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting readable repositories (cRud). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public interface IReadableRepository : IRepository where TEntity : class, IIdentity { /// - /// Defines a generic way of abstracting readable repositories (cRud). + /// Loads the entity from the specified asynchronous. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public interface IReadableRepository : IRepository where TEntity : class, IIdentity - { - /// - /// Loads the entity from the specified asynchronous. - /// - /// The key that uniquely identifies the entity. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. - Task GetByIdAsync(TKey id, Action setup = null); - } + /// The key that uniquely identifies the entity. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. + Task GetByIdAsync(TKey id, Action setup = null); } diff --git a/src/Savvyio.Core/Domain/IRepository.cs b/src/Savvyio.Core/Domain/IRepository.cs index 34848d89..bae651da 100644 --- a/src/Savvyio.Core/Domain/IRepository.cs +++ b/src/Savvyio.Core/Domain/IRepository.cs @@ -1,11 +1,10 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// A marker interface that specifies an abstraction of data persistence based on the Repository pattern. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +public interface IRepository where TEntity : class, IIdentity { - /// - /// A marker interface that specifies an abstraction of data persistence based on the Repository pattern. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - public interface IRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Core/Domain/ISearchableRepository.cs b/src/Savvyio.Core/Domain/ISearchableRepository.cs index a15b1847..4c209dca 100644 --- a/src/Savvyio.Core/Domain/ISearchableRepository.cs +++ b/src/Savvyio.Core/Domain/ISearchableRepository.cs @@ -4,22 +4,21 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting searchable repositories (cRud). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public interface ISearchableRepository : IRepository where TEntity : class, IIdentity { /// - /// Defines a generic way of abstracting searchable repositories (cRud). + /// Finds all entities matching the specified asynchronous. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public interface ISearchableRepository : IRepository where TEntity : class, IIdentity - { - /// - /// Finds all entities matching the specified asynchronous. - /// - /// The predicate that matches the entities to retrieve. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the matching entities of the operation or an empty sequence if no match was found. - Task> FindAllAsync(Expression> predicate = null, Action setup = null); - } + /// The predicate that matches the entities to retrieve. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the matching entities of the operation or an empty sequence if no match was found. + Task> FindAllAsync(Expression> predicate = null, Action setup = null); } diff --git a/src/Savvyio.Core/Domain/IUnitOfWork.cs b/src/Savvyio.Core/Domain/IUnitOfWork.cs index d890990c..ba16b184 100644 --- a/src/Savvyio.Core/Domain/IUnitOfWork.cs +++ b/src/Savvyio.Core/Domain/IUnitOfWork.cs @@ -2,18 +2,17 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a transaction that bundles multiple calls into a single unit. +/// +public interface IUnitOfWork { /// - /// Defines a transaction that bundles multiple calls into a single unit. + /// Saves the different implementations as one transaction towards a data store asynchronous. /// - public interface IUnitOfWork - { - /// - /// Saves the different implementations as one transaction towards a data store asynchronous. - /// - /// The which may be configured. - /// A that represents the asynchronous operation. - Task SaveChangesAsync(Action setup = null); - } + /// The which may be configured. + /// A that represents the asynchronous operation. + Task SaveChangesAsync(Action setup = null); } diff --git a/src/Savvyio.Core/Domain/IWritableRepository.cs b/src/Savvyio.Core/Domain/IWritableRepository.cs index 555a640f..07628138 100644 --- a/src/Savvyio.Core/Domain/IWritableRepository.cs +++ b/src/Savvyio.Core/Domain/IWritableRepository.cs @@ -1,25 +1,24 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Defines a generic way of abstracting writable repositories (CrUd). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public interface IWritableRepository : IRepository where TEntity : class, IIdentity { /// - /// Defines a generic way of abstracting writable repositories (CrUd). + /// Marks the specified to be added in the data store when is called. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public interface IWritableRepository : IRepository where TEntity : class, IIdentity - { - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The entity to add. - void Add(TEntity entity); + /// The entity to add. + void Add(TEntity entity); - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The entities to add. - void AddRange(IEnumerable entities); - } + /// + /// Marks the specified to be added in the data store when is called. + /// + /// The entities to add. + void AddRange(IEnumerable entities); } diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs b/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs index 5a49b309..7e8cb9a4 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs @@ -1,9 +1,8 @@ -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// A marker interface that specifies something that happened when an object was successfully persisted and you want other subsystems (out-process/inter-application) to be made aware of. +/// +public interface IIntegrationEvent : IRequest, IMetadata { - /// - /// A marker interface that specifies something that happened when an object was successfully persisted and you want other subsystems (out-process/inter-application) to be made aware of. - /// - public interface IIntegrationEvent : IRequest, IMetadata - { - } } diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs b/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs index 5d6733a1..38731767 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs @@ -3,26 +3,25 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Defines an Integration Event dispatcher that uses Fire-and-Forget/In-Only MEP. +/// +/// +public interface IIntegrationEventDispatcher : IDispatcher { /// - /// Defines an Integration Event dispatcher that uses Fire-and-Forget/In-Only MEP. + /// Publishes the specified using Fire-and-Forget/In-Only MEP. /// - /// - public interface IIntegrationEventDispatcher : IDispatcher - { - /// - /// Publishes the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - void Publish(IIntegrationEvent request); + /// The to publish. + void Publish(IIntegrationEvent request); - /// - /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task PublishAsync(IIntegrationEvent request, Action setup = null); - } + /// + /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task PublishAsync(IIntegrationEvent request, Action setup = null); } diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs b/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs index 7e1538a9..4d52df07 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs @@ -1,12 +1,11 @@ using Savvyio.Handlers; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Specifies a handler responsible for objects that implements the interface. +/// +/// +public interface IIntegrationEventHandler : IFireForgetHandler { - /// - /// Specifies a handler responsible for objects that implements the interface. - /// - /// - public interface IIntegrationEventHandler : IFireForgetHandler - { - } } diff --git a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs index e647c186..dc09a089 100644 --- a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs +++ b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs @@ -1,14 +1,13 @@ using Savvyio.Messaging.Cryptography; -namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; + +/// +/// Defines a generic way to wrap an inside a CloudEvents compliant message format. +/// +/// The type of the payload constraint to the interface. +/// +/// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md +public interface ISignedCloudEvent : ICloudEvent, ISignedMessage where T : IIntegrationEvent { - /// - /// Defines a generic way to wrap an inside a CloudEvents compliant message format. - /// - /// The type of the payload constraint to the interface. - /// - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md - public interface ISignedCloudEvent : ICloudEvent, ISignedMessage where T : IIntegrationEvent - { - } } diff --git a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs index fccb0882..a44d8b27 100644 --- a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs +++ b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs @@ -1,21 +1,20 @@ using System.Collections.Generic; using Savvyio.Messaging; -namespace Savvyio.EventDriven.Messaging.CloudEvents +namespace Savvyio.EventDriven.Messaging.CloudEvents; + +/// +/// Defines a generic way to wrap an inside a CloudEvents compliant message format. +/// +/// The type of the payload constraint to the interface. +/// +/// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md +public interface ICloudEvent : IMessage, IDictionary where T : IIntegrationEvent { /// - /// Defines a generic way to wrap an inside a CloudEvents compliant message format. + /// Gets version of the CloudEvents specification which the event uses. /// - /// The type of the payload constraint to the interface. - /// - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md - public interface ICloudEvent : IMessage, IDictionary where T : IIntegrationEvent - { - /// - /// Gets version of the CloudEvents specification which the event uses. - /// - /// The version of the CloudEvents specification which the event uses. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#specversion - string Specversion { get; } - } + /// The version of the CloudEvents specification which the event uses. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#specversion + string Specversion { get; } } diff --git a/src/Savvyio.Core/HandlerDiscoveryModel.cs b/src/Savvyio.Core/HandlerDiscoveryModel.cs index f035e7f8..95a5fff0 100644 --- a/src/Savvyio.Core/HandlerDiscoveryModel.cs +++ b/src/Savvyio.Core/HandlerDiscoveryModel.cs @@ -6,204 +6,203 @@ using Cuemon.Extensions; using Cuemon.Extensions.Runtime; -namespace Savvyio +namespace Savvyio; + +/// +/// Represents a model for handler services discovery. +/// +public record HandlerDiscoveryModel { /// - /// Represents a model for handler services discovery. + /// Initializes a new instance of the class. /// - public record HandlerDiscoveryModel + /// The of the handler abstraction. + /// The of the delegate abstraction. + /// The implementations of the interface. + public HandlerDiscoveryModel(Type handlerAbstractionType, Type delegateAbstractionType, IGrouping>>> groupHandlers) { - /// - /// Initializes a new instance of the class. - /// - /// The of the handler abstraction. - /// The of the delegate abstraction. - /// The implementations of the interface. - public HandlerDiscoveryModel(Type handlerAbstractionType, Type delegateAbstractionType, IGrouping>>> groupHandlers) - { - Validator.ThrowIfNull(handlerAbstractionType); - Validator.ThrowIfNull(delegateAbstractionType); - Validator.ThrowIfNull(groupHandlers); + Validator.ThrowIfNull(handlerAbstractionType); + Validator.ThrowIfNull(delegateAbstractionType); + Validator.ThrowIfNull(groupHandlers); - var handlers = groupHandlers.Where(pair => pair.Key == handlerAbstractionType).SelectMany(pair => pair.Value).ToList(); - if (handlers.Count == 0) { return; } + var handlers = groupHandlers.Where(pair => pair.Key == handlerAbstractionType).SelectMany(pair => pair.Value).ToList(); + if (handlers.Count == 0) { return; } - var handlersDelegatesCount = 0; + var handlersDelegatesCount = 0; - var assemblyModels = new List(); - foreach (var group in handlers.GroupBy(h => new HandlerServiceAssemblyModel(h.Instance.As()))) - { - var delegateCount = 0; + var assemblyModels = new List(); + foreach (var group in handlers.GroupBy(h => new HandlerServiceAssemblyModel(h.Instance.As()))) + { + var delegateCount = 0; - var implementations = new List(); - foreach (var node in group) + var implementations = new List(); + foreach (var node in group) + { + if (node.Instance is Type handlerImplementationType) { - if (node.Instance is Type handlerImplementationType) - { - var implementation = new HandlerServiceTypeImplementationModel(node, handlerImplementationType, delegateAbstractionType); - delegateCount += implementation.DelegatesCount; - implementations.Add(implementation); - } + var implementation = new HandlerServiceTypeImplementationModel(node, handlerImplementationType, delegateAbstractionType); + delegateCount += implementation.DelegatesCount; + implementations.Add(implementation); } - - group.Key.Implementations = implementations; - - handlersDelegatesCount += delegateCount; - assemblyModels.Add(group.Key); } - ImplementationsCount = handlers.Count; - DelegatesCount = handlersDelegatesCount; - AbstractionType = handlerAbstractionType.Name; - DelegateType = delegateAbstractionType.Name; - Assemblies = assemblyModels; + group.Key.Implementations = implementations; + + handlersDelegatesCount += delegateCount; + assemblyModels.Add(group.Key); } - /// - /// Gets the name of the handler abstraction. - /// - public string AbstractionType { get; init; } - - /// - /// Gets the count of handler implementations. - /// - public int ImplementationsCount { get; init; } - - /// - /// Gets the name of the delegate abstraction. - /// - public string DelegateType { get; init; } - - /// - /// Gets the count of handler implementations delegates. - /// - public int DelegatesCount { get; init; } - - /// - /// Gets the assemblies containing the handler implementations. - /// - public IEnumerable Assemblies { get; init; } + ImplementationsCount = handlers.Count; + DelegatesCount = handlersDelegatesCount; + AbstractionType = handlerAbstractionType.Name; + DelegateType = delegateAbstractionType.Name; + Assemblies = assemblyModels; } /// - /// Represents a model for handler service assemblies. + /// Gets the name of the handler abstraction. /// - public record HandlerServiceAssemblyModel - { - /// - /// Initializes a new instance of the class. - /// - /// The of the handler implementation. - public HandlerServiceAssemblyModel(Type handlerImplementationType) - { - Validator.ThrowIfNull(handlerImplementationType); + public string AbstractionType { get; init; } - Name = handlerImplementationType.Assembly.GetName().Name; - Namespace = handlerImplementationType.Namespace; - } + /// + /// Gets the count of handler implementations. + /// + public int ImplementationsCount { get; init; } + + /// + /// Gets the name of the delegate abstraction. + /// + public string DelegateType { get; init; } - /// - /// Gets the name of the assembly. - /// - public string Name { get; init; } + /// + /// Gets the count of handler implementations delegates. + /// + public int DelegatesCount { get; init; } + + /// + /// Gets the assemblies containing the handler implementations. + /// + public IEnumerable Assemblies { get; init; } +} - /// - /// Gets the namespace of the handler implementation. - /// - public string Namespace { get; init; } +/// +/// Represents a model for handler service assemblies. +/// +public record HandlerServiceAssemblyModel +{ + /// + /// Initializes a new instance of the class. + /// + /// The of the handler implementation. + public HandlerServiceAssemblyModel(Type handlerImplementationType) + { + Validator.ThrowIfNull(handlerImplementationType); - /// - /// Gets or sets the implementations of the handler service type. - /// - public IEnumerable Implementations { get; internal set; } + Name = handlerImplementationType.Assembly.GetName().Name; + Namespace = handlerImplementationType.Namespace; } /// - /// Represents a model for handler service type implementations. + /// Gets the name of the assembly. + /// + public string Name { get; init; } + + /// + /// Gets the namespace of the handler implementation. + /// + public string Namespace { get; init; } + + /// + /// Gets or sets the implementations of the handler service type. /// - public record HandlerServiceTypeImplementationModel + public IEnumerable Implementations { get; internal set; } +} + +/// +/// Represents a model for handler service type implementations. +/// +public record HandlerServiceTypeImplementationModel +{ + /// + /// Initializes a new instance of the class. + /// + /// The hierarchy node. + /// The of the handler implementation. + /// The of the delegate abstraction. + public HandlerServiceTypeImplementationModel(IHierarchy node, Type handlerImplementationType, Type delegateAbstractionType) { - /// - /// Initializes a new instance of the class. - /// - /// The hierarchy node. - /// The of the handler implementation. - /// The of the delegate abstraction. - public HandlerServiceTypeImplementationModel(IHierarchy node, Type handlerImplementationType, Type delegateAbstractionType) - { - Validator.ThrowIfNull(node); - Validator.ThrowIfNull(handlerImplementationType); - Validator.ThrowIfNull(delegateAbstractionType); + Validator.ThrowIfNull(node); + Validator.ThrowIfNull(handlerImplementationType); + Validator.ThrowIfNull(delegateAbstractionType); - var delegates = new List(); - var children = node.GetChildren().ToList(); - foreach (var child in children.Select(h => h.Instance).OrderBy(h => h.As()?.Name, StringComparer.OrdinalIgnoreCase)) + var delegates = new List(); + var children = node.GetChildren().ToList(); + foreach (var child in children.Select(h => h.Instance).OrderBy(h => h.As()?.Name, StringComparer.OrdinalIgnoreCase)) + { + if (child is MethodInfo methodInfo) + { + var p = methodInfo.GetParameters().Single(p => p.ParameterType.HasInterfaces(delegateAbstractionType)); + delegates.Add(new HandlerServiceTypeImplementationDelegatesModel(p.ParameterType.Name, methodInfo.Name)); + DelegatesCount++; + } + else if (child is Type runtimeType) // we will get here when no class dependencies is specified (e.g., isolated 'method') { - if (child is MethodInfo methodInfo) + var nestedMethods = runtimeType.GetRuntimeMethods().Where(i => i.GetParameters().Any(p => p.ParameterType.HasInterfaces(delegateAbstractionType))); + foreach (var nested in nestedMethods) { - var p = methodInfo.GetParameters().Single(p => p.ParameterType.HasInterfaces(delegateAbstractionType)); - delegates.Add(new HandlerServiceTypeImplementationDelegatesModel(p.ParameterType.Name, methodInfo.Name)); + var p = nested.GetParameters().Single(); + delegates.Add(new HandlerServiceTypeImplementationDelegatesModel(p.ParameterType.Name, nested.Name)); DelegatesCount++; } - else if (child is Type runtimeType) // we will get here when no class dependencies is specified (e.g., isolated 'method') - { - var nestedMethods = runtimeType.GetRuntimeMethods().Where(i => i.GetParameters().Any(p => p.ParameterType.HasInterfaces(delegateAbstractionType))); - foreach (var nested in nestedMethods) - { - var p = nested.GetParameters().Single(); - delegates.Add(new HandlerServiceTypeImplementationDelegatesModel(p.ParameterType.Name, nested.Name)); - DelegatesCount++; - } - } } - - Name = handlerImplementationType.ToFriendlyName(); - Delegates = delegates; } - /// - /// Gets the name of the handler implementation. - /// - public string Name { get; init; } + Name = handlerImplementationType.ToFriendlyName(); + Delegates = delegates; + } - /// - /// Gets the count of delegates for the handler implementation. - /// - internal int DelegatesCount { get; init; } + /// + /// Gets the name of the handler implementation. + /// + public string Name { get; init; } - /// - /// Gets the delegates of the handler implementation. - /// - public IEnumerable Delegates { get; init; } - } + /// + /// Gets the count of delegates for the handler implementation. + /// + internal int DelegatesCount { get; init; } + + /// + /// Gets the delegates of the handler implementation. + /// + public IEnumerable Delegates { get; init; } +} +/// +/// Represents a model for handler service type implementation delegates. +/// +public record HandlerServiceTypeImplementationDelegatesModel +{ /// - /// Represents a model for handler service type implementation delegates. + /// Initializes a new instance of the class. /// - public record HandlerServiceTypeImplementationDelegatesModel + /// Type of the delegate model. + /// Type of the delegate method. + public HandlerServiceTypeImplementationDelegatesModel(string type, string handler) { - /// - /// Initializes a new instance of the class. - /// - /// Type of the delegate model. - /// Type of the delegate method. - public HandlerServiceTypeImplementationDelegatesModel(string type, string handler) - { - Validator.ThrowIfNull(type); - Validator.ThrowIfNull(handler); + Validator.ThrowIfNull(type); + Validator.ThrowIfNull(handler); - Type = type; - Handler = handler; - } + Type = type; + Handler = handler; + } - /// - /// Gets the name of the delegate model. - /// - public string Type { get; init; } + /// + /// Gets the name of the delegate model. + /// + public string Type { get; init; } - /// - /// Gets the name of the delegate method. - /// - public string Handler { get; init; } - } + /// + /// Gets the name of the delegate method. + /// + public string Handler { get; init; } } diff --git a/src/Savvyio.Core/HandlerFactory.cs b/src/Savvyio.Core/HandlerFactory.cs index 62de0af1..26900d74 100644 --- a/src/Savvyio.Core/HandlerFactory.cs +++ b/src/Savvyio.Core/HandlerFactory.cs @@ -2,39 +2,38 @@ using Cuemon; using Savvyio.Handlers; -namespace Savvyio +namespace Savvyio; + +/// +/// Provides access to factory methods for creating and configuring generic handlers that supports MEP. +/// +public static class HandlerFactory { /// - /// Provides access to factory methods for creating and configuring generic handlers that supports MEP. + /// Creates an instance of a Fire-and-Forget/In-Only MEP activator responsible of invoking delegates that handles . /// - public static class HandlerFactory + /// The type of the model to handle. + /// The delegate responsible for registering delegates of type . + /// An implementation of the interface responsible of invoking delegates that handles . + public static IFireForgetActivator CreateFireForget(Action> handlerRegistrar) { - /// - /// Creates an instance of a Fire-and-Forget/In-Only MEP activator responsible of invoking delegates that handles . - /// - /// The type of the model to handle. - /// The delegate responsible for registering delegates of type . - /// An implementation of the interface responsible of invoking delegates that handles . - public static IFireForgetActivator CreateFireForget(Action> handlerRegistrar) - { - Validator.ThrowIfNull(handlerRegistrar); - var handlerManager = new FireForgetManager(); - handlerRegistrar(handlerManager); - return handlerManager; - } + Validator.ThrowIfNull(handlerRegistrar); + var handlerManager = new FireForgetManager(); + handlerRegistrar(handlerManager); + return handlerManager; + } - /// - /// Creates an instance of a Request-Reply/In-Out MEP activator responsible of invoking delegates that handles . - /// - /// The type of the model to handle. - /// The delegate responsible for registering delegates of type . - /// An implementation of the interface responsible of invoking delegates that handles . - public static IRequestReplyActivator CreateRequestReply(Action> handlerRegistrar) - { - Validator.ThrowIfNull(handlerRegistrar); - var handlerManager = new RequestReplyManager(); - handlerRegistrar(handlerManager); - return handlerManager; - } + /// + /// Creates an instance of a Request-Reply/In-Out MEP activator responsible of invoking delegates that handles . + /// + /// The type of the model to handle. + /// The delegate responsible for registering delegates of type . + /// An implementation of the interface responsible of invoking delegates that handles . + public static IRequestReplyActivator CreateRequestReply(Action> handlerRegistrar) + { + Validator.ThrowIfNull(handlerRegistrar); + var handlerManager = new RequestReplyManager(); + handlerRegistrar(handlerManager); + return handlerManager; } } diff --git a/src/Savvyio.Core/HandlerServicesDescriptor.cs b/src/Savvyio.Core/HandlerServicesDescriptor.cs index e07b7f59..66c0e7a7 100644 --- a/src/Savvyio.Core/HandlerServicesDescriptor.cs +++ b/src/Savvyio.Core/HandlerServicesDescriptor.cs @@ -8,121 +8,120 @@ using Cuemon.Extensions; using Cuemon.Extensions.Runtime; -namespace Savvyio +namespace Savvyio; + +/// +/// Provides information, in a developer friendly way, about implementations of the interface such as name, declared members and what type of request they handle. +/// +/// +/// An example of the output available when calling :
+///
+/// Discovered 1 ICommandHandler implementation covering a total of 5 ICommand methods
+///
+///
+/// Assembly: Savvyio.Assets.Tests
+/// Namespace: Savvyio.Assets
+///
+/// <AccountCommandHandler>
+/// *UpdateAccount --> &<RegisterDelegates>b__5_0
+/// *CreateAccount --> &CreateAccountAsync
+///
> +public class HandlerServicesDescriptor : IHandlerServicesDescriptor { + private List _models; + private readonly Lock _locker = new(); + /// - /// Provides information, in a developer friendly way, about implementations of the interface such as name, declared members and what type of request they handle. + /// Initializes a new instance of the class. /// - /// - /// An example of the output available when calling :
- ///
- /// Discovered 1 ICommandHandler implementation covering a total of 5 ICommand methods
- ///
- ///
- /// Assembly: Savvyio.Assets.Tests
- /// Namespace: Savvyio.Assets
- ///
- /// <AccountCommandHandler>
- /// *UpdateAccount --> &<RegisterDelegates>b__5_0
- /// *CreateAccount --> &CreateAccountAsync
- ///
> - public class HandlerServicesDescriptor : IHandlerServicesDescriptor + /// The discovered implementations of the interface. + /// The registered service types. + public HandlerServicesDescriptor(IEnumerable>>>> discoveredServices, IEnumerable serviceTypes) { - private List _models; - private readonly Lock _locker = new(); - - /// - /// Initializes a new instance of the class. - /// - /// The discovered implementations of the interface. - /// The registered service types. - public HandlerServicesDescriptor(IEnumerable>>>> discoveredServices, IEnumerable serviceTypes) - { - DiscoveredServices = new List>>>>(discoveredServices ?? Enumerable.Empty>>>>()); - ServiceTypes = new List(serviceTypes ?? Enumerable.Empty()).OrderBy(type => type.Name).ToList(); - } + DiscoveredServices = new List>>>>(discoveredServices ?? Enumerable.Empty>>>>()); + ServiceTypes = new List(serviceTypes ?? Enumerable.Empty()).OrderBy(type => type.Name).ToList(); + } - private IReadOnlyList>>>> DiscoveredServices { get; } + private IReadOnlyList>>>> DiscoveredServices { get; } - private IReadOnlyList ServiceTypes { get; } + private IReadOnlyList ServiceTypes { get; } - /// - /// Returns a that represents this instance. - /// - /// A that represents this instance. - public override string ToString() + /// + /// Returns a that represents this instance. + /// + /// A that represents this instance. + public override string ToString() + { + var builder = new StringBuilder(); + foreach (var model in GenerateHandlerDiscoveries()) { - var builder = new StringBuilder(); - foreach (var model in GenerateHandlerDiscoveries()) + var discovery = FormatDiscoveryHeader(model); + builder.Append(discovery); + builder.AppendLine(); + foreach (var assembly in model.Assemblies) { - var discovery = FormatDiscoveryHeader(model); - builder.Append(discovery); - builder.AppendLine(); - foreach (var assembly in model.Assemblies) - { - AppendAssembly(builder, assembly); - } - builder.AppendLine(Generate.FixedString('-', discovery.Length.Max(discovery.Length.Max(discovery.Length)))); - builder.AppendLine(); + AppendAssembly(builder, assembly); } - return builder.ToString().TrimEnd(); + builder.AppendLine(Generate.FixedString('-', discovery.Length.Max(discovery.Length.Max(discovery.Length)))); + builder.AppendLine(); } + return builder.ToString().TrimEnd(); + } - private static string FormatDiscoveryHeader(HandlerDiscoveryModel model) - { - return $"Discovered {model.ImplementationsCount} {model.AbstractionType} implementation{(model.ImplementationsCount > 1 ? "s" : "")} covering a total of {model.DelegatesCount} {model.DelegateType} method{(model.DelegatesCount > 1 ? "s" : "")}"; - } + private static string FormatDiscoveryHeader(HandlerDiscoveryModel model) + { + return $"Discovered {model.ImplementationsCount} {model.AbstractionType} implementation{(model.ImplementationsCount > 1 ? "s" : "")} covering a total of {model.DelegatesCount} {model.DelegateType} method{(model.DelegatesCount > 1 ? "s" : "")}"; + } - private static void AppendAssembly(StringBuilder builder, HandlerServiceAssemblyModel assembly) - { - builder.AppendLine(); - builder.AppendLine(CultureInfo.InvariantCulture, $"Assembly: {assembly.Name}"); - builder.AppendLine(CultureInfo.InvariantCulture, $"Namespace: {assembly.Namespace}"); - builder.AppendLine(); + private static void AppendAssembly(StringBuilder builder, HandlerServiceAssemblyModel assembly) + { + builder.AppendLine(); + builder.AppendLine(CultureInfo.InvariantCulture, $"Assembly: {assembly.Name}"); + builder.AppendLine(CultureInfo.InvariantCulture, $"Namespace: {assembly.Namespace}"); + builder.AppendLine(); - foreach (var implementation in assembly.Implementations) + foreach (var implementation in assembly.Implementations) + { + builder.AppendLine(CultureInfo.InvariantCulture, $"<{implementation.Name}>"); + foreach (var @delegate in implementation.Delegates) { - builder.AppendLine(CultureInfo.InvariantCulture, $"<{implementation.Name}>"); - foreach (var @delegate in implementation.Delegates) - { - builder.AppendLine(CultureInfo.InvariantCulture, $"\t*{@delegate.Type} --> &{@delegate.Handler}"); - } - builder.AppendLine(); + builder.AppendLine(CultureInfo.InvariantCulture, $"\t*{@delegate.Type} --> &{@delegate.Handler}"); } + builder.AppendLine(); } + } - /// - /// Generates the handler discoveries. - /// - /// A collection of representing the handler discoveries. - public IEnumerable GenerateHandlerDiscoveries() - { - if (_models != null) { return _models; } + /// + /// Generates the handler discoveries. + /// + /// A collection of representing the handler discoveries. + public IEnumerable GenerateHandlerDiscoveries() + { + if (_models != null) { return _models; } - lock (_locker) - { - _models ??= BuildHandlerDiscoveries(); - } - return _models; + lock (_locker) + { + _models ??= BuildHandlerDiscoveries(); } + return _models; + } - private List BuildHandlerDiscoveries() + private List BuildHandlerDiscoveries() + { + var models = new List(); + foreach (var serviceType in ServiceTypes) { - var models = new List(); - foreach (var serviceType in ServiceTypes) + var serviceRequestType = serviceType.GetInterface("IHandler`1")?.GenericTypeArguments.Single(); + if (serviceRequestType == null) { continue; } + foreach (var discoveredServicesGroup in DiscoveredServices) { - var serviceRequestType = serviceType.GetInterface("IHandler`1")?.GenericTypeArguments.Single(); - if (serviceRequestType == null) { continue; } - foreach (var discoveredServicesGroup in DiscoveredServices) + var model = new HandlerDiscoveryModel(serviceType, serviceRequestType, discoveredServicesGroup); + if (model.ImplementationsCount > 0) { - var model = new HandlerDiscoveryModel(serviceType, serviceRequestType, discoveredServicesGroup); - if (model.ImplementationsCount > 0) - { - models.Add(model); - } + models.Add(model); } } - return models; } + return models; } } diff --git a/src/Savvyio.Core/Handlers/FireForgetManager.cs b/src/Savvyio.Core/Handlers/FireForgetManager.cs index 661dd93c..4c76c42f 100644 --- a/src/Savvyio.Core/Handlers/FireForgetManager.cs +++ b/src/Savvyio.Core/Handlers/FireForgetManager.cs @@ -4,49 +4,48 @@ using System.Threading.Tasks; using Cuemon; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +internal sealed class FireForgetManager : IFireForgetRegistry, IFireForgetActivator { - internal sealed class FireForgetManager : IFireForgetRegistry, IFireForgetActivator - { - private readonly ConcurrentDictionary> _handlers = new(); - private readonly ConcurrentDictionary> _asyncHandlers = new(); + private readonly ConcurrentDictionary> _handlers = new(); + private readonly ConcurrentDictionary> _asyncHandlers = new(); - public FireForgetManager() - { - } + public FireForgetManager() + { + } - public void Register(Action handler) where T : class, TRequest - { - Validator.ThrowIfNull(handler); - _handlers.TryAdd(typeof(T), e => handler(e as T)); - } + public void Register(Action handler) where T : class, TRequest + { + Validator.ThrowIfNull(handler); + _handlers.TryAdd(typeof(T), e => handler(e as T)); + } - public void RegisterAsync(Func handler) where T : class, TRequest - { - Validator.ThrowIfNull(handler); - _asyncHandlers.TryAdd(typeof(T), async (h, t) => await handler(h as T, t)); - } + public void RegisterAsync(Func handler) where T : class, TRequest + { + Validator.ThrowIfNull(handler); + _asyncHandlers.TryAdd(typeof(T), async (h, t) => await handler(h as T, t)); + } - public bool TryInvoke(TRequest request) + public bool TryInvoke(TRequest request) + { + Validator.ThrowIfNull(request); + if (_handlers.TryGetValue(request.GetType(), out var handler)) { - Validator.ThrowIfNull(request); - if (_handlers.TryGetValue(request.GetType(), out var handler)) - { - handler.Invoke(request); - return true; - } - return false; + handler.Invoke(request); + return true; } + return false; + } - public async Task TryInvokeAsync(TRequest request, CancellationToken ct = default) + public async Task TryInvokeAsync(TRequest request, CancellationToken ct = default) + { + Validator.ThrowIfNull(request); + if (_asyncHandlers.TryGetValue(request.GetType(), out var handler)) { - Validator.ThrowIfNull(request); - if (_asyncHandlers.TryGetValue(request.GetType(), out var handler)) - { - await handler(request, ct).ConfigureAwait(false); - return new SuccessfulValue(); - } - return new UnsuccessfulValue(); + await handler(request, ct).ConfigureAwait(false); + return new SuccessfulValue(); } + return new UnsuccessfulValue(); } } diff --git a/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs b/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs index 0f2cd25c..1ed26ae2 100644 --- a/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs +++ b/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs @@ -1,22 +1,21 @@ using System; using System.Threading.Tasks; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Extension methods for the interface. +/// +public static class FireForgetRegistryExtensions { /// - /// Extension methods for the interface. + /// Registers the specified function delegate . /// - public static class FireForgetRegistryExtensions + /// The type of the model to store in the registry. + /// The to extend. + /// The function delegate that handles . + public static void RegisterAsync(this IFireForgetRegistry registry, Func handler) where TRequest : class { - /// - /// Registers the specified function delegate . - /// - /// The type of the model to store in the registry. - /// The to extend. - /// The function delegate that handles . - public static void RegisterAsync(this IFireForgetRegistry registry, Func handler) where TRequest : class - { - registry.RegisterAsync((h, _) => handler(h)); - } + registry.RegisterAsync((h, _) => handler(h)); } } diff --git a/src/Savvyio.Core/Handlers/IFireForgetActivator.cs b/src/Savvyio.Core/Handlers/IFireForgetActivator.cs index a114ef37..f65a0e8f 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetActivator.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetActivator.cs @@ -2,28 +2,27 @@ using System.Threading.Tasks; using Cuemon; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Specifies a way of invoking Fire-and-Forget/In-Only MEP delegates that handles . +/// +/// The type of the model to invoke on a handler. +/// +public interface IFireForgetActivator { /// - /// Specifies a way of invoking Fire-and-Forget/In-Only MEP delegates that handles . + /// Invokes (if registered) the delegate handling the specified . /// - /// The type of the model to invoke on a handler. - /// - public interface IFireForgetActivator - { - /// - /// Invokes (if registered) the delegate handling the specified . - /// - /// The model that is handled by a delegate. - /// true if the delegate handling the specified was invoked, false otherwise. - bool TryInvoke(TRequest request); + /// The model that is handled by a delegate. + /// true if the delegate handling the specified was invoked, false otherwise. + bool TryInvoke(TRequest request); - /// - /// Invokes (if registered) the function delegate handling the specified . - /// - /// The model that is handled by a function delegate. - /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// true if the function delegate handling the specified was invoked, false otherwise. - Task TryInvokeAsync(TRequest request, CancellationToken ct = default); - } + /// + /// Invokes (if registered) the function delegate handling the specified . + /// + /// The model that is handled by a function delegate. + /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// true if the function delegate handling the specified was invoked, false otherwise. + Task TryInvokeAsync(TRequest request, CancellationToken ct = default); } diff --git a/src/Savvyio.Core/Handlers/IFireForgetHandler.cs b/src/Savvyio.Core/Handlers/IFireForgetHandler.cs index e3703c4a..a355a5af 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetHandler.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetHandler.cs @@ -1,16 +1,15 @@ -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Defines a generic handler that uses Fire-and-Forget/In-Only MEP. +/// +/// The type of the model to handle. +/// +public interface IFireForgetHandler : IHandler where TRequest : IRequest { /// - /// Defines a generic handler that uses Fire-and-Forget/In-Only MEP. + /// Gets the responsible of invoking delegates that handles the model. /// - /// The type of the model to handle. - /// - public interface IFireForgetHandler : IHandler where TRequest : IRequest - { - /// - /// Gets the responsible of invoking delegates that handles the model. - /// - /// The responsible of invoking delegates of type . - public IFireForgetActivator Delegates { get; } - } + /// The responsible of invoking delegates of type . + public IFireForgetActivator Delegates { get; } } diff --git a/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs b/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs index 8149518d..14d0d8c2 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs @@ -2,27 +2,26 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Specifies a Fire-and-Forget/In-Only MEP registry that store delegates responsible for handling type . +/// +/// The type of the model to store in the registry. +/// +public interface IFireForgetRegistry { /// - /// Specifies a Fire-and-Forget/In-Only MEP registry that store delegates responsible for handling type . + /// Registers the specified delegate . /// - /// The type of the model to store in the registry. - /// - public interface IFireForgetRegistry - { - /// - /// Registers the specified delegate . - /// - /// The type that implements . - /// The delegate that handles . - void Register(Action handler) where T : class, TRequest; + /// The type that implements . + /// The delegate that handles . + void Register(Action handler) where T : class, TRequest; - /// - /// Registers the specified function delegate . - /// - /// The type that implements . - /// The function delegate that handles . - void RegisterAsync(Func handler) where T : class, TRequest; - } + /// + /// Registers the specified function delegate . + /// + /// The type that implements . + /// The function delegate that handles . + void RegisterAsync(Func handler) where T : class, TRequest; } diff --git a/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs b/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs index 599254e6..46f58dee 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs @@ -2,31 +2,30 @@ using System.Threading.Tasks; using Cuemon; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Specifies a way of invoking Request-Reply/In-Out MEP delegates that handles . +/// +/// The type of the model to invoke on a handler. +/// +public interface IRequestReplyActivator { /// - /// Specifies a way of invoking Request-Reply/In-Out MEP delegates that handles . + /// Invokes (if registered) the delegate handling the specified . /// - /// The type of the model to invoke on a handler. - /// - public interface IRequestReplyActivator - { - /// - /// Invokes (if registered) the delegate handling the specified . - /// - /// The type of the response. - /// The model that is handled by a delegate. - /// The value returned from the request; otherwise the default value for of the parameter. - /// true if a delegate matching the specified was invoked; otherwise, false. - bool TryInvoke(TRequest request, out TResponse result); + /// The type of the response. + /// The model that is handled by a delegate. + /// The value returned from the request; otherwise the default value for of the parameter. + /// true if a delegate matching the specified was invoked; otherwise, false. + bool TryInvoke(TRequest request, out TResponse result); - /// - /// Invokes (if registered) the function delegate handling the specified . - /// - /// The type of the response. - /// The model that is handled by a function delegate. - /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A task that represents the asynchronous operation. The task result contains a that indicates if a function delegate matching the specified was invoked and with the potential result hereof. - Task> TryInvokeAsync(TRequest request, CancellationToken ct = default); - } + /// + /// Invokes (if registered) the function delegate handling the specified . + /// + /// The type of the response. + /// The model that is handled by a function delegate. + /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A task that represents the asynchronous operation. The task result contains a that indicates if a function delegate matching the specified was invoked and with the potential result hereof. + Task> TryInvokeAsync(TRequest request, CancellationToken ct = default); } diff --git a/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs b/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs index 75263273..cda32b26 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs @@ -1,16 +1,15 @@ -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Defines a generic Request-Reply/In-Out MEP handler. +/// +/// The type of the model to handle. +/// +public interface IRequestReplyHandler : IHandler where TRequest : IRequest { /// - /// Defines a generic Request-Reply/In-Out MEP handler. + /// Gets the responsible of invoking delegates that handles the model. /// - /// The type of the model to handle. - /// - public interface IRequestReplyHandler : IHandler where TRequest : IRequest - { - /// - /// Gets the responsible of invoking delegates that handles the model. - /// - /// The responsible of invoking delegates of type . - public IRequestReplyActivator Delegates { get; } - } + /// The responsible of invoking delegates of type . + public IRequestReplyActivator Delegates { get; } } diff --git a/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs b/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs index 8257df85..8e29b2d6 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs @@ -2,29 +2,28 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Specifies a Request-Reply/In-Out MEP registry that store delegates responsible for handling type . +/// +/// The type of the model to store in the registry. +/// +public interface IRequestReplyRegistry { /// - /// Specifies a Request-Reply/In-Out MEP registry that store delegates responsible for handling type . + /// Registers the specified function delegate . /// - /// The type of the model to store in the registry. - /// - public interface IRequestReplyRegistry - { - /// - /// Registers the specified function delegate . - /// - /// The type that implements . - /// The type of the response to return. - /// The function delegate that handles . - void Register(Func handler) where T : class, TRequest; + /// The type that implements . + /// The type of the response to return. + /// The function delegate that handles . + void Register(Func handler) where T : class, TRequest; - /// - /// Registers the specified function delegate . - /// - /// The type that implements . - /// The type of the response to return. - /// The function delegate that handles . - void RegisterAsync(Func> handler) where T : class, TRequest; - } + /// + /// Registers the specified function delegate . + /// + /// The type that implements . + /// The type of the response to return. + /// The function delegate that handles . + void RegisterAsync(Func> handler) where T : class, TRequest; } diff --git a/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs b/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs index 5a7e0bb6..a0de27ea 100644 --- a/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs +++ b/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs @@ -1,37 +1,36 @@ using System; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// The exception that is thrown when an implementation cannot be resolved. +/// +/// +public class OrphanedHandlerException : ArgumentException + { /// - /// The exception that is thrown when an implementation cannot be resolved. + /// Creates a new instance of using the provided generic type arguments. /// - /// - public class OrphanedHandlerException : ArgumentException - + /// The type of the input model registered to a handler. + /// The type of the handler to locate the input model. + /// The model that is being handled by a registered delegate. + /// The name of the parameter that caused the current exception. + /// A new instance of initialized from the provided generic type arguments. + public static OrphanedHandlerException Create(TRequest request, string paramName) + where TRequest : IRequest + where THandler : IHandler { - /// - /// Creates a new instance of using the provided generic type arguments. - /// - /// The type of the input model registered to a handler. - /// The type of the handler to locate the input model. - /// The model that is being handled by a registered delegate. - /// The name of the parameter that caused the current exception. - /// A new instance of initialized from the provided generic type arguments. - public static OrphanedHandlerException Create(TRequest request, string paramName) - where TRequest : IRequest - where THandler : IHandler - { - var requestType = request.GetType(); - return new OrphanedHandlerException($"Unable to retrieve an {typeof(THandler).Name} for the specified {requestType.Name}: {requestType.FullName}.", paramName); - } + var requestType = request.GetType(); + return new OrphanedHandlerException($"Unable to retrieve an {typeof(THandler).Name} for the specified {requestType.Name}: {requestType.FullName}.", paramName); + } - /// - /// Initializes a new instance of the class. - /// - /// The error message that explains the reason for the exception. - /// The name of the parameter that caused the current exception. - public OrphanedHandlerException(string message, string paramName) : base(message, paramName) - { - } + /// + /// Initializes a new instance of the class. + /// + /// The error message that explains the reason for the exception. + /// The name of the parameter that caused the current exception. + public OrphanedHandlerException(string message, string paramName) : base(message, paramName) + { } } diff --git a/src/Savvyio.Core/Handlers/RequestReplyManager.cs b/src/Savvyio.Core/Handlers/RequestReplyManager.cs index b8c19f17..5930da56 100644 --- a/src/Savvyio.Core/Handlers/RequestReplyManager.cs +++ b/src/Savvyio.Core/Handlers/RequestReplyManager.cs @@ -4,50 +4,49 @@ using System.Threading.Tasks; using Cuemon; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +internal sealed class RequestReplyManager : IRequestReplyRegistry, IRequestReplyActivator { - internal sealed class RequestReplyManager : IRequestReplyRegistry, IRequestReplyActivator - { - private readonly ConcurrentDictionary> _handlers = new(); - private readonly ConcurrentDictionary>> _asyncHandlers = new(); + private readonly ConcurrentDictionary> _handlers = new(); + private readonly ConcurrentDictionary>> _asyncHandlers = new(); - public RequestReplyManager() - { - } + public RequestReplyManager() + { + } - public void Register(Func handler) where T : class, TModel //, IRequestReply - { - Validator.ThrowIfNull(handler); - _handlers.TryAdd(typeof(T), e => handler(e as T)); - } + public void Register(Func handler) where T : class, TModel //, IRequestReply + { + Validator.ThrowIfNull(handler); + _handlers.TryAdd(typeof(T), e => handler(e as T)); + } - public void RegisterAsync(Func> handler) where T : class, TModel //, IRequestReply - { - Validator.ThrowIfNull(handler); - _asyncHandlers.TryAdd(typeof(T), async (h, t) => await handler(h as T, t)); - } + public void RegisterAsync(Func> handler) where T : class, TModel //, IRequestReply + { + Validator.ThrowIfNull(handler); + _asyncHandlers.TryAdd(typeof(T), async (h, t) => await handler(h as T, t)); + } - public bool TryInvoke(TModel request, out TResult result) + public bool TryInvoke(TModel request, out TResult result) + { + Validator.ThrowIfNull(request); + if (_handlers.TryGetValue(request.GetType(), out var handler)) { - Validator.ThrowIfNull(request); - if (_handlers.TryGetValue(request.GetType(), out var handler)) - { - result = (TResult)handler(request); - return true; - } - result = default; - return false; + result = (TResult)handler(request); + return true; } + result = default; + return false; + } - public async Task> TryInvokeAsync(TModel request, CancellationToken ct = default) + public async Task> TryInvokeAsync(TModel request, CancellationToken ct = default) + { + Validator.ThrowIfNull(request); + if (_asyncHandlers.TryGetValue(request.GetType(), out var handler)) { - Validator.ThrowIfNull(request); - if (_asyncHandlers.TryGetValue(request.GetType(), out var handler)) - { - var result = await handler(request, ct).ConfigureAwait(false); - return new SuccessfulValue((TResult)result); - } - return new UnsuccessfulValue(); + var result = await handler(request, ct).ConfigureAwait(false); + return new SuccessfulValue((TResult)result); } + return new UnsuccessfulValue(); } } diff --git a/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs b/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs index 9ed35efb..63c347df 100644 --- a/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs +++ b/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs @@ -1,23 +1,22 @@ using System; using System.Threading.Tasks; -namespace Savvyio.Handlers +namespace Savvyio.Handlers; + +/// +/// Extension methods for the interface. +/// +public static class RequestReplyRegistryExtensions { /// - /// Extension methods for the interface. + /// Registers the asynchronous. /// - public static class RequestReplyRegistryExtensions + /// The type of the model to store in the registry. + /// The type of the response to return. + /// The to extend. + /// The function delegate that handles . + public static void RegisterAsync(this IRequestReplyRegistry registry, Func> handler) where TRequest : class { - /// - /// Registers the asynchronous. - /// - /// The type of the model to store in the registry. - /// The type of the response to return. - /// The to extend. - /// The function delegate that handles . - public static void RegisterAsync(this IRequestReplyRegistry registry, Func> handler) where TRequest : class - { - registry.RegisterAsync((h, _) => handler(h)); - } + registry.RegisterAsync((h, _) => handler(h)); } } diff --git a/src/Savvyio.Core/IDataSource.cs b/src/Savvyio.Core/IDataSource.cs index 7aaf1078..5efad1c2 100644 --- a/src/Savvyio.Core/IDataSource.cs +++ b/src/Savvyio.Core/IDataSource.cs @@ -1,15 +1,14 @@ using Savvyio.Data; using Savvyio.Domain; -namespace Savvyio +namespace Savvyio; + +/// +/// A marker interface that specifies the actual I/O communication with a source of data. +/// +/// A data source can be anything that holds data, eg. high level DbContext (EFCore) to low level ADO.NET. It could also be as simple as files, services or anything that can expose data. +/// +/// +public interface IDataSource { - /// - /// A marker interface that specifies the actual I/O communication with a source of data. - /// - /// A data source can be anything that holds data, eg. high level DbContext (EFCore) to low level ADO.NET. It could also be as simple as files, services or anything that can expose data. - /// - /// - public interface IDataSource - { - } } diff --git a/src/Savvyio.Core/IHandler.cs b/src/Savvyio.Core/IHandler.cs index a695c4ee..824933ea 100644 --- a/src/Savvyio.Core/IHandler.cs +++ b/src/Savvyio.Core/IHandler.cs @@ -1,17 +1,16 @@ -namespace Savvyio +namespace Savvyio; + +/// +/// A marker interface that specifies a handler. +/// +public interface IHandler { - /// - /// A marker interface that specifies a handler. - /// - public interface IHandler - { - } +} - /// - /// Defines a marker interface for a generic handler. - /// - /// The type of the model to handle. - public interface IHandler : IHandler where TRequest : IRequest - { - } +/// +/// Defines a marker interface for a generic handler. +/// +/// The type of the model to handle. +public interface IHandler : IHandler where TRequest : IRequest +{ } diff --git a/src/Savvyio.Core/IHandlerServicesDescriptor.cs b/src/Savvyio.Core/IHandlerServicesDescriptor.cs index 0d7ae216..6d08992e 100644 --- a/src/Savvyio.Core/IHandlerServicesDescriptor.cs +++ b/src/Savvyio.Core/IHandlerServicesDescriptor.cs @@ -1,16 +1,15 @@ using System.Collections.Generic; -namespace Savvyio +namespace Savvyio; + +/// +/// Defines a contract about implementations of the interface such as name, declared members and what type of request they handle. +/// +public interface IHandlerServicesDescriptor { /// - /// Defines a contract about implementations of the interface such as name, declared members and what type of request they handle. + /// Generates the handler discoveries. /// - public interface IHandlerServicesDescriptor - { - /// - /// Generates the handler discoveries. - /// - /// A collection of representing the handler discoveries. - IEnumerable GenerateHandlerDiscoveries(); - } + /// A collection of representing the handler discoveries. + IEnumerable GenerateHandlerDiscoveries(); } diff --git a/src/Savvyio.Core/IIdentity.cs b/src/Savvyio.Core/IIdentity.cs index d8fc56a1..a1dfed8b 100644 --- a/src/Savvyio.Core/IIdentity.cs +++ b/src/Savvyio.Core/IIdentity.cs @@ -1,15 +1,14 @@ -namespace Savvyio +namespace Savvyio; + +/// +/// Defines a generic identity typically associated with a storage such as a database. +/// +/// The type of the identifier. +public interface IIdentity { /// - /// Defines a generic identity typically associated with a storage such as a database. + /// Gets the value of the identifier. /// - /// The type of the identifier. - public interface IIdentity - { - /// - /// Gets the value of the identifier. - /// - /// The value of the identifier. - TKey Id { get; } - } + /// The value of the identifier. + TKey Id { get; } } diff --git a/src/Savvyio.Core/IMarshaller.cs b/src/Savvyio.Core/IMarshaller.cs index c8143147..43e8dac1 100644 --- a/src/Savvyio.Core/IMarshaller.cs +++ b/src/Savvyio.Core/IMarshaller.cs @@ -1,42 +1,41 @@ using System; using System.IO; -namespace Savvyio +namespace Savvyio; + +/// +/// Defines methods for serializing and deserializing objects to and from a . +/// +public interface IMarshaller { /// - /// Defines methods for serializing and deserializing objects to and from a . + /// Serializes the specified to an object of . /// - public interface IMarshaller - { - /// - /// Serializes the specified to an object of . - /// - /// The object to serialize to format. - /// A of the serialized . - Stream Serialize(TValue value); + /// The object to serialize to format. + /// A of the serialized . + Stream Serialize(TValue value); - /// - /// Serializes the specified to an object of . - /// - /// The object to serialize to format. - /// The type of the object to serialize. - /// A of the serialized . - Stream Serialize(object value, Type inputType); + /// + /// Serializes the specified to an object of . + /// + /// The object to serialize to format. + /// The type of the object to serialize. + /// A of the serialized . + Stream Serialize(object value, Type inputType); - /// - /// Deserializes the specified into an object of . - /// - /// The type of the object to return. - /// The object from which to deserialize the object graph. - /// An object of . - TValue Deserialize(Stream data); + /// + /// Deserializes the specified into an object of . + /// + /// The type of the object to return. + /// The object from which to deserialize the object graph. + /// An object of . + TValue Deserialize(Stream data); - /// - /// Deserializes the specified into an object of . - /// - /// The string from which to deserialize the object graph. - /// The type of the deserialized object. - /// An object of . - object Deserialize(Stream data, Type returnType); - } + /// + /// Deserializes the specified into an object of . + /// + /// The string from which to deserialize the object graph. + /// The type of the deserialized object. + /// An object of . + object Deserialize(Stream data, Type returnType); } diff --git a/src/Savvyio.Core/IMetadata.cs b/src/Savvyio.Core/IMetadata.cs index 0ea6583d..d840eee0 100644 --- a/src/Savvyio.Core/IMetadata.cs +++ b/src/Savvyio.Core/IMetadata.cs @@ -1,14 +1,13 @@ -namespace Savvyio +namespace Savvyio; + +/// +/// Defines a generic way to associate metadata with any type of object. +/// +public interface IMetadata { /// - /// Defines a generic way to associate metadata with any type of object. + /// Gets the associated metadata of this instance. /// - public interface IMetadata - { - /// - /// Gets the associated metadata of this instance. - /// - /// The associated metadata of this instance. - public IMetadataDictionary Metadata { get; } - } + /// The associated metadata of this instance. + public IMetadataDictionary Metadata { get; } } diff --git a/src/Savvyio.Core/IMetadataDictionary.cs b/src/Savvyio.Core/IMetadataDictionary.cs index 0bd346ed..2c5f5353 100644 --- a/src/Savvyio.Core/IMetadataDictionary.cs +++ b/src/Savvyio.Core/IMetadataDictionary.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -namespace Savvyio +namespace Savvyio; + +/// +/// Defines a generic way to support metadata capabilities. +/// +/// +public interface IMetadataDictionary : IDictionary { - /// - /// Defines a generic way to support metadata capabilities. - /// - /// - public interface IMetadataDictionary : IDictionary - { - } } diff --git a/src/Savvyio.Core/IRequest.cs b/src/Savvyio.Core/IRequest.cs index 900a7cb5..43ecd512 100644 --- a/src/Savvyio.Core/IRequest.cs +++ b/src/Savvyio.Core/IRequest.cs @@ -1,10 +1,9 @@ -namespace Savvyio +namespace Savvyio; + +/// +/// A marker interface that specifies a request/model/event. +/// +/// A request can be a command, domain event, integration event, query etc. +public interface IRequest { - /// - /// A marker interface that specifies a request/model/event. - /// - /// A request can be a command, domain event, integration event, query etc. - public interface IRequest - { - } } diff --git a/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs b/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs index 2f4d8542..549e532b 100644 --- a/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs +++ b/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs @@ -1,36 +1,35 @@ using System; using System.Collections.Generic; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Provides data for message related operations. +/// +/// +public class AcknowledgedEventArgs : EventArgs { /// - /// Provides data for message related operations. + /// Represents an event with no event data. /// - /// - public class AcknowledgedEventArgs : EventArgs - { - /// - /// Represents an event with no event data. - /// - public new static readonly AcknowledgedEventArgs Empty = new(); - - AcknowledgedEventArgs() : this(null) - { - } + public new static readonly AcknowledgedEventArgs Empty = new(); - /// - /// Initializes a new instance of the class. - /// - /// The > to associate with the event. - public AcknowledgedEventArgs(IDictionary properties) - { - Properties = properties ?? new Dictionary(); - } + AcknowledgedEventArgs() : this(null) + { + } - /// - /// Share state between components during message processing. - /// - /// The state between components during message processing. - public IDictionary Properties { get; } + /// + /// Initializes a new instance of the class. + /// + /// The > to associate with the event. + public AcknowledgedEventArgs(IDictionary properties) + { + Properties = properties ?? new Dictionary(); } + + /// + /// Share state between components during message processing. + /// + /// The state between components during message processing. + public IDictionary Properties { get; } } diff --git a/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs b/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs index a96f5773..ca8a1149 100644 --- a/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs +++ b/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs @@ -1,15 +1,14 @@ -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +/// +/// Defines a generic way to wrap an inside a cryptographically signed message. +/// +/// The type of the payload constraint to the interface. + public interface ISignedMessage : IMessage where T : IRequest { /// - /// Defines a generic way to wrap an inside a cryptographically signed message. + /// Gets the cryptographic signature of the message. /// - /// The type of the payload constraint to the interface. - public interface ISignedMessage : IMessage where T : IRequest - { - /// - /// Gets the cryptographic signature of the message. - /// - /// The cryptographic signature of the message. - string Signature { get; } - } + /// The cryptographic signature of the message. + string Signature { get; } } diff --git a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs index b8a80245..8b1e3a6d 100644 --- a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs +++ b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs @@ -1,28 +1,27 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a generic way to make a message acknowledgeable. +/// +public interface IAcknowledgeable { /// - /// Defines a generic way to make a message acknowledgeable. + /// Occurs when the method is called. /// - public interface IAcknowledgeable - { - /// - /// Occurs when the method is called. - /// - event AsyncEventHandler Acknowledged; + event AsyncEventHandler Acknowledged; - /// - /// Share state between components during message processing. - /// - /// The state between components during message processing. - IDictionary Properties { get; } + /// + /// Share state between components during message processing. + /// + /// The state between components during message processing. + IDictionary Properties { get; } - /// - /// Acknowledges that this message was processed successfully. - /// - /// A task that represents the asynchronous operation. - Task AcknowledgeAsync(); - } + /// + /// Acknowledges that this message was processed successfully. + /// + /// A task that represents the asynchronous operation. + Task AcknowledgeAsync(); } diff --git a/src/Savvyio.Core/Messaging/IMessage.cs b/src/Savvyio.Core/Messaging/IMessage.cs index f2eb819c..5337a1bf 100644 --- a/src/Savvyio.Core/Messaging/IMessage.cs +++ b/src/Savvyio.Core/Messaging/IMessage.cs @@ -1,43 +1,42 @@ using System; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a generic way to wrap an inside a message. +/// +/// The type of the payload constraint to the interface. +/// Inspired by cloudevents.io (https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md) default attributes. +/// +public interface IMessage : IAcknowledgeable where T : IRequest { /// - /// Defines a generic way to wrap an inside a message. + /// Gets the identifier of the message. When combined with , this enables deduplication. /// - /// The type of the payload constraint to the interface. - /// Inspired by cloudevents.io (https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md) default attributes. - /// - public interface IMessage : IAcknowledgeable where T : IRequest - { - /// - /// Gets the identifier of the message. When combined with , this enables deduplication. - /// - /// The identifier of the message. - string Id { get; } + /// The identifier of the message. + string Id { get; } - /// - /// Gets the context that describes the origin of the message. When combined with , this enables deduplication. - /// - /// The context that describes the origin of the message. - public string Source { get; } + /// + /// Gets the context that describes the origin of the message. When combined with , this enables deduplication. + /// + /// The context that describes the origin of the message. + public string Source { get; } - /// - /// Gets the type that describes the type of event related to the originating occurrence. - /// - /// The type that describes the type of event related to the originating occurrence. - string Type { get; } + /// + /// Gets the type that describes the type of event related to the originating occurrence. + /// + /// The type that describes the type of event related to the originating occurrence. + string Type { get; } - /// - /// Gets the time, expressed as the Coordinated Universal Time (UTC), at which this message was generated. - /// - /// The time at which this message was generated. - DateTime? Time { get; } + /// + /// Gets the time, expressed as the Coordinated Universal Time (UTC), at which this message was generated. + /// + /// The time at which this message was generated. + DateTime? Time { get; } - /// - /// Gets the payload of the message. - /// - /// The payload of the message. - T Data { get; } - } + /// + /// Gets the payload of the message. + /// + /// The payload of the message. + T Data { get; } } diff --git a/src/Savvyio.Core/Messaging/IPointToPointChannel.cs b/src/Savvyio.Core/Messaging/IPointToPointChannel.cs index 9ae389d7..51d447b6 100644 --- a/src/Savvyio.Core/Messaging/IPointToPointChannel.cs +++ b/src/Savvyio.Core/Messaging/IPointToPointChannel.cs @@ -1,12 +1,11 @@ -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +/// +/// +public interface IPointToPointChannel : ISender, IReceiver where TRequest : IRequest { - /// - /// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). - /// - /// The type of the model to invoke on a handler. - /// - /// - public interface IPointToPointChannel : ISender, IReceiver where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs b/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs index 2caa059a..5bd136e1 100644 --- a/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs +++ b/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs @@ -1,12 +1,11 @@ -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). +/// +/// The type of the model to invoke on a handler. +/// +/// +public interface IPublishSubscribeChannel : IPublisher, ISubscriber where TRequest : IRequest { - /// - /// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). - /// - /// The type of the model to invoke on a handler. - /// - /// - public interface IPublishSubscribeChannel : IPublisher, ISubscriber where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Core/Messaging/IPublisher.cs b/src/Savvyio.Core/Messaging/IPublisher.cs index 3298cb86..e1a64e1b 100644 --- a/src/Savvyio.Core/Messaging/IPublisher.cs +++ b/src/Savvyio.Core/Messaging/IPublisher.cs @@ -2,20 +2,19 @@ using System.Threading.Tasks; using Cuemon.Threading; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a publisher/sender channel for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). +/// +/// The type of the model to invoke on a handler. +public interface IPublisher where TRequest : IRequest { /// - /// Defines a publisher/sender channel for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). + /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. /// - /// The type of the model to invoke on a handler. - public interface IPublisher where TRequest : IRequest - { - /// - /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The message to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task PublishAsync(IMessage message, Action setup = null); - } + /// The message to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task PublishAsync(IMessage message, Action setup = null); } diff --git a/src/Savvyio.Core/Messaging/IReceiver.cs b/src/Savvyio.Core/Messaging/IReceiver.cs index 4142ffda..b692aaea 100644 --- a/src/Savvyio.Core/Messaging/IReceiver.cs +++ b/src/Savvyio.Core/Messaging/IReceiver.cs @@ -2,19 +2,18 @@ using System.Collections.Generic; using Cuemon.Threading; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a consumer/receiver channel used by subsystems to receive a command and perform one or more actions (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +public interface IReceiver where TRequest : IRequest { /// - /// Defines a consumer/receiver channel used by subsystems to receive a command and perform one or more actions (e.g., change the state). + /// Receive one or more message(s) asynchronous using Point-to-Point Channel/P2P MEP. /// - /// The type of the model to invoke on a handler. - public interface IReceiver where TRequest : IRequest - { - /// - /// Receive one or more message(s) asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - IAsyncEnumerable> ReceiveAsync(Action setup = null); - } + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + IAsyncEnumerable> ReceiveAsync(Action setup = null); } diff --git a/src/Savvyio.Core/Messaging/ISender.cs b/src/Savvyio.Core/Messaging/ISender.cs index 0823ec24..ee0b6e8f 100644 --- a/src/Savvyio.Core/Messaging/ISender.cs +++ b/src/Savvyio.Core/Messaging/ISender.cs @@ -3,20 +3,19 @@ using System; using System.Collections.Generic; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a producer/sender channel used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +public interface ISender where TRequest : IRequest { /// - /// Defines a producer/sender channel used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). + /// Sends the specified asynchronous using Point-to-Point Channel/P2P MEP. /// - /// The type of the model to invoke on a handler. - public interface ISender where TRequest : IRequest - { - /// - /// Sends the specified asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The messages to send. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task SendAsync(IEnumerable> messages, Action setup = null); - } + /// The messages to send. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task SendAsync(IEnumerable> messages, Action setup = null); } diff --git a/src/Savvyio.Core/Messaging/ISubscriber.cs b/src/Savvyio.Core/Messaging/ISubscriber.cs index 65f9786b..b25a8823 100644 --- a/src/Savvyio.Core/Messaging/ISubscriber.cs +++ b/src/Savvyio.Core/Messaging/ISubscriber.cs @@ -2,20 +2,19 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Defines a subscriber/receiver channel used by subsystems to subscribe to messages (typically events) to be made aware of something that has happened. +/// +/// The type of the model to invoke on a handler. +public interface ISubscriber where TRequest : IRequest { /// - /// Defines a subscriber/receiver channel used by subsystems to subscribe to messages (typically events) to be made aware of something that has happened. + /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. /// - /// The type of the model to invoke on a handler. - public interface ISubscriber where TRequest : IRequest - { - /// - /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The function delegate that will handle the message. - /// The which may be configured. - /// A that represents the asynchronous operation. - Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null); - } + /// The function delegate that will handle the message. + /// The which may be configured. + /// A that represents the asynchronous operation. + Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null); } diff --git a/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs b/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs index 1e7a8900..cbd91dcd 100644 --- a/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs +++ b/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs @@ -2,38 +2,37 @@ using System.Threading; using Cuemon.Threading; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Configuration options that is related to implementations of the interface. +/// +/// +public class SubscribeAsyncOptions : AsyncOptions { /// - /// Configuration options that is related to implementations of the interface. + /// Initializes a new instance of the class. /// - /// - public class SubscribeAsyncOptions : AsyncOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// false + /// + /// + /// + public SubscribeAsyncOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// false - /// - /// - /// - public SubscribeAsyncOptions() - { - } - - /// - /// Gets or sets a value indicating whether to throw an (or derived thereof) if a was requested cancelled. - /// - /// true to throw an if a was requested cancelled; otherwise, false. - public bool ThrowIfCancellationWasRequested { get; set; } } + + /// + /// Gets or sets a value indicating whether to throw an (or derived thereof) if a was requested cancelled. + /// + /// true to throw an if a was requested cancelled; otherwise, false. + public bool ThrowIfCancellationWasRequested { get; set; } } diff --git a/src/Savvyio.Core/MetadataDictionary.cs b/src/Savvyio.Core/MetadataDictionary.cs index a362ee17..74bd13ef 100644 --- a/src/Savvyio.Core/MetadataDictionary.cs +++ b/src/Savvyio.Core/MetadataDictionary.cs @@ -4,213 +4,212 @@ using System.Linq; using Cuemon.Collections.Generic; -namespace Savvyio +namespace Savvyio; + +/// +/// Provides a default implementation of the interface. This class cannot be inherited. +/// +/// +public sealed class MetadataDictionary : IMetadataDictionary { + private readonly IDictionary _dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); + /// - /// Provides a default implementation of the interface. This class cannot be inherited. + /// Gets a list of the reserved keywords. /// - /// - public sealed class MetadataDictionary : IMetadataDictionary + /// A list of the reserved keywords. + public static IReadOnlyCollection ReservedKeywords { get; } = Arguments.ToEnumerableOf(Timestamp, MemberType, CorrelationId, RequestId, CausationId, EventId, AggregateVersion).ToList(); + + internal static string EnsureReservedKeywordCapitalization(string key) { - private readonly IDictionary _dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); + return ReservedKeywords.SingleOrDefault(rk => rk.Equals(key, StringComparison.OrdinalIgnoreCase)) ?? key; + } - /// - /// Gets a list of the reserved keywords. - /// - /// A list of the reserved keywords. - public static IReadOnlyCollection ReservedKeywords { get; } = Arguments.ToEnumerableOf(Timestamp, MemberType, CorrelationId, RequestId, CausationId, EventId, AggregateVersion).ToList(); + /// + /// Timestamp is a reserved keyword. + /// + public const string Timestamp = nameof(Timestamp); - internal static string EnsureReservedKeywordCapitalization(string key) - { - return ReservedKeywords.SingleOrDefault(rk => rk.Equals(key, StringComparison.OrdinalIgnoreCase)) ?? key; - } + /// + /// MemberType is a reserved keyword. + /// + public const string MemberType = nameof(MemberType); - /// - /// Timestamp is a reserved keyword. - /// - public const string Timestamp = nameof(Timestamp); - - /// - /// MemberType is a reserved keyword. - /// - public const string MemberType = nameof(MemberType); - - /// - /// CorrelationId is a reserved keyword. - /// - public const string CorrelationId = nameof(CorrelationId); - - /// - /// RequestId is a reserved keyword. - /// - public const string RequestId = nameof(RequestId); - - /// - /// CausationId is a reserved keyword. - /// - public const string CausationId = nameof(CausationId); - - /// - /// EventId is a reserved keyword. - /// - public const string EventId = nameof(EventId); - - /// - /// AggregateVersion is a reserved keyword. - /// - public const string AggregateVersion = nameof(AggregateVersion); - - /// - /// Initializes a new instance of the class. - /// - public MetadataDictionary() - { - } + /// + /// CorrelationId is a reserved keyword. + /// + public const string CorrelationId = nameof(CorrelationId); - /// - /// Gets or sets the element with the specified key. - /// - /// The key of the value to get or set. - /// The value associated with the specified key. - public object this[string key] - { - get => _dictionary[key]; - set - { - var parsedKey = EnsureReservedKeywordCapitalization(key); - _dictionary[parsedKey] = value; - } - } + /// + /// RequestId is a reserved keyword. + /// + public const string RequestId = nameof(RequestId); - /// - /// Gets the number of elements contained in the . - /// - /// The number of key/value pairs contained in the . - public int Count => _dictionary.Count; - - /// - /// Gets a value indicating whether the is read-only. - /// - /// true if this instance is read only; otherwise, false. - public bool IsReadOnly => _dictionary.IsReadOnly; - - /// - /// Gets an containing the keys of the . - /// - /// A containing the keys in the . - public ICollection Keys => _dictionary.Keys; - - /// - /// Gets an containing the values in the . - /// - /// A containing the values in the . - public ICollection Values => _dictionary.Values; - - /// - /// Adds an item to the . - /// - /// The object to add to the . - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } + /// + /// CausationId is a reserved keyword. + /// + public const string CausationId = nameof(CausationId); + + /// + /// EventId is a reserved keyword. + /// + public const string EventId = nameof(EventId); + + /// + /// AggregateVersion is a reserved keyword. + /// + public const string AggregateVersion = nameof(AggregateVersion); - /// - /// Adds an element with the provided key and value to the . - /// - /// The object to use as the key of the element to add. - /// The object to use as the value of the element to add. - public void Add(string key, object value) + /// + /// Initializes a new instance of the class. + /// + public MetadataDictionary() + { + } + + /// + /// Gets or sets the element with the specified key. + /// + /// The key of the value to get or set. + /// The value associated with the specified key. + public object this[string key] + { + get => _dictionary[key]; + set { var parsedKey = EnsureReservedKeywordCapitalization(key); - _dictionary.Add(parsedKey, value); + _dictionary[parsedKey] = value; } + } - /// - /// Removes all items from the . - /// - public void Clear() - { - _dictionary.Clear(); - } + /// + /// Gets the number of elements contained in the . + /// + /// The number of key/value pairs contained in the . + public int Count => _dictionary.Count; - /// - /// Copies the elements of the to an array of type , starting at the specified array index. - /// - /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. - /// The zero-based index in at which copying begins. - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - _dictionary.CopyTo(array, arrayIndex); - } + /// + /// Gets a value indicating whether the is read-only. + /// + /// true if this instance is read only; otherwise, false. + public bool IsReadOnly => _dictionary.IsReadOnly; - /// - /// Determines whether the contains a specific value. - /// - /// The object to locate in the . - /// if is found in the ; otherwise, . - public bool Contains(KeyValuePair item) - { - return _dictionary.Contains(item); - } + /// + /// Gets an containing the keys of the . + /// + /// A containing the keys in the . + public ICollection Keys => _dictionary.Keys; - /// - /// Determines whether the contains an element with the specified key. - /// - /// The key to locate in the . - /// if the contains an element with the key; otherwise, . - public bool ContainsKey(string key) - { - return _dictionary.ContainsKey(key); - } + /// + /// Gets an containing the values in the . + /// + /// A containing the values in the . + public ICollection Values => _dictionary.Values; - /// - /// Removes the first occurrence of a specific object from the . - /// - /// The object to remove from the . - /// if was successfully removed from the ; otherwise, . This method also returns if is not found in the original . - public bool Remove(KeyValuePair item) - { - return Remove(item.Key); - } + /// + /// Adds an item to the . + /// + /// The object to add to the . + public void Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } - /// - /// Removes the element with the specified key from the . - /// - /// The key of the element to remove. - /// if the element is successfully removed; otherwise, . This method also returns if was not found in the original . - public bool Remove(string key) - { - return _dictionary.Remove(key); - } + /// + /// Adds an element with the provided key and value to the . + /// + /// The object to use as the key of the element to add. + /// The object to use as the value of the element to add. + public void Add(string key, object value) + { + var parsedKey = EnsureReservedKeywordCapitalization(key); + _dictionary.Add(parsedKey, value); + } - /// - /// Gets the value associated with the specified key. - /// - /// The key whose value to get. - /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. - /// if the object that implements contains an element with the specified key; otherwise, . - public bool TryGetValue(string key, out object value) - { - return _dictionary.TryGetValue(key, out value); - } + /// + /// Removes all items from the . + /// + public void Clear() + { + _dictionary.Clear(); + } - /// - /// Returns an enumerator that iterates through the collection. - /// - /// An enumerator that can be used to iterate through the collection. - public IEnumerator> GetEnumerator() - { - return _dictionary.GetEnumerator(); - } + /// + /// Copies the elements of the to an array of type , starting at the specified array index. + /// + /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. + /// The zero-based index in at which copying begins. + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + _dictionary.CopyTo(array, arrayIndex); + } - /// - /// Returns an enumerator that iterates through a collection. - /// - /// An object that can be used to iterate through the collection. - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)_dictionary).GetEnumerator(); - } + /// + /// Determines whether the contains a specific value. + /// + /// The object to locate in the . + /// if is found in the ; otherwise, . + public bool Contains(KeyValuePair item) + { + return _dictionary.Contains(item); + } + + /// + /// Determines whether the contains an element with the specified key. + /// + /// The key to locate in the . + /// if the contains an element with the key; otherwise, . + public bool ContainsKey(string key) + { + return _dictionary.ContainsKey(key); + } + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// The object to remove from the . + /// if was successfully removed from the ; otherwise, . This method also returns if is not found in the original . + public bool Remove(KeyValuePair item) + { + return Remove(item.Key); + } + + /// + /// Removes the element with the specified key from the . + /// + /// The key of the element to remove. + /// if the element is successfully removed; otherwise, . This method also returns if was not found in the original . + public bool Remove(string key) + { + return _dictionary.Remove(key); + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key whose value to get. + /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. + /// if the object that implements contains an element with the specified key; otherwise, . + public bool TryGetValue(string key, out object value) + { + return _dictionary.TryGetValue(key, out value); + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator that can be used to iterate through the collection. + public IEnumerator> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + /// + /// Returns an enumerator that iterates through a collection. + /// + /// An object that can be used to iterate through the collection. + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_dictionary).GetEnumerator(); } } diff --git a/src/Savvyio.Core/MetadataExtensions.cs b/src/Savvyio.Core/MetadataExtensions.cs index 7ee3a80a..29f5a2e3 100644 --- a/src/Savvyio.Core/MetadataExtensions.cs +++ b/src/Savvyio.Core/MetadataExtensions.cs @@ -3,186 +3,185 @@ using Cuemon.Extensions; using Cuemon.Extensions.Reflection; -namespace Savvyio +namespace Savvyio; + +/// +/// Extension methods for the interface. +/// +public static class MetadataExtensions { /// - /// Extension methods for the interface. + /// Gets the string representation of the causation identifier from the . /// - public static class MetadataExtensions + /// The model that implements the interface. + /// The to extend. + /// The string representation of the causation identifier from the . + public static string GetCausationId(this T request) where T : IMetadata { - /// - /// Gets the string representation of the causation identifier from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the causation identifier from the . - public static string GetCausationId(this T request) where T : IMetadata - { - return MetadataFactory.Get(request, MetadataDictionary.CausationId).As(); - } + return MetadataFactory.Get(request, MetadataDictionary.CausationId).As(); + } - /// - /// Gets the string representation of the correlation identifier from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the correlation identifier from the . - public static string GetCorrelationId(this T request) where T : IMetadata - { - return MetadataFactory.Get(request, MetadataDictionary.CorrelationId).As(); - } + /// + /// Gets the string representation of the correlation identifier from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The string representation of the correlation identifier from the . + public static string GetCorrelationId(this T request) where T : IMetadata + { + return MetadataFactory.Get(request, MetadataDictionary.CorrelationId).As(); + } - /// - /// Gets the string representation of the request identifier from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the request identifier from the . - public static string GetRequestId(this T request) where T : IMetadata - { - return MetadataFactory.Get(request, MetadataDictionary.RequestId).As(); - } + /// + /// Gets the string representation of the request identifier from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The string representation of the request identifier from the . + public static string GetRequestId(this T request) where T : IMetadata + { + return MetadataFactory.Get(request, MetadataDictionary.RequestId).As(); + } - /// - /// Gets the string representation of the underlying member type of . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the member type from the . - /// The underlying of a model expressed as a string representation (fully qualified name of the type, including its namespace, comma delimited with the simple name of the assembly). - public static string GetMemberType(this T request) where T : IMetadata - { - return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); - } + /// + /// Gets the string representation of the underlying member type of . + /// + /// The model that implements the interface. + /// The to extend. + /// The string representation of the member type from the . + /// The underlying of a model expressed as a string representation (fully qualified name of the type, including its namespace, comma delimited with the simple name of the assembly). + public static string GetMemberType(this T request) where T : IMetadata + { + return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); + } - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The causation identifier of the model. - /// A reference to after the operation has completed. - public static T SetCausationId(this T request, string causationId) where T : IMetadata - { - MetadataFactory.Set(request, MetadataDictionary.CausationId, causationId); - return request; - } + /// + /// Assigns a new to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The causation identifier of the model. + /// A reference to after the operation has completed. + public static T SetCausationId(this T request, string causationId) where T : IMetadata + { + MetadataFactory.Set(request, MetadataDictionary.CausationId, causationId); + return request; + } - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The correlation identifier of the model. - /// A reference to after the operation has completed. - public static T SetCorrelationId(this T request, string correlationId) where T : IMetadata - { - MetadataFactory.Set(request, MetadataDictionary.CorrelationId, correlationId); - return request; - } + /// + /// Assigns a new to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The correlation identifier of the model. + /// A reference to after the operation has completed. + public static T SetCorrelationId(this T request, string correlationId) where T : IMetadata + { + MetadataFactory.Set(request, MetadataDictionary.CorrelationId, correlationId); + return request; + } - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The request identifier of the model. - /// A reference to after the operation has completed. - public static T SetRequestId(this T request, string requestId) where T : IMetadata - { - MetadataFactory.Set(request, MetadataDictionary.RequestId, requestId); - return request; - } + /// + /// Assigns a new to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The request identifier of the model. + /// A reference to after the operation has completed. + public static T SetRequestId(this T request, string requestId) where T : IMetadata + { + MetadataFactory.Set(request, MetadataDictionary.RequestId, requestId); + return request; + } - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The event identifier of the model. - /// A reference to after the operation has completed. - public static T SetEventId(this T request, string eventId) where T : IMetadata - { - MetadataFactory.Set(request, MetadataDictionary.EventId, eventId); - return request; - } + /// + /// Assigns a new to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The event identifier of the model. + /// A reference to after the operation has completed. + public static T SetEventId(this T request, string eventId) where T : IMetadata + { + MetadataFactory.Set(request, MetadataDictionary.EventId, eventId); + return request; + } - /// - /// Assigns a new timestamp ( value) to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The optional value expressed as the Coordinated Universal Time (UTC). - /// A reference to after the operation has completed. - /// - /// (when set) was not expressed as the Coordinated Universal Time (UTC). - /// - public static T SetTimestamp(this T request, DateTime? utcTimestamp = null) where T : IMetadata - { - Validator.ThrowIfTrue(utcTimestamp.HasValue && utcTimestamp.Value.Kind != DateTimeKind.Utc, nameof(utcTimestamp), "Value must be expressed as the Coordinated Universal Time (UTC)."); - MetadataFactory.Set(request, MetadataDictionary.Timestamp, utcTimestamp ?? DateTime.UtcNow); - return request; - } + /// + /// Assigns a new timestamp ( value) to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The optional value expressed as the Coordinated Universal Time (UTC). + /// A reference to after the operation has completed. + /// + /// (when set) was not expressed as the Coordinated Universal Time (UTC). + /// + public static T SetTimestamp(this T request, DateTime? utcTimestamp = null) where T : IMetadata + { + Validator.ThrowIfTrue(utcTimestamp.HasValue && utcTimestamp.Value.Kind != DateTimeKind.Utc, nameof(utcTimestamp), "Value must be expressed as the Coordinated Universal Time (UTC)."); + MetadataFactory.Set(request, MetadataDictionary.Timestamp, utcTimestamp ?? DateTime.UtcNow); + return request; + } - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The type of the model. - /// A reference to after the operation has completed. - /// The is converted to its equivalent string representation (fully qualified name of the type, including its namespace, comma delimited with the simple name of the assembly). - public static T SetMemberType(this T request, Type type) where T : IMetadata - { - MetadataFactory.Set(request, MetadataDictionary.MemberType, type.ToFullNameIncludingAssemblyName()); - return request; - } + /// + /// Assigns a new to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The type of the model. + /// A reference to after the operation has completed. + /// The is converted to its equivalent string representation (fully qualified name of the type, including its namespace, comma delimited with the simple name of the assembly). + public static T SetMemberType(this T request, Type type) where T : IMetadata + { + MetadataFactory.Set(request, MetadataDictionary.MemberType, type.ToFullNameIncludingAssemblyName()); + return request; + } - /// - /// Add or update a set of model to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The key of the element to add or update. - /// The value of the element to add or update. - /// A reference to after the operation has completed. - /// - /// cannot be null -or- - /// cannot be null. - /// - public static T SaveMetadata(this T request, string key, object value) where T : IMetadata - { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(key); + /// + /// Add or update a set of model to the . + /// + /// The model that implements the interface. + /// The to extend. + /// The key of the element to add or update. + /// The value of the element to add or update. + /// A reference to after the operation has completed. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static T SaveMetadata(this T request, string key, object value) where T : IMetadata + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(key); - var parsedKey = MetadataDictionary.EnsureReservedKeywordCapitalization(key); - MetadataFactory.Set(request, parsedKey, value); - return request; - } + var parsedKey = MetadataDictionary.EnsureReservedKeywordCapitalization(key); + MetadataFactory.Set(request, parsedKey, value); + return request; + } - /// - /// Copies model from the to the if not already existing. - /// - /// The giving type of the model that implements the interface. - /// The receiving type of the model that implements the interface. - /// The to extend. Receives model from . - /// The model that will give metadata to . - /// A reference to after the operation has completed. - public static TDestination MergeMetadata(this TDestination destination, TSource source) - where TSource : IMetadata - where TDestination : IMetadata + /// + /// Copies model from the to the if not already existing. + /// + /// The giving type of the model that implements the interface. + /// The receiving type of the model that implements the interface. + /// The to extend. Receives model from . + /// The model that will give metadata to . + /// A reference to after the operation has completed. + public static TDestination MergeMetadata(this TDestination destination, TSource source) + where TSource : IMetadata + where TDestination : IMetadata + { + if (destination != null && source != null) { - if (destination != null && source != null) + foreach (var entry in source.Metadata) { - foreach (var entry in source.Metadata) + if (!destination.Metadata.ContainsKey(entry.Key)) { - if (!destination.Metadata.ContainsKey(entry.Key)) - { - destination.Metadata.Add(entry.Key, entry.Value); - } + destination.Metadata.Add(entry.Key, entry.Value); } } - return destination; } + return destination; } } diff --git a/src/Savvyio.Core/MetadataFactory.cs b/src/Savvyio.Core/MetadataFactory.cs index 23f6ccda..e004b1ec 100644 --- a/src/Savvyio.Core/MetadataFactory.cs +++ b/src/Savvyio.Core/MetadataFactory.cs @@ -1,55 +1,54 @@ using System; using Cuemon; -namespace Savvyio +namespace Savvyio; + +/// +/// Provides access to factory methods for maintaining metadata in models. +/// +public static class MetadataFactory { /// - /// Provides access to factory methods for maintaining metadata in models. + /// Gets the value associates to the from the item with the specified . /// - public static class MetadataFactory + /// The model that implements the interface. + /// The to extend. + /// The key of the element to retrieve. + /// A reference to the value in the that is identified by , if the entry exists; otherwise, null. + public static object Get(T request, string key) where T : IMetadata { - /// - /// Gets the value associates to the from the item with the specified . - /// - /// The model that implements the interface. - /// The to extend. - /// The key of the element to retrieve. - /// A reference to the value in the that is identified by , if the entry exists; otherwise, null. - public static object Get(T request, string key) where T : IMetadata + if (request.Metadata.TryGetValue(key, out var result)) { - if (request.Metadata.TryGetValue(key, out var result)) - { - return result; - } - return null; + return result; } + return null; + } - /// - /// Assigns a new to the on the item with the specified . - /// - /// The model that implements the interface. - /// The to extend. - /// The key of the element to retrieve. - /// The value of the element to change. - /// A reference to after the operation has completed. - /// - /// cannot be null -or- - /// cannot be null. - /// - public static T Set(T request, string key, object value) where T : IMetadata - { - Validator.ThrowIfNull(request); - Validator.ThrowIfNull(key); + /// + /// Assigns a new to the on the item with the specified . + /// + /// The model that implements the interface. + /// The to extend. + /// The key of the element to retrieve. + /// The value of the element to change. + /// A reference to after the operation has completed. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static T Set(T request, string key, object value) where T : IMetadata + { + Validator.ThrowIfNull(request); + Validator.ThrowIfNull(key); - if (request.Metadata.ContainsKey(key)) - { - request.Metadata[key] = value; - } - else - { - request.Metadata.Add(key, value); - } - return request; + if (request.Metadata.ContainsKey(key)) + { + request.Metadata[key] = value; + } + else + { + request.Metadata.Add(key, value); } + return request; } } diff --git a/src/Savvyio.Core/Queries/IQuery.cs b/src/Savvyio.Core/Queries/IQuery.cs index 7821c952..e9a0d71a 100644 --- a/src/Savvyio.Core/Queries/IQuery.cs +++ b/src/Savvyio.Core/Queries/IQuery.cs @@ -1,17 +1,16 @@ -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// A marker interface that specifies something that returns data. +/// +public interface IQuery : IRequest, IMetadata { - /// - /// A marker interface that specifies something that returns data. - /// - public interface IQuery : IRequest, IMetadata - { - } +} - /// - /// A marker interface that specifies something that returns data. - /// - /// The type of the result to return. - public interface IQuery : IQuery - { - } +/// +/// A marker interface that specifies something that returns data. +/// +/// The type of the result to return. +public interface IQuery : IQuery +{ } diff --git a/src/Savvyio.Core/Queries/IQueryDispatcher.cs b/src/Savvyio.Core/Queries/IQueryDispatcher.cs index 10c8f097..6eefaa0f 100644 --- a/src/Savvyio.Core/Queries/IQueryDispatcher.cs +++ b/src/Savvyio.Core/Queries/IQueryDispatcher.cs @@ -3,29 +3,28 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Defines a Query dispatcher that uses Request-Reply/In-Out MEP. +/// +/// +public interface IQueryDispatcher : IDispatcher { /// - /// Defines a Query dispatcher that uses Request-Reply/In-Out MEP. + /// Queries the specified using Request-Reply/In-Out MEP. /// - /// - public interface IQueryDispatcher : IDispatcher - { - /// - /// Queries the specified using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// The outcome of the query operation. - TResult Query(IQuery request); + /// The type of the result to return. + /// The to request. + /// The outcome of the query operation. + TResult Query(IQuery request); - /// - /// Queries the specified asynchronous using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. - Task QueryAsync(IQuery request, Action setup = null); - } + /// + /// Queries the specified asynchronous using Request-Reply/In-Out MEP. + /// + /// The type of the result to return. + /// The to request. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. + Task QueryAsync(IQuery request, Action setup = null); } diff --git a/src/Savvyio.Core/Queries/IQueryHandler.cs b/src/Savvyio.Core/Queries/IQueryHandler.cs index 4cf5f121..797e0531 100644 --- a/src/Savvyio.Core/Queries/IQueryHandler.cs +++ b/src/Savvyio.Core/Queries/IQueryHandler.cs @@ -1,12 +1,11 @@ using Savvyio.Handlers; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Specifies a handler responsible for objects that implements the interface. +/// +/// +public interface IQueryHandler : IRequestReplyHandler { - /// - /// Specifies a handler responsible for objects that implements the interface. - /// - /// - public interface IQueryHandler : IRequestReplyHandler - { - } } diff --git a/src/Savvyio.Core/Reflection/AssemblyContext.cs b/src/Savvyio.Core/Reflection/AssemblyContext.cs index 4c898375..98a153fb 100644 --- a/src/Savvyio.Core/Reflection/AssemblyContext.cs +++ b/src/Savvyio.Core/Reflection/AssemblyContext.cs @@ -1,10 +1,10 @@ -using Cuemon.Extensions.Collections.Generic; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Cuemon; namespace Savvyio.Reflection { /// /// Provides a set of static methods and properties to manage and filter assemblies in the current application domain. /// public static class AssemblyContext { private static readonly Lazy> AssemblyLoadFactory = new(() => AppDomain .CurrentDomain .GetAssemblies() .Where(AssemblyFilterCallback) .SelectMany(AssemblyDependenciesCallback) .Distinct() .Except(typeof(AssemblyContext).Assembly.Yield()) .ToList() .AsReadOnly()); private static Func _assemblyFilterCallback = DefaultAssemblyFilter; private static Func> _assemblyDependenciesCallback = DefaultAssemblyDependencies; private static Func _assemblyDependenciesFilterCallback = DefaultAssemblyDependenciesFilter; /// /// Gets or sets the function delegate that filters assemblies from the current application domain. /// /// The function delegate that filters assemblies from the current application domain. /// The default implementation filters away assemblies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyFilterCallback { get => _assemblyFilterCallback; set => _assemblyFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// The function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// cannot be null. /// public static Func> AssemblyDependenciesCallback { get => _assemblyDependenciesCallback; set => _assemblyDependenciesCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that filters assembly dependencies from the current application domain. /// /// The function delegate that filters assembly dependencies from the current application domain. /// The default implementation filters away assembly dependencies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyDependenciesFilterCallback { get => _assemblyDependenciesFilterCallback; set => _assemblyDependenciesFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets the qualified assemblies from the current application domain. /// /// The qualified assemblies from the current application domain. /// This result of this property is coupled with and . public static IReadOnlyList CurrentDomainAssemblies => AssemblyLoadFactory.Value; private static bool DefaultAssemblyFilter(Assembly assembly) { return assembly.FullName != null && - !assembly.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && - !assembly.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); - } +using Cuemon.Extensions.Collections.Generic; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Cuemon; namespace Savvyio.Reflection; /// /// Provides a set of static methods and properties to manage and filter assemblies in the current application domain. /// public static class AssemblyContext { private static readonly Lazy> AssemblyLoadFactory = new(() => AppDomain .CurrentDomain .GetAssemblies() .Where(AssemblyFilterCallback) .SelectMany(AssemblyDependenciesCallback) .Distinct() .Except(typeof(AssemblyContext).Assembly.Yield()) .ToList() .AsReadOnly()); private static Func _assemblyFilterCallback = DefaultAssemblyFilter; private static Func> _assemblyDependenciesCallback = DefaultAssemblyDependencies; private static Func _assemblyDependenciesFilterCallback = DefaultAssemblyDependenciesFilter; /// /// Gets or sets the function delegate that filters assemblies from the current application domain. /// /// The function delegate that filters assemblies from the current application domain. /// The default implementation filters away assemblies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyFilterCallback { get => _assemblyFilterCallback; set => _assemblyFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// The function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// cannot be null. /// public static Func> AssemblyDependenciesCallback { get => _assemblyDependenciesCallback; set => _assemblyDependenciesCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that filters assembly dependencies from the current application domain. /// /// The function delegate that filters assembly dependencies from the current application domain. /// The default implementation filters away assembly dependencies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyDependenciesFilterCallback { get => _assemblyDependenciesFilterCallback; set => _assemblyDependenciesFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets the qualified assemblies from the current application domain. /// /// The qualified assemblies from the current application domain. /// This result of this property is coupled with and . public static IReadOnlyList CurrentDomainAssemblies => AssemblyLoadFactory.Value; private static bool DefaultAssemblyFilter(Assembly assembly) { return assembly.FullName != null && + !assembly.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && + !assembly.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); + } - private static bool DefaultAssemblyDependenciesFilter(AssemblyName assemblyName) - { - return !assemblyName.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && - !assemblyName.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); - } private static IEnumerable DefaultAssemblyDependencies(Assembly assembly) { var stack = new Stack(); var guard = new HashSet(); yield return assembly; stack.Push(assembly); guard.Add(assembly.FullName); while (stack.TryPop(out var assemblyToTraverse)) { foreach (var assemblyName in assemblyToTraverse.GetReferencedAssemblies().Where(AssemblyDependenciesFilterCallback)) { if (!guard.Add(assemblyName.FullName)) { continue; } if (Patterns.TryInvoke(() => Assembly.Load(assemblyName), out var referencedAssembly) && referencedAssembly != null) { stack.Push(referencedAssembly); yield return referencedAssembly; } } } } } } \ No newline at end of file + private static bool DefaultAssemblyDependenciesFilter(AssemblyName assemblyName) + { + return !assemblyName.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && + !assemblyName.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); + } private static IEnumerable DefaultAssemblyDependencies(Assembly assembly) { var stack = new Stack(); var guard = new HashSet(); yield return assembly; stack.Push(assembly); guard.Add(assembly.FullName); while (stack.TryPop(out var assemblyToTraverse)) { foreach (var assemblyName in assemblyToTraverse.GetReferencedAssemblies().Where(AssemblyDependenciesFilterCallback)) { if (!guard.Add(assemblyName.FullName)) { continue; } if (Patterns.TryInvoke(() => Assembly.Load(assemblyName), out var referencedAssembly) && referencedAssembly != null) { stack.Push(referencedAssembly); yield return referencedAssembly; } } } } } \ No newline at end of file diff --git a/src/Savvyio.Core/Request.cs b/src/Savvyio.Core/Request.cs index 05e11227..96ccf041 100644 --- a/src/Savvyio.Core/Request.cs +++ b/src/Savvyio.Core/Request.cs @@ -1,24 +1,23 @@ -namespace Savvyio +namespace Savvyio; + +/// +/// Represents the base class from which all implementations of should derive. +/// +/// +/// +public abstract record Request : IRequest, IMetadata { /// - /// Represents the base class from which all implementations of should derive. + /// Initializes a new instance of the class. /// - /// - /// - public abstract record Request : IRequest, IMetadata + protected Request() { - /// - /// Initializes a new instance of the class. - /// - protected Request() - { - this.SetMemberType(GetType()); - } - - /// - /// Gets the associated metadata of this model. - /// - /// The associated metadata of this model. - public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); + this.SetMemberType(GetType()); } + + /// + /// Gets the associated metadata of this model. + /// + /// The associated metadata of this model. + public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); } diff --git a/src/Savvyio.Core/SavvyioOptions.cs b/src/Savvyio.Core/SavvyioOptions.cs index 35341383..1505677d 100644 --- a/src/Savvyio.Core/SavvyioOptions.cs +++ b/src/Savvyio.Core/SavvyioOptions.cs @@ -5,199 +5,198 @@ using Cuemon.Extensions.Collections.Generic; using Savvyio.Dispatchers; -namespace Savvyio +namespace Savvyio; + +/// +/// Specifies options that is related to setting up Savvy I/O services. +/// +public class SavvyioOptions : IParameterObject { + private readonly List _handlerServiceTypes = new(); // the handler service types to tie one or more handler implementation types + private readonly List _handlerImplementationTypes = new(); // the handler implementation types to tie one or more handler service types + + private readonly List _dispatcherServiceTypes = new(); // the dispatchers service types to tie one or more dispatcher implementation types + private readonly List _dispatcherImplementationTypes = new(); // the dispatcher implementation types to tie one or more dispatchers service types + /// - /// Specifies options that is related to setting up Savvy I/O services. + /// Determines if a given pair of types are a valid as a dependency. /// - public class SavvyioOptions : IParameterObject + /// The type of the service to validate. + /// The provider type. + /// The contract type. + /// true if the specified provider is a valid dependency; otherwise, false. + /// Dependency formula: provider.HasInterfaces(contract) && provider.IsClass && !provider.IsAbstract && !provider.IsInterface + public static bool IsValid(Type provider, Type contract) { - private readonly List _handlerServiceTypes = new(); // the handler service types to tie one or more handler implementation types - private readonly List _handlerImplementationTypes = new(); // the handler implementation types to tie one or more handler service types - - private readonly List _dispatcherServiceTypes = new(); // the dispatchers service types to tie one or more dispatcher implementation types - private readonly List _dispatcherImplementationTypes = new(); // the dispatcher implementation types to tie one or more dispatchers service types - - /// - /// Determines if a given pair of types are a valid as a dependency. - /// - /// The type of the service to validate. - /// The provider type. - /// The contract type. - /// true if the specified provider is a valid dependency; otherwise, false. - /// Dependency formula: provider.HasInterfaces(contract) && provider.IsClass && !provider.IsAbstract && !provider.IsInterface - public static bool IsValid(Type provider, Type contract) + if (provider.HasInterfaces(typeof(T))) { - if (provider.HasInterfaces(typeof(T))) - { - return provider.HasInterfaces(contract) && provider.IsClass && !provider.IsAbstract && !provider.IsInterface; - } - return false; + return provider.HasInterfaces(contract) && provider.IsClass && !provider.IsAbstract && !provider.IsInterface; } + return false; + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// false - /// - /// - /// - /// false - /// - /// - /// - /// false - /// - /// - /// - public SavvyioOptions() - { - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// false + /// + /// + /// + /// false + /// + /// + /// + /// false + /// + /// + /// + public SavvyioOptions() + { + } - /// - /// Gets a value indicating whether discovery of implementations using assembly scanning is enabled. - /// - /// true discovery of implementations using assembly scanning is enabled; otherwise, false. - public bool AllowHandlerDiscovery { get; private set; } - - /// - /// Gets a value indicating whether discovery of implementations using assembly scanning is enabled. - /// - /// true discovery of implementations using assembly scanning is enabled; otherwise, false. - public bool AllowDispatcherDiscovery { get; private set; } - - /// - /// Gets a value indicating whether the is enabled. - /// - /// true if the is enabled; otherwise, false. - public bool IncludeHandlerServicesDescriptor { get; private set; } - - /// - /// Enables discovery of handlers implementing the interface using assembly scanning. - /// - /// true if handlers implementing the interface are allowed to be discovered using assembly scanning; otherwise, false. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions EnableHandlerDiscovery(bool allowHandlerDiscovery = true) - { - AllowHandlerDiscovery = allowHandlerDiscovery; - return this; - } + /// + /// Gets a value indicating whether discovery of implementations using assembly scanning is enabled. + /// + /// true discovery of implementations using assembly scanning is enabled; otherwise, false. + public bool AllowHandlerDiscovery { get; private set; } - /// - /// Enables discovery of dispatchers implementing the interface using assembly scanning. - /// - /// true if dispatchers implementing the interface are allowed to be discovered using assembly scanning; otherwise, false. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions EnableDispatcherDiscovery(bool allowDispatcherDiscovery = true) - { - AllowDispatcherDiscovery = allowDispatcherDiscovery; - return this; - } + /// + /// Gets a value indicating whether discovery of implementations using assembly scanning is enabled. + /// + /// true discovery of implementations using assembly scanning is enabled; otherwise, false. + public bool AllowDispatcherDiscovery { get; private set; } - /// - /// Enables the inclusion of the that provides an overview of all handlers presented in a detailed and developer friendly way. - /// - /// true enables the inclusion of an implemenation that provides an overview of all handlers presented in a detailed and developer friendly way; otherwise, false. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions EnableHandlerServicesDescriptor(bool includeHandlerServicesDescriptor = true) - { - IncludeHandlerServicesDescriptor = includeHandlerServicesDescriptor; - return this; - } + /// + /// Gets a value indicating whether the is enabled. + /// + /// true if the is enabled; otherwise, false. + public bool IncludeHandlerServicesDescriptor { get; private set; } - /// - /// Adds a dispatcher of type to (if not already registered) and (if not already registered). - /// - /// The type of the interface to add. - /// The type of the implementation to use. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions AddDispatcher() - where TDispatcher : IDispatcher - where TImplementation : class, TDispatcher - { - AddDispatcher(typeof(TDispatcher), typeof(TImplementation)); - return this; - } + /// + /// Enables discovery of handlers implementing the interface using assembly scanning. + /// + /// true if handlers implementing the interface are allowed to be discovered using assembly scanning; otherwise, false. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions EnableHandlerDiscovery(bool allowHandlerDiscovery = true) + { + AllowHandlerDiscovery = allowHandlerDiscovery; + return this; + } - /// - /// Adds a dispatcher of type to (if not already registered) and (if not already registered). - /// - /// The of the interface to add. - /// The type of the implementation to use. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions AddDispatcher(Type service, Type implementation) - { - if (IsValid(implementation, service)) - { - _dispatcherServiceTypes.TryAdd(service); - _dispatcherImplementationTypes.TryAdd(implementation); - } - return this; - } + /// + /// Enables discovery of dispatchers implementing the interface using assembly scanning. + /// + /// true if dispatchers implementing the interface are allowed to be discovered using assembly scanning; otherwise, false. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions EnableDispatcherDiscovery(bool allowDispatcherDiscovery = true) + { + AllowDispatcherDiscovery = allowDispatcherDiscovery; + return this; + } - /// - /// Adds a handler of type to (if not already registered) and (if not already registered). - /// - /// The type of the service to add. - /// The type of the model to handle. - /// The type of the implementation to use. - /// A reference to this instance so that additional configuration calls can be chained. - /// Type is only added if the following conditions are true: typeof(THandler).HasInterfaces(typeof(IHandler<TRequest>)) && typeof(T).IsClass && !typeof(T).IsAbstract && !typeof(T).IsInterface - public SavvyioOptions AddHandler() - where THandler : IHandler - where TRequest : IRequest - where TImplementation : class, THandler + /// + /// Enables the inclusion of the that provides an overview of all handlers presented in a detailed and developer friendly way. + /// + /// true enables the inclusion of an implemenation that provides an overview of all handlers presented in a detailed and developer friendly way; otherwise, false. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions EnableHandlerServicesDescriptor(bool includeHandlerServicesDescriptor = true) + { + IncludeHandlerServicesDescriptor = includeHandlerServicesDescriptor; + return this; + } + + /// + /// Adds a dispatcher of type to (if not already registered) and (if not already registered). + /// + /// The type of the interface to add. + /// The type of the implementation to use. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions AddDispatcher() + where TDispatcher : IDispatcher + where TImplementation : class, TDispatcher + { + AddDispatcher(typeof(TDispatcher), typeof(TImplementation)); + return this; + } + + /// + /// Adds a dispatcher of type to (if not already registered) and (if not already registered). + /// + /// The of the interface to add. + /// The type of the implementation to use. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions AddDispatcher(Type service, Type implementation) + { + if (IsValid(implementation, service)) { - return AddHandler(typeof(THandler), typeof(TImplementation)); + _dispatcherServiceTypes.TryAdd(service); + _dispatcherImplementationTypes.TryAdd(implementation); } + return this; + } + + /// + /// Adds a handler of type to (if not already registered) and (if not already registered). + /// + /// The type of the service to add. + /// The type of the model to handle. + /// The type of the implementation to use. + /// A reference to this instance so that additional configuration calls can be chained. + /// Type is only added if the following conditions are true: typeof(THandler).HasInterfaces(typeof(IHandler<TRequest>)) && typeof(T).IsClass && !typeof(T).IsAbstract && !typeof(T).IsInterface + public SavvyioOptions AddHandler() + where THandler : IHandler + where TRequest : IRequest + where TImplementation : class, THandler + { + return AddHandler(typeof(THandler), typeof(TImplementation)); + } - /// - /// Adds a dispatcher of type to (if not already registered) and (if not already registered). - /// - /// The of the interface to add. - /// The type of the implementation to use. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioOptions AddHandler(Type service, Type implementation) + /// + /// Adds a dispatcher of type to (if not already registered) and (if not already registered). + /// + /// The of the interface to add. + /// The type of the implementation to use. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioOptions AddHandler(Type service, Type implementation) + { + if (IsValid(implementation, service)) { - if (IsValid(implementation, service)) - { - _handlerServiceTypes.TryAdd(service); - _handlerImplementationTypes.TryAdd(implementation); - } - return this; + _handlerServiceTypes.TryAdd(service); + _handlerImplementationTypes.TryAdd(implementation); } - - /// - /// Gets the types associated with an service. - /// - /// The types associated with an service. - public IReadOnlyCollection HandlerServiceTypes => _handlerServiceTypes; - - /// - /// Gets the types implementing an service. - /// - /// The types implementing an service. - public IReadOnlyCollection HandlerImplementationTypes => _handlerImplementationTypes; - - /// - /// Gets the types associated with an service. - /// - /// The types dispatcher with an service. - public IReadOnlyCollection DispatcherServiceTypes => _dispatcherServiceTypes; - - /// - /// Gets the types implementing an service. - /// - /// The types implementing an service. - public IReadOnlyCollection DispatcherImplementationTypes => _dispatcherImplementationTypes; + return this; } + + /// + /// Gets the types associated with an service. + /// + /// The types associated with an service. + public IReadOnlyCollection HandlerServiceTypes => _handlerServiceTypes; + + /// + /// Gets the types implementing an service. + /// + /// The types implementing an service. + public IReadOnlyCollection HandlerImplementationTypes => _handlerImplementationTypes; + + /// + /// Gets the types associated with an service. + /// + /// The types dispatcher with an service. + public IReadOnlyCollection DispatcherServiceTypes => _dispatcherServiceTypes; + + /// + /// Gets the types implementing an service. + /// + /// The types implementing an service. + public IReadOnlyCollection DispatcherImplementationTypes => _dispatcherImplementationTypes; } diff --git a/src/Savvyio.Core/SavvyioOptionsExtensions.cs b/src/Savvyio.Core/SavvyioOptionsExtensions.cs index 2e47a3e3..3ce3b2c8 100644 --- a/src/Savvyio.Core/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Core/SavvyioOptionsExtensions.cs @@ -6,71 +6,70 @@ using Cuemon.Extensions; using Savvyio.Dispatchers; -namespace Savvyio +namespace Savvyio; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds handlers of type from the specified to the extended . /// - public static class SavvyioOptionsExtensions + /// The to extend. + /// The assemblies to scan for implementations. + /// A reference to so that additional configuration calls can be chained. + /// + /// cannot be null. + /// + public static SavvyioOptions AddDispatchers(this SavvyioOptions options, params Assembly[] assemblies) { - /// - /// Adds handlers of type from the specified to the extended . - /// - /// The to extend. - /// The assemblies to scan for implementations. - /// A reference to so that additional configuration calls can be chained. - /// - /// cannot be null. - /// - public static SavvyioOptions AddDispatchers(this SavvyioOptions options, params Assembly[] assemblies) - { - return AddDependenciesCore(options, (service, implementation) => options.AddDispatcher(service, implementation), assemblies); - } + return AddDependenciesCore(options, (service, implementation) => options.AddDispatcher(service, implementation), assemblies); + } - /// - /// Adds handlers of type from the specified to the extended . - /// - /// The to extend. - /// The assemblies to scan for implementations. - /// A reference to so that additional configuration calls can be chained. - /// - /// cannot be null. - /// - public static SavvyioOptions AddHandlers(this SavvyioOptions options, params Assembly[] assemblies) - { - return AddDependenciesCore(options, (service, implementation) => options.AddHandler(service, implementation), assemblies); - } + /// + /// Adds handlers of type from the specified to the extended . + /// + /// The to extend. + /// The assemblies to scan for implementations. + /// A reference to so that additional configuration calls can be chained. + /// + /// cannot be null. + /// + public static SavvyioOptions AddHandlers(this SavvyioOptions options, params Assembly[] assemblies) + { + return AddDependenciesCore(options, (service, implementation) => options.AddHandler(service, implementation), assemblies); + } - private static SavvyioOptions AddDependenciesCore(SavvyioOptions options, Action servicesManager, IEnumerable assemblies) - { - Validator.ThrowIfNull(assemblies); + private static SavvyioOptions AddDependenciesCore(SavvyioOptions options, Action servicesManager, IEnumerable assemblies) + { + Validator.ThrowIfNull(assemblies); - var self = typeof(SavvyioOptions).Assembly; - var definedTypes = new List(); - var filteredTypes = self.DefinedTypes.Where(type => type.HasInterfaces(typeof(T)) && !type.Namespace!.ContainsAny(nameof(Commands), nameof(Domain), nameof(EventDriven), nameof(Queries))).ToList(); + var self = typeof(SavvyioOptions).Assembly; + var definedTypes = new List(); + var filteredTypes = self.DefinedTypes.Where(type => type.HasInterfaces(typeof(T)) && !type.Namespace!.ContainsAny(nameof(Commands), nameof(Domain), nameof(EventDriven), nameof(Queries))).ToList(); - foreach (var assembly in assemblies.Append(self)) + foreach (var assembly in assemblies.Append(self)) + { + try { - try - { - definedTypes.AddRange(assembly.DefinedTypes.Where(type => type.HasInterfaces(typeof(T))).Except(filteredTypes)); - } - catch (ReflectionTypeLoadException) - { - // by design; ignore potential orphaned dll references causing ReflectionTypeLoadException - } + definedTypes.AddRange(assembly.DefinedTypes.Where(type => type.HasInterfaces(typeof(T))).Except(filteredTypes)); } + catch (ReflectionTypeLoadException) + { + // by design; ignore potential orphaned dll references causing ReflectionTypeLoadException + } + } - foreach (var contract in definedTypes.Where(type => type.IsInterface).OrderBy(ti => ti.FullName)) + foreach (var contract in definedTypes.Where(type => type.IsInterface).OrderBy(ti => ti.FullName)) + { + var filtered = definedTypes.Where(type => SavvyioOptions.IsValid(type, contract)).ToList(); + if (filtered.Count == 0) { continue; } + foreach (var filteredType in filtered) { - var filtered = definedTypes.Where(type => SavvyioOptions.IsValid(type, contract)).ToList(); - if (filtered.Count == 0) { continue; } - foreach (var filteredType in filtered) - { - servicesManager(contract, filteredType); - } + servicesManager(contract, filteredType); } - return options; } + return options; } } diff --git a/src/Savvyio.Core/TaskExtensions.cs b/src/Savvyio.Core/TaskExtensions.cs index f14b7e0d..425448ed 100644 --- a/src/Savvyio.Core/TaskExtensions.cs +++ b/src/Savvyio.Core/TaskExtensions.cs @@ -2,23 +2,22 @@ using System.Linq; using System.Threading.Tasks; -namespace Savvyio +namespace Savvyio; + +/// +/// Extension methods for the class. +/// +public static class TaskExtensions { /// - /// Extension methods for the class. + /// Asynchronously returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence. /// - public static class TaskExtensions + /// The type of the elements of . + /// The to return the single element of. + /// A task that represents the asynchronous operation. The task result contains the single element of the input sequence, or default (TSource) if the sequence contains no elements. + public static async Task SingleOrDefaultAsync(this Task> source) { - /// - /// Asynchronously returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence. - /// - /// The type of the elements of . - /// The to return the single element of. - /// A task that represents the asynchronous operation. The task result contains the single element of the input sequence, or default (TSource) if the sequence contains no elements. - public static async Task SingleOrDefaultAsync(this Task> source) - { - var presult = await source.ConfigureAwait(false); - return presult.SingleOrDefault(); - } + var presult = await source.ConfigureAwait(false); + return presult.SingleOrDefault(); } } diff --git a/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs b/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs index 4475f1e8..fd273c10 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs @@ -1,93 +1,92 @@ using System.Collections.Generic; using Savvyio.Handlers; -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Provides a way to cover the pattern of an Aggregate as specified in Domain Driven Design that is optimized for Event Sourcing. This is an abstract class. +/// +/// The type of the key that uniquely identifies this aggregate. +/// +/// +public abstract class TracedAggregateRoot : Aggregate, ITracedAggregateRoot { + private IFireForgetActivator _handlers; + /// - /// Provides a way to cover the pattern of an Aggregate as specified in Domain Driven Design that is optimized for Event Sourcing. This is an abstract class. + /// Initializes a new instance of the class. /// - /// The type of the key that uniquely identifies this aggregate. - /// - /// - public abstract class TracedAggregateRoot : Aggregate, ITracedAggregateRoot + /// The optional metadata to merge with this instance. + protected TracedAggregateRoot(IMetadata metadata = null) : base(metadata) { - private IFireForgetActivator _handlers; - - /// - /// Initializes a new instance of the class. - /// - /// The optional metadata to merge with this instance. - protected TracedAggregateRoot(IMetadata metadata = null) : base(metadata) - { - Initialize(); - } + Initialize(); + } - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the entity. - /// The events to rehydrate from. - protected TracedAggregateRoot(TKey id, IEnumerable events) : base(id) - { - Initialize(); - ReplayEvents(events); - } + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the entity. + /// The events to rehydrate from. + protected TracedAggregateRoot(TKey id, IEnumerable events) : base(id) + { + Initialize(); + ReplayEvents(events); + } - private void Initialize() - { - _handlers = HandlerFactory.CreateFireForget(RegisterDelegates); - } + private void Initialize() + { + _handlers = HandlerFactory.CreateFireForget(RegisterDelegates); + } - /// - /// Registers the delegates responsible for handling types that implements the interface. - /// - /// The registry that store the delegates of type . - protected abstract void RegisterDelegates(IFireForgetRegistry handler); + /// + /// Registers the delegates responsible for handling types that implements the interface. + /// + /// The registry that store the delegates of type . + protected abstract void RegisterDelegates(IFireForgetRegistry handler); - /// - /// Gets the version of the Aggregate. - /// - /// The version of the Aggregate. - public long Version { get; private set; } + /// + /// Gets the version of the Aggregate. + /// + /// The version of the Aggregate. + public long Version { get; private set; } - private void ReplayEvents(IEnumerable events) + private void ReplayEvents(IEnumerable events) + { + if (events == null) { return; } + foreach (var e in events) { - if (events == null) { return; } - foreach (var e in events) - { - Version = e.GetAggregateVersion(); - ApplyChange(e, false); - } + Version = e.GetAggregateVersion(); + ApplyChange(e, false); } + } - /// - /// Adds an event to the Aggregate. - /// - /// The event to be added to the end of . - protected sealed override void AddEvent(ITracedDomainEvent e) - { - ApplyChange(e); - } + /// + /// Adds an event to the Aggregate. + /// + /// The event to be added to the end of . + protected sealed override void AddEvent(ITracedDomainEvent e) + { + ApplyChange(e); + } - private void ApplyChange(ITracedDomainEvent e, bool isNew = true) + private void ApplyChange(ITracedDomainEvent e, bool isNew = true) + { + if (e == null) { return; } + if (isNew) { - if (e == null) { return; } - if (isNew) - { - RaiseEvent(e); - e.SetAggregateVersion(Version + 1); - Version = e.GetAggregateVersion(); - base.AddEvent(e); - } - else - { - RaiseEvent(e); - } + RaiseEvent(e); + e.SetAggregateVersion(Version + 1); + Version = e.GetAggregateVersion(); + base.AddEvent(e); } - - private void RaiseEvent(ITracedDomainEvent @event) + else { - _handlers.TryInvoke(@event); + RaiseEvent(e); } } + + private void RaiseEvent(ITracedDomainEvent @event) + { + _handlers.TryInvoke(@event); + } } diff --git a/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs b/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs index f2709b86..438bbbe2 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs @@ -1,36 +1,35 @@ -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Provides a default implementation of something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. +/// +/// +/// +public abstract record TracedDomainEvent : DomainEvent, ITracedDomainEvent { /// - /// Provides a default implementation of something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. + /// Initializes a new instance of the class. /// - /// - /// - public abstract record TracedDomainEvent : DomainEvent, ITracedDomainEvent + /// The optional identifier of the event. Default is an auto-generated UUID. + /// The optional metadata to merge with this instance. + /// + /// The following table shows the initial metadata values for an instance of . + /// + /// + /// Key + /// Initial Value + /// + /// + /// + /// eventId ?? Guid.NewGuid().ToString("N") + /// + /// + /// + /// DateTime.UtcNow + /// + /// + /// + protected TracedDomainEvent(string eventId = null, IMetadata metadata = null) : base(eventId, metadata) { - /// - /// Initializes a new instance of the class. - /// - /// The optional identifier of the event. Default is an auto-generated UUID. - /// The optional metadata to merge with this instance. - /// - /// The following table shows the initial metadata values for an instance of . - /// - /// - /// Key - /// Initial Value - /// - /// - /// - /// eventId ?? Guid.NewGuid().ToString("N") - /// - /// - /// - /// DateTime.UtcNow - /// - /// - /// - protected TracedDomainEvent(string eventId = null, IMetadata metadata = null) : base(eventId, metadata) - { - } } } diff --git a/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs b/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs index 39288358..73392fe3 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs @@ -1,44 +1,43 @@ using Cuemon.Extensions; -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +/// +/// Extension methods for the interface. +/// +public static class TracedDomainEventExtensions { /// - /// Extension methods for the interface. + /// Assigns a new to the . /// - public static class TracedDomainEventExtensions + /// The model that implements the interface. + /// The to extend. + /// The aggregate version of the model. + /// A reference to after the operation has completed. + public static T SetAggregateVersion(this T request, long version) where T : ITracedDomainEvent { - /// - /// Assigns a new to the . - /// - /// The model that implements the interface. - /// The to extend. - /// The aggregate version of the model. - /// A reference to after the operation has completed. - public static T SetAggregateVersion(this T request, long version) where T : ITracedDomainEvent - { - return MetadataFactory.Set(request, MetadataDictionary.AggregateVersion, version); - } + return MetadataFactory.Set(request, MetadataDictionary.AggregateVersion, version); + } - /// - /// Gets the aggregate version from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The version of the associated . - public static long GetAggregateVersion(this T request) where T : ITracedDomainEvent - { - return MetadataFactory.Get(request, MetadataDictionary.AggregateVersion).As(); - } + /// + /// Gets the aggregate version from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The version of the associated . + public static long GetAggregateVersion(this T request) where T : ITracedDomainEvent + { + return MetadataFactory.Get(request, MetadataDictionary.AggregateVersion).As(); + } - /// - /// Gets the string representation of the type from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the type from the . - public static string GetMemberType(this T request) where T : ITracedDomainEvent - { - return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); - } + /// + /// Gets the string representation of the type from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The string representation of the type from the . + public static string GetMemberType(this T request) where T : ITracedDomainEvent + { + return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); } } diff --git a/src/Savvyio.Domain/Aggregate.cs b/src/Savvyio.Domain/Aggregate.cs index d7e74ee6..8d7192f1 100644 --- a/src/Savvyio.Domain/Aggregate.cs +++ b/src/Savvyio.Domain/Aggregate.cs @@ -1,61 +1,60 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Represents the base class from which all implementations of an Aggregate Root (as specified in Domain Driven Design) should derive. +/// +/// The type of the key that uniquely identifies this aggregate. +/// The type of the event that implements the interface. +/// +public abstract class Aggregate : Entity, IMetadata { + private readonly List _events = new(); + + /// + /// Initializes a new instance of the class. + /// + /// The optional metadata to merge with this instance. + protected Aggregate(IMetadata metadata = null) + { + this.MergeMetadata(metadata); + } + + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the entity. + protected Aggregate(TKey id) : base(id) + { + } + + /// + /// Gets the events that was added to the Aggregate. + /// + /// The events added to the Aggregate. + public IReadOnlyList Events => _events; + + /// + /// Gets the associated metadata of this Aggregate. + /// + /// The associated metadata of this Aggregate. + public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); + + /// + /// Adds an event to the Aggregate. + /// + /// The event to be added to the end of . + protected virtual void AddEvent(TEvent e) + { + _events.Add(e); + } + /// - /// Represents the base class from which all implementations of an Aggregate Root (as specified in Domain Driven Design) should derive. + /// Removes all events from the Aggregate. /// - /// The type of the key that uniquely identifies this aggregate. - /// The type of the event that implements the interface. - /// - public abstract class Aggregate : Entity, IMetadata + public void RemoveAllEvents() { - private readonly List _events = new(); - - /// - /// Initializes a new instance of the class. - /// - /// The optional metadata to merge with this instance. - protected Aggregate(IMetadata metadata = null) - { - this.MergeMetadata(metadata); - } - - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the entity. - protected Aggregate(TKey id) : base(id) - { - } - - /// - /// Gets the events that was added to the Aggregate. - /// - /// The events added to the Aggregate. - public IReadOnlyList Events => _events; - - /// - /// Gets the associated metadata of this Aggregate. - /// - /// The associated metadata of this Aggregate. - public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); - - /// - /// Adds an event to the Aggregate. - /// - /// The event to be added to the end of . - protected virtual void AddEvent(TEvent e) - { - _events.Add(e); - } - - /// - /// Removes all events from the Aggregate. - /// - public void RemoveAllEvents() - { - _events.Clear(); - } + _events.Clear(); } } diff --git a/src/Savvyio.Domain/AggregateRoot.cs b/src/Savvyio.Domain/AggregateRoot.cs index 38ea0d99..a0f4c6b9 100644 --- a/src/Savvyio.Domain/AggregateRoot.cs +++ b/src/Savvyio.Domain/AggregateRoot.cs @@ -1,26 +1,25 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides a way to cover the pattern of an Aggregate Root as specified in Domain Driven Design. This is an abstract class. +/// +/// The type of the key that uniquely identifies this aggregate. +/// +public abstract class AggregateRoot : Aggregate, IAggregateRoot { /// - /// Provides a way to cover the pattern of an Aggregate Root as specified in Domain Driven Design. This is an abstract class. + /// Initializes a new instance of the class. /// - /// The type of the key that uniquely identifies this aggregate. - /// - public abstract class AggregateRoot : Aggregate, IAggregateRoot + /// The optional metadata to merge with this instance. + protected AggregateRoot(IMetadata metadata = null) : base(metadata) { - /// - /// Initializes a new instance of the class. - /// - /// The optional metadata to merge with this instance. - protected AggregateRoot(IMetadata metadata = null) : base(metadata) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the entity. - protected AggregateRoot(TKey id) : base(id) - { - } + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the entity. + protected AggregateRoot(TKey id) : base(id) + { } } diff --git a/src/Savvyio.Domain/DomainEvent.cs b/src/Savvyio.Domain/DomainEvent.cs index d3858c44..a58fe12c 100644 --- a/src/Savvyio.Domain/DomainEvent.cs +++ b/src/Savvyio.Domain/DomainEvent.cs @@ -1,41 +1,40 @@ using System; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides a default implementation of the interface. +/// +/// +/// +public abstract record DomainEvent : Request, IDomainEvent { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public abstract record DomainEvent : Request, IDomainEvent + /// The optional identifier of the event. Default is an auto-generated UUID. + /// The optional metadata to merge with this instance. + /// + /// The following table shows the initial metadata values for an instance of . + /// + /// + /// Key + /// Initial Value + /// + /// + /// + /// eventId ?? Guid.NewGuid().ToString("N") + /// + /// + /// + /// DateTime.UtcNow + /// + /// + /// + protected DomainEvent(string eventId = null, IMetadata metadata = null) { - /// - /// Initializes a new instance of the class. - /// - /// The optional identifier of the event. Default is an auto-generated UUID. - /// The optional metadata to merge with this instance. - /// - /// The following table shows the initial metadata values for an instance of . - /// - /// - /// Key - /// Initial Value - /// - /// - /// - /// eventId ?? Guid.NewGuid().ToString("N") - /// - /// - /// - /// DateTime.UtcNow - /// - /// - /// - protected DomainEvent(string eventId = null, IMetadata metadata = null) - { - this.SetEventId(eventId ?? Guid.NewGuid().ToString("N")); - this.SetTimestamp(); - this.MergeMetadata(metadata); - } + this.SetEventId(eventId ?? Guid.NewGuid().ToString("N")); + this.SetTimestamp(); + this.MergeMetadata(metadata); } } diff --git a/src/Savvyio.Domain/DomainEventDispatcher.cs b/src/Savvyio.Domain/DomainEventDispatcher.cs index a57e9e7c..382e02ee 100644 --- a/src/Savvyio.Domain/DomainEventDispatcher.cs +++ b/src/Savvyio.Domain/DomainEventDispatcher.cs @@ -4,43 +4,42 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides a default implementation of of the interface. +/// +/// +/// +public class DomainEventDispatcher : FireForgetDispatcher, IDomainEventDispatcher { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public class DomainEventDispatcher : FireForgetDispatcher, IDomainEventDispatcher + /// The provider of service implementations. + public DomainEventDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - public DomainEventDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Raises the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to raise. - public void Raise(IDomainEvent request) - { - Validator.ThrowIfNull(request); - Dispatch(request, handler => handler.Delegates); - } + /// + /// Raises the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to raise. + public void Raise(IDomainEvent request) + { + Validator.ThrowIfNull(request); + Dispatch(request, handler => handler.Delegates); + } - /// - /// Raises the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to raise. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task RaiseAsync(IDomainEvent request, Action setup = null) - { - Validator.ThrowIfNull(request); - return DispatchAsync(request, handler => handler.Delegates, setup); - } + /// + /// Raises the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to raise. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task RaiseAsync(IDomainEvent request, Action setup = null) + { + Validator.ThrowIfNull(request); + return DispatchAsync(request, handler => handler.Delegates, setup); } } diff --git a/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs b/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs index baf43454..db4bc657 100644 --- a/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs +++ b/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs @@ -4,45 +4,44 @@ using Cuemon.Threading; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Extension methods for the interface. +/// +public static class DomainEventDispatcherExtensions { /// - /// Extension methods for the interface. + /// Raises domain events from the specified to handlers that implements the interface. /// - public static class DomainEventDispatcherExtensions + /// The type that implements the interface. + /// The to extend. + /// The aggregate to publish domain events from. + public static void RaiseMany(this IDomainEventDispatcher dispatcher, IAggregateRoot aggregate) where T : IDomainEvent { - /// - /// Raises domain events from the specified to handlers that implements the interface. - /// - /// The type that implements the interface. - /// The to extend. - /// The aggregate to publish domain events from. - public static void RaiseMany(this IDomainEventDispatcher dispatcher, IAggregateRoot aggregate) where T : IDomainEvent + var events = aggregate.Events.ToList(); + if (!typeof(ITracedDomainEvent).IsAssignableFrom(typeof(T))) { aggregate.RemoveAllEvents(); } + foreach (var @event in events) { - var events = aggregate.Events.ToList(); - if (!typeof(ITracedDomainEvent).IsAssignableFrom(typeof(T))) { aggregate.RemoveAllEvents(); } - foreach (var @event in events) - { - dispatcher.Raise(@event.MergeMetadata(aggregate)); - } + dispatcher.Raise(@event.MergeMetadata(aggregate)); } + } - /// - /// Asynchronously raises domain events from the specified to handlers that implements the interface. - /// - /// The type that implements the interface. - /// The to extend. - /// The aggregate to publish domain events from. - /// The which may be configured. - /// A that represents the asynchronous operation. - public static async Task RaiseManyAsync(this IDomainEventDispatcher dispatcher, IAggregateRoot aggregate, Action setup = null) where T : IDomainEvent + /// + /// Asynchronously raises domain events from the specified to handlers that implements the interface. + /// + /// The type that implements the interface. + /// The to extend. + /// The aggregate to publish domain events from. + /// The which may be configured. + /// A that represents the asynchronous operation. + public static async Task RaiseManyAsync(this IDomainEventDispatcher dispatcher, IAggregateRoot aggregate, Action setup = null) where T : IDomainEvent + { + var events = aggregate.Events.ToList(); + if (!typeof(ITracedDomainEvent).IsAssignableFrom(typeof(T))) { aggregate.RemoveAllEvents(); } + foreach (var @event in events) { - var events = aggregate.Events.ToList(); - if (!typeof(ITracedDomainEvent).IsAssignableFrom(typeof(T))) { aggregate.RemoveAllEvents(); } - foreach (var @event in events) - { - await dispatcher.RaiseAsync(@event.MergeMetadata(aggregate), setup).ConfigureAwait(false); - } + await dispatcher.RaiseAsync(@event.MergeMetadata(aggregate), setup).ConfigureAwait(false); } } } diff --git a/src/Savvyio.Domain/DomainEventExtensions.cs b/src/Savvyio.Domain/DomainEventExtensions.cs index cc78d551..955ad22b 100644 --- a/src/Savvyio.Domain/DomainEventExtensions.cs +++ b/src/Savvyio.Domain/DomainEventExtensions.cs @@ -2,33 +2,32 @@ using Cuemon.Extensions; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Extension methods for the interface. +/// +public static class DomainEventExtensions { /// - /// Extension methods for the interface. + /// Gets the string representation of the event identifier from the . /// - public static class DomainEventExtensions + /// The model that implements the interface. + /// The to extend. + /// The string representation of the event identifier from the . + public static string GetEventId(this T request) where T : IDomainEvent { - /// - /// Gets the string representation of the event identifier from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the event identifier from the . - public static string GetEventId(this T request) where T : IDomainEvent - { - return MetadataFactory.Get(request, MetadataDictionary.EventId).As(); - } + return MetadataFactory.Get(request, MetadataDictionary.EventId).As(); + } - /// - /// Gets the value of the timestamp from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The value of the timestamp from the . - public static DateTime GetTimestamp(this T request) where T : IDomainEvent - { - return MetadataFactory.Get(request, MetadataDictionary.Timestamp).As(); - } + /// + /// Gets the value of the timestamp from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The value of the timestamp from the . + public static DateTime GetTimestamp(this T request) where T : IDomainEvent + { + return MetadataFactory.Get(request, MetadataDictionary.Timestamp).As(); } } diff --git a/src/Savvyio.Domain/DomainEventHandler.cs b/src/Savvyio.Domain/DomainEventHandler.cs index 3041e0db..9c7d2fa3 100644 --- a/src/Savvyio.Domain/DomainEventHandler.cs +++ b/src/Savvyio.Domain/DomainEventHandler.cs @@ -1,31 +1,30 @@ using Savvyio.Handlers; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides a generic and consistent way of handling Domain Event (as specified in Domain Driven Design) objects that implements the interface. This is an abstract class. +/// +/// +public abstract class DomainEventHandler : IDomainEventHandler { /// - /// Provides a generic and consistent way of handling Domain Event (as specified in Domain Driven Design) objects that implements the interface. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class DomainEventHandler : IDomainEventHandler + protected DomainEventHandler() { - /// - /// Initializes a new instance of the class. - /// - protected DomainEventHandler() - { - Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); - } + Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); + } - /// - /// Registers the delegates responsible of handling types that implements the interface. - /// - /// The registry that store the delegates of type . - protected abstract void RegisterDelegates(IFireForgetRegistry handlers); + /// + /// Registers the delegates responsible of handling types that implements the interface. + /// + /// The registry that store the delegates of type . + protected abstract void RegisterDelegates(IFireForgetRegistry handlers); - /// - /// Gets the activator responsible of invoking delegates that handles . - /// - /// The activator responsible of invoking delegates that handles . - public IFireForgetActivator Delegates { get; } - } + /// + /// Gets the activator responsible of invoking delegates that handles . + /// + /// The activator responsible of invoking delegates that handles . + public IFireForgetActivator Delegates { get; } } diff --git a/src/Savvyio.Domain/Entity.cs b/src/Savvyio.Domain/Entity.cs index b293e710..a4ceb16d 100644 --- a/src/Savvyio.Domain/Entity.cs +++ b/src/Savvyio.Domain/Entity.cs @@ -1,40 +1,39 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides a way to cover the pattern of an Entity as specified in Domain Driven Design. This is an abstract class. +/// +/// The type of the identifier. +/// +public abstract class Entity : IEntity { /// - /// Provides a way to cover the pattern of an Entity as specified in Domain Driven Design. This is an abstract class. + /// Initializes a new instance of the class. /// - /// The type of the identifier. - /// - public abstract class Entity : IEntity + protected Entity() { - /// - /// Initializes a new instance of the class. - /// - protected Entity() - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the entity. - protected Entity(TKey id) - { - Id = id; - } + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the entity. + protected Entity(TKey id) + { + Id = id; + } - /// - /// Gets or sets the value of the identifier. - /// - /// The value of the identifier. - public TKey Id { get; protected set; } + /// + /// Gets or sets the value of the identifier. + /// + /// The value of the identifier. + public TKey Id { get; protected set; } - /// - /// Gets a value indicating whether this instance is transient. - /// - /// true if this instance is transient; otherwise, false. - public virtual bool IsTransient => EqualityComparer.Default.Equals(Id, default); - } + /// + /// Gets a value indicating whether this instance is transient. + /// + /// true if this instance is transient; otherwise, false. + public virtual bool IsTransient => EqualityComparer.Default.Equals(Id, default); } diff --git a/src/Savvyio.Domain/SavvyioOptionsExtensions.cs b/src/Savvyio.Domain/SavvyioOptionsExtensions.cs index 36bb560e..c88adf60 100644 --- a/src/Savvyio.Domain/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Domain/SavvyioOptionsExtensions.cs @@ -1,29 +1,28 @@ -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds an implementation of the interface to (if not already registered). /// - public static class SavvyioOptionsExtensions + /// The type that implements the interface. + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddDomainEventHandler(this SavvyioOptions options) where TImplementation : class, IDomainEventHandler { - /// - /// Adds an implementation of the interface to (if not already registered). - /// - /// The type that implements the interface. - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddDomainEventHandler(this SavvyioOptions options) where TImplementation : class, IDomainEventHandler - { - return options.AddHandler(); - } + return options.AddHandler(); + } - /// - /// Adds a default implementation of the interface. - /// - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddDomainEventDispatcher(this SavvyioOptions options) - { - return options.AddDispatcher(); - } + /// + /// Adds a default implementation of the interface. + /// + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddDomainEventDispatcher(this SavvyioOptions options) + { + return options.AddDispatcher(); } } diff --git a/src/Savvyio.Domain/SingleValueObject.cs b/src/Savvyio.Domain/SingleValueObject.cs index 2158ce1d..12266e5f 100644 --- a/src/Savvyio.Domain/SingleValueObject.cs +++ b/src/Savvyio.Domain/SingleValueObject.cs @@ -1,46 +1,45 @@ using System.Collections.Generic; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Provides an implementation of tailored for handling a single value. +/// +/// The type of the object. +/// +public abstract record SingleValueObject : ValueObject { /// - /// Provides an implementation of tailored for handling a single value. + /// Performs an implicit conversion from to . /// - /// The type of the object. - /// - public abstract record SingleValueObject : ValueObject + /// The value to convert. + /// that is equivalent to . + public static implicit operator T(SingleValueObject value) { - /// - /// Performs an implicit conversion from to . - /// - /// The value to convert. - /// that is equivalent to . - public static implicit operator T(SingleValueObject value) - { - return value.Value; - } + return value.Value; + } - /// - /// Initializes a new instance of the class. - /// - /// The value to associate to . - protected SingleValueObject(T value) - { - Value = value; - } + /// + /// Initializes a new instance of the class. + /// + /// The value to associate to . + protected SingleValueObject(T value) + { + Value = value; + } - /// - /// Gets the value of this instance. - /// - /// The value of this instance. - public T Value { get; } + /// + /// Gets the value of this instance. + /// + /// The value of this instance. + public T Value { get; } - /// - /// Gets the equality components of this instance. - /// - /// An that contains the equality components of this instance. - protected sealed override IEnumerable GetEqualityComponents() - { - yield return Value; - } + /// + /// Gets the equality components of this instance. + /// + /// An that contains the equality components of this instance. + protected sealed override IEnumerable GetEqualityComponents() + { + yield return Value; } } diff --git a/src/Savvyio.Domain/ValueObject.cs b/src/Savvyio.Domain/ValueObject.cs index a2ef8dcd..d4ea34ad 100644 --- a/src/Savvyio.Domain/ValueObject.cs +++ b/src/Savvyio.Domain/ValueObject.cs @@ -5,78 +5,77 @@ using Cuemon.Extensions; using Cuemon.Reflection; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +/// +/// Represents an object whose equality is based on the value rather than identity as specified in Domain Driven Design. +/// +/// +public abstract record ValueObject { + private const int NullHashCode = 472074819; + private readonly Lock _locker = new(); + private IEnumerable _equalityComponents; + /// - /// Represents an object whose equality is based on the value rather than identity as specified in Domain Driven Design. + /// Initializes a new instance of the class. /// - /// - public abstract record ValueObject + protected ValueObject() { - private const int NullHashCode = 472074819; - private readonly Lock _locker = new(); - private IEnumerable _equalityComponents; - - /// - /// Initializes a new instance of the class. - /// - protected ValueObject() - { - } + } - /// - /// Gets the equality components of this instance. Default is all public properties having a simple signature. - /// - /// An that contains the equality components of this instance. - protected virtual IEnumerable GetEqualityComponents() + /// + /// Gets the equality components of this instance. Default is all public properties having a simple signature. + /// + /// An that contains the equality components of this instance. + protected virtual IEnumerable GetEqualityComponents() + { + if (_equalityComponents == null) { - if (_equalityComponents == null) + lock (_locker) { - lock (_locker) + if (_equalityComponents == null) { - if (_equalityComponents == null) + var equalityComponents = new List(); + var properties = GetType().GetProperties(new MemberReflection(true, true)).Where(pi => (pi.PropertyType.IsSimple() || pi.PropertyType.IsAssignableTo(typeof(ValueObject))) && pi.CanRead); + foreach (var property in properties) { - var equalityComponents = new List(); - var properties = GetType().GetProperties(new MemberReflection(true, true)).Where(pi => (pi.PropertyType.IsSimple() || pi.PropertyType.IsAssignableTo(typeof(ValueObject))) && pi.CanRead); - foreach (var property in properties) - { - equalityComponents.Add(property.GetValue(this)); - } - _equalityComponents = equalityComponents; + equalityComponents.Add(property.GetValue(this)); } + _equalityComponents = equalityComponents; } } - return _equalityComponents; } + return _equalityComponents; + } - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// An object to compare with this object. - /// if the current object is equal to the parameter; otherwise, . - public virtual bool Equals(ValueObject other) - { - if (ReferenceEquals(this, other)) { return true; } - if (ReferenceEquals(null, other)) { return false; } - return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); - } + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// if the current object is equal to the parameter; otherwise, . + public virtual bool Equals(ValueObject other) + { + if (ReferenceEquals(this, other)) { return true; } + if (ReferenceEquals(null, other)) { return false; } + return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); + } - /// - /// Returns a hash code for this instance. - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - public override int GetHashCode() - { - return GetEqualityComponents().Select(x => x != null ? x.GetHashCode() : NullHashCode).GetHashCode32(); - } + /// + /// Returns a hash code for this instance. + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + public override int GetHashCode() + { + return GetEqualityComponents().Select(x => x != null ? x.GetHashCode() : NullHashCode).GetHashCode32(); + } - /// - /// Returns a that represents this instance. - /// - /// A that represents this instance. - public override string ToString() - { - return DelimitedString.Create(GetEqualityComponents()); - } + /// + /// Returns a that represents this instance. + /// + /// A that represents this instance. + public override string ToString() + { + return DelimitedString.Create(GetEqualityComponents()); } } diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs index 6a55b0f8..fb548b3a 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs @@ -6,208 +6,207 @@ using Cuemon.Collections.Generic; using Savvyio.Messaging; -namespace Savvyio.EventDriven.Messaging.CloudEvents +namespace Savvyio.EventDriven.Messaging.CloudEvents; + +/// +/// Provides the base class for an implementation of the interface. +/// +public abstract record CloudEvent : Acknowledgeable { /// - /// Provides the base class for an implementation of the interface. + /// Gets a list of the reserved keywords. /// - public abstract record CloudEvent : Acknowledgeable - { - /// - /// Gets a list of the reserved keywords. - /// - /// A list of the reserved keywords. - protected static IReadOnlyCollection ReservedKeywords { get; } = Arguments.ToEnumerableOf(nameof(Id), nameof(Source), nameof(Type), nameof(Time), nameof(Data), nameof(Specversion)).ToList(); - - /// - /// Initializes a new instance of the class. - /// - protected CloudEvent() - { - } + /// A list of the reserved keywords. + protected static IReadOnlyCollection ReservedKeywords { get; } = Arguments.ToEnumerableOf(nameof(Id), nameof(Source), nameof(Type), nameof(Time), nameof(Data), nameof(Specversion)).ToList(); - /// - /// Gets the identifier of the event. When combined with , this enables deduplication. - /// - /// The identifier of the event. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#id - public string Id { get; protected set; } - - /// - /// Gets the context in which an event happened. When combined with , this enables deduplication. - /// - /// The context in which an event happened. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#source-1 - public string Source { get; protected set; } - - - /// - /// Gets the value describing the type of event related to the originating occurrence. - /// - /// The value describing the type of event related to the originating occurrence. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#type - public string Type { get; protected set; } - - /// - /// Gets the time, expressed as the Coordinated Universal Time (UTC), of when the occurrence happened. - /// - /// The timestamp of when the occurrence happened. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#time - public DateTime? Time { get; protected set; } - - /// - /// Gets version of the CloudEvents specification which the event uses. - /// - /// The version of the CloudEvents specification which the event uses. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#specversion - public string Specversion { get; protected set; } + /// + /// Initializes a new instance of the class. + /// + protected CloudEvent() + { } /// - /// Provides a default implementation of the interface. + /// Gets the identifier of the event. When combined with , this enables deduplication. /// - /// The type of the payload constraint to the interface. - /// - public record CloudEvent : CloudEvent, ICloudEvent where T : IIntegrationEvent - { - private readonly IDictionary _extensionAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase); + /// The identifier of the event. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#id + public string Id { get; protected set; } - private static string EnsureReservedKeywordCompliance(string key) // https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#attribute-naming-convention - { - Validator.ThrowIfNullOrWhitespace(key); - Validator.ThrowIfContainsReservedKeyword(key, ReservedKeywords); - return key.ToLowerInvariant(); - } + /// + /// Gets the context in which an event happened. When combined with , this enables deduplication. + /// + /// The context in which an event happened. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#source-1 + public string Source { get; protected set; } - /// - /// Initializes a new instance of the class. - /// - /// The message to elevate to an compliance. - /// The version of the CloudEvents specification which the event uses. - /// - /// cannot be null. - /// - public CloudEvent(IMessage message, string specversion = null) - { - Validator.ThrowIfNull(message); - Id = message.Id; - Source = message.Source; - Type = message.Type; - Time = message.Time; - Data = message.Data; - Specversion = specversion ?? "1.0"; - } - /// - /// Gets the event payload. - /// - /// The event payload. - /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#event-data - public T Data { get; } + /// + /// Gets the value describing the type of event related to the originating occurrence. + /// + /// The value describing the type of event related to the originating occurrence. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#type + public string Type { get; protected set; } + /// + /// Gets the time, expressed as the Coordinated Universal Time (UTC), of when the occurrence happened. + /// + /// The timestamp of when the occurrence happened. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#time + public DateTime? Time { get; protected set; } + /// + /// Gets version of the CloudEvents specification which the event uses. + /// + /// The version of the CloudEvents specification which the event uses. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#specversion + public string Specversion { get; protected set; } +} - IEnumerator> IEnumerable>.GetEnumerator() - { - return _extensionAttributes.GetEnumerator(); - } +/// +/// Provides a default implementation of the interface. +/// +/// The type of the payload constraint to the interface. +/// +public record CloudEvent : CloudEvent, ICloudEvent where T : IIntegrationEvent +{ + private readonly IDictionary _extensionAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase); - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)_extensionAttributes).GetEnumerator(); - } + private static string EnsureReservedKeywordCompliance(string key) // https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#attribute-naming-convention + { + Validator.ThrowIfNullOrWhitespace(key); + Validator.ThrowIfContainsReservedKeyword(key, ReservedKeywords); + return key.ToLowerInvariant(); + } - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } + /// + /// Initializes a new instance of the class. + /// + /// The message to elevate to an compliance. + /// The version of the CloudEvents specification which the event uses. + /// + /// cannot be null. + /// + public CloudEvent(IMessage message, string specversion = null) + { + Validator.ThrowIfNull(message); + Id = message.Id; + Source = message.Source; + Type = message.Type; + Time = message.Time; + Data = message.Data; + Specversion = specversion ?? "1.0"; + } - /// - /// Removes all items from the . - /// - public void Clear() - { - _extensionAttributes.Clear(); - } + /// + /// Gets the event payload. + /// + /// The event payload. + /// https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#event-data + public T Data { get; } - bool ICollection>.Contains(KeyValuePair item) - { - return _extensionAttributes.Contains(item); - } - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - _extensionAttributes.CopyTo(array, arrayIndex); - } - bool ICollection>.Remove(KeyValuePair item) - { - return Remove(item.Key); - } + IEnumerator> IEnumerable>.GetEnumerator() + { + return _extensionAttributes.GetEnumerator(); + } - int ICollection>.Count => _extensionAttributes.Count; + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_extensionAttributes).GetEnumerator(); + } - bool ICollection>.IsReadOnly => _extensionAttributes.IsReadOnly; + void ICollection>.Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } - /// - /// Adds an element with the provided key and value to the . - /// - /// The object to use as the key of the element to add. - /// The object to use as the value of the element to add. - public void Add(string key, object value) - { - var parsedKey = EnsureReservedKeywordCompliance(key); - _extensionAttributes.Add(parsedKey, value); - } + /// + /// Removes all items from the . + /// + public void Clear() + { + _extensionAttributes.Clear(); + } - /// - /// Determines whether the contains an element with the specified key. - /// - /// The key to locate in the . - /// if the contains an element with the key; otherwise, . - public bool ContainsKey(string key) - { - return _extensionAttributes.ContainsKey(key); - } + bool ICollection>.Contains(KeyValuePair item) + { + return _extensionAttributes.Contains(item); + } - /// - /// Removes the element with the specified key from the . - /// - /// The key of the element to remove. - /// if the element is successfully removed; otherwise, . This method also returns if was not found in the original . - public bool Remove(string key) - { - return _extensionAttributes.Remove(key); - } + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + _extensionAttributes.CopyTo(array, arrayIndex); + } - /// - /// Gets the value associated with the specified key. - /// - /// The key whose value to get. - /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. - /// if the object that implements contains an element with the specified key; otherwise, . - public bool TryGetValue(string key, out object value) - { - return _extensionAttributes.TryGetValue(key, out value); - } + bool ICollection>.Remove(KeyValuePair item) + { + return Remove(item.Key); + } + + int ICollection>.Count => _extensionAttributes.Count; + + bool ICollection>.IsReadOnly => _extensionAttributes.IsReadOnly; + + /// + /// Adds an element with the provided key and value to the . + /// + /// The object to use as the key of the element to add. + /// The object to use as the value of the element to add. + public void Add(string key, object value) + { + var parsedKey = EnsureReservedKeywordCompliance(key); + _extensionAttributes.Add(parsedKey, value); + } + + /// + /// Determines whether the contains an element with the specified key. + /// + /// The key to locate in the . + /// if the contains an element with the key; otherwise, . + public bool ContainsKey(string key) + { + return _extensionAttributes.ContainsKey(key); + } + + /// + /// Removes the element with the specified key from the . + /// + /// The key of the element to remove. + /// if the element is successfully removed; otherwise, . This method also returns if was not found in the original . + public bool Remove(string key) + { + return _extensionAttributes.Remove(key); + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key whose value to get. + /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. + /// if the object that implements contains an element with the specified key; otherwise, . + public bool TryGetValue(string key, out object value) + { + return _extensionAttributes.TryGetValue(key, out value); + } - /// - /// Gets or sets the element with the specified key. - /// - /// The key of the value to get or set. - /// The value associated with the specified key. - public object this[string key] + /// + /// Gets or sets the element with the specified key. + /// + /// The key of the value to get or set. + /// The value associated with the specified key. + public object this[string key] + { + get => _extensionAttributes[key]; + set { - get => _extensionAttributes[key]; - set - { - var parsedKey = EnsureReservedKeywordCompliance(key); - _extensionAttributes[parsedKey] = value; - } + var parsedKey = EnsureReservedKeywordCompliance(key); + _extensionAttributes[parsedKey] = value; } + } - ICollection IDictionary.Keys => _extensionAttributes.Keys; + ICollection IDictionary.Keys => _extensionAttributes.Keys; - ICollection IDictionary.Values => _extensionAttributes.Values; - } + ICollection IDictionary.Values => _extensionAttributes.Values; } diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs index d28d17ca..f3f1ceee 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs @@ -3,36 +3,35 @@ using Cuemon.Security.Cryptography; using Savvyio.Messaging.Cryptography; -namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; + +/// +/// Extension methods for the interface. +/// +public static class CloudEventExtensions { /// - /// Extension methods for the interface. + /// Converts the specified to an equivalent. /// - public static class CloudEventExtensions + /// The type of the payload constraint to the interface. + /// The payload to attach within the message. + /// The that is used when converting the into an . + /// The which may be configured. + /// An instance of constraint to the interface. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + public static ISignedCloudEvent SignCloudEvent(this ICloudEvent cloudEvent, IMarshaller marshaller, Action setup = null) where T : IIntegrationEvent { - /// - /// Converts the specified to an equivalent. - /// - /// The type of the payload constraint to the interface. - /// The payload to attach within the message. - /// The that is used when converting the into an . - /// The which may be configured. - /// An instance of constraint to the interface. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - public static ISignedCloudEvent SignCloudEvent(this ICloudEvent cloudEvent, IMarshaller marshaller, Action setup = null) where T : IIntegrationEvent - { - Validator.ThrowIfNull(cloudEvent); - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - var data = marshaller.Serialize(cloudEvent); - var signature = KeyedHashFactory.CreateHmacCrypto(options.SignatureSecret, options.SignatureAlgorithm).ComputeHash(data).ToHexadecimalString(); - return new SignedCloudEvent(cloudEvent, signature); - } + Validator.ThrowIfNull(cloudEvent); + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + var data = marshaller.Serialize(cloudEvent); + var signature = KeyedHashFactory.CreateHmacCrypto(options.SignatureSecret, options.SignatureAlgorithm).ComputeHash(data).ToHexadecimalString(); + return new SignedCloudEvent(cloudEvent, signature); } } diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs index f37795aa..2762803a 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs @@ -1,34 +1,33 @@ using System; using Cuemon; -namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; + +/// +/// Provides a default implementation of the interface. +/// +/// The type of the payload constraint to the interface. +/// +public record SignedCloudEvent : CloudEvent, ISignedCloudEvent where T : IIntegrationEvent { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// The type of the payload constraint to the interface. - /// - public record SignedCloudEvent : CloudEvent, ISignedCloudEvent where T : IIntegrationEvent + /// The cloud event to sign. + /// The cryptographic signature of the . + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// cannot be empty or consist only of white-space characters. + /// + public SignedCloudEvent(ICloudEvent message, string signature) : base(message, message.Specversion) { - /// - /// Initializes a new instance of the class. - /// - /// The cloud event to sign. - /// The cryptographic signature of the . - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// cannot be empty or consist only of white-space characters. - /// - public SignedCloudEvent(ICloudEvent message, string signature) : base(message, message.Specversion) - { - Validator.ThrowIfNullOrWhitespace(signature); - Signature = signature; - } - - /// - public string Signature { get; } + Validator.ThrowIfNullOrWhitespace(signature); + Signature = signature; } + + /// + public string Signature { get; } } diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEventExtensions.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEventExtensions.cs index cb18d358..00d5d6bb 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEventExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEventExtensions.cs @@ -3,42 +3,41 @@ using Savvyio.Messaging; using Savvyio.Messaging.Cryptography; -namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; + +/// +/// Extension methods for the interface. +/// +public static class SignedCloudEventExtensions { + /// - /// Extension methods for the interface. + /// Verifies the digital signature of the message. /// - public static class SignedCloudEventExtensions + /// The type of the payload constraint to the interface. + /// The message to cryptographically verify. + /// The that is used when converting the into an . + /// The that must be configured. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + /// + /// signature did not match the cryptographically calculated value. + /// + /// This method throws an if the verification of the digital signature fails. + public static void CheckCloudEventSignature(this ISignedCloudEvent cloudEvent, IMarshaller marshaller, Action setup) where T : IIntegrationEvent { - - /// - /// Verifies the digital signature of the message. - /// - /// The type of the payload constraint to the interface. - /// The message to cryptographically verify. - /// The that is used when converting the into an . - /// The that must be configured. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - /// - /// signature did not match the cryptographically calculated value. - /// - /// This method throws an if the verification of the digital signature fails. - public static void CheckCloudEventSignature(this ISignedCloudEvent cloudEvent, IMarshaller marshaller, Action setup) where T : IIntegrationEvent + Validator.ThrowIfNull(cloudEvent); + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidConfigurator(setup, out _); + var baseCloudEvent = (cloudEvent.Clone(() => new CloudEvent(cloudEvent, cloudEvent.Specversion)) as ICloudEvent).SignCloudEvent(marshaller, setup); + if (!cloudEvent.Signature.Equals(baseCloudEvent.Signature, StringComparison.Ordinal)) { - Validator.ThrowIfNull(cloudEvent); - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidConfigurator(setup, out _); - var baseCloudEvent = (cloudEvent.Clone(() => new CloudEvent(cloudEvent, cloudEvent.Specversion)) as ICloudEvent).SignCloudEvent(marshaller, setup); - if (!cloudEvent.Signature.Equals(baseCloudEvent.Signature, StringComparison.Ordinal)) - { - throw new ArgumentOutOfRangeException(nameof(cloudEvent), cloudEvent.Signature, "The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with."); - } + throw new ArgumentOutOfRangeException(nameof(cloudEvent), cloudEvent.Signature, "The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with."); } } } diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs index 8077747a..6b64aee0 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs @@ -2,27 +2,26 @@ using Cuemon; using Savvyio.Messaging; -namespace Savvyio.EventDriven.Messaging.CloudEvents +namespace Savvyio.EventDriven.Messaging.CloudEvents; + +/// +/// Extension methods for the interface. +/// +public static class MessageExtensions { /// - /// Extension methods for the interface. + /// Converts the specified to an equivalent. /// - public static class MessageExtensions + /// The type of the payload constraint to the interface. + /// The payload to attach within the message. + /// The version of the CloudEvents specification which the event uses. + /// An instance of constraint to the interface. + /// + /// cannot be null. + /// + public static ICloudEvent ToCloudEvent(this IMessage message, string specversion = null) where T : IIntegrationEvent { - /// - /// Converts the specified to an equivalent. - /// - /// The type of the payload constraint to the interface. - /// The payload to attach within the message. - /// The version of the CloudEvents specification which the event uses. - /// An instance of constraint to the interface. - /// - /// cannot be null. - /// - public static ICloudEvent ToCloudEvent(this IMessage message, string specversion = null) where T : IIntegrationEvent - { - Validator.ThrowIfNull(message); - return new CloudEvent(message, specversion); - } + Validator.ThrowIfNull(message); + return new CloudEvent(message, specversion); } } diff --git a/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs b/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs index 16e21f0a..b6e6cb83 100644 --- a/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs +++ b/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs @@ -7,62 +7,61 @@ using Cuemon.Threading; using Savvyio.Messaging; -namespace Savvyio.EventDriven.Messaging +namespace Savvyio.EventDriven.Messaging; + +/// +/// Provides an in-memory implementation of the interface useful for unit testing and the likes thereof. +/// +public class InMemoryEventBus : IPublishSubscribeChannel { + private readonly Channel> _channel = Channel.CreateUnbounded>(); + /// - /// Provides an in-memory implementation of the interface useful for unit testing and the likes thereof. + /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. /// - public class InMemoryEventBus : IPublishSubscribeChannel + /// The to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task PublishAsync(IMessage @event, Action setup = null) { - private readonly Channel> _channel = Channel.CreateUnbounded>(); - - /// - /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - public async Task PublishAsync(IMessage @event, Action setup = null) - { - var options = setup.Configure(); - await _channel.Writer.WriteAsync(@event, options.CancellationToken).ConfigureAwait(false); - } + var options = setup.Configure(); + await _channel.Writer.WriteAsync(@event, options.CancellationToken).ConfigureAwait(false); + } - /// - /// Subscribe to one or more event(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The delegate that will handle the event. - /// The which may be configured. - /// A that represents the asynchronous operation. - public async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + /// + /// Subscribe to one or more event(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The delegate that will handle the event. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + { + var options = setup.Configure(); + await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => WaitToReadAsync(asyncHandler, options.CancellationToken), async () => { - var options = setup.Configure(); - await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => WaitToReadAsync(asyncHandler, options.CancellationToken), async () => + try { - try - { - await WaitToReadAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) - { - // ThrowIfCancellationWasRequested was set to false (default) - } - }); - } + await WaitToReadAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) + { + // ThrowIfCancellationWasRequested was set to false (default) + } + }); + } - private async Task WaitToReadAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken ct) + private async Task WaitToReadAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken ct) + { + var currentSize = Math.Clamp(_channel.Reader.Count, 0, byte.MaxValue); + while (currentSize > 0) { - var currentSize = Math.Clamp(_channel.Reader.Count, 0, byte.MaxValue); - while (currentSize > 0) + for (var i = 0; i < currentSize; i++) { - for (var i = 0; i < currentSize; i++) - { - var message = await _channel.Reader.ReadAsync(ct).ConfigureAwait(false); - if (message == null) { break; } - await asyncHandler.Invoke(message, ct).ConfigureAwait(false); - } - currentSize = _channel.Reader.Count; + var message = await _channel.Reader.ReadAsync(ct).ConfigureAwait(false); + if (message == null) { break; } + await asyncHandler.Invoke(message, ct).ConfigureAwait(false); } + currentSize = _channel.Reader.Count; } } } diff --git a/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs b/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs index 31019e3d..d9abd7e2 100644 --- a/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs @@ -2,36 +2,35 @@ using Cuemon; using Savvyio.Messaging; -namespace Savvyio.EventDriven.Messaging +namespace Savvyio.EventDriven.Messaging; + +/// +/// Extension methods for the interface. +/// +public static class IntegrationEventExtensions { /// - /// Extension methods for the interface. + /// Encloses the specified to an instance of . /// - public static class IntegrationEventExtensions + /// The type of the payload constraint to the interface. + /// The payload to attach within the message. + /// The context that describes the origin of the message. + /// The type that describes the type of related to the originating occurrence. + /// The which may be configured. + /// An instance of constraint to the interface. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + public static IMessage ToMessage(this T @event, Uri source, string type, Action setup = null) where T : IIntegrationEvent { - /// - /// Encloses the specified to an instance of . - /// - /// The type of the payload constraint to the interface. - /// The payload to attach within the message. - /// The context that describes the origin of the message. - /// The type that describes the type of related to the originating occurrence. - /// The which may be configured. - /// An instance of constraint to the interface. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - public static IMessage ToMessage(this T @event, Uri source, string type, Action setup = null) where T : IIntegrationEvent - { - Validator.ThrowIfNull(@event); - Validator.ThrowIfNull(source); - Validator.ThrowIfNullOrWhitespace(type); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - return new Message(options.MessageId, source, type, @event, options.Time); - } + Validator.ThrowIfNull(@event); + Validator.ThrowIfNull(source); + Validator.ThrowIfNullOrWhitespace(type); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + return new Message(options.MessageId, source, type, @event, options.Time); } } diff --git a/src/Savvyio.EventDriven/IntegrationEvent.cs b/src/Savvyio.EventDriven/IntegrationEvent.cs index f0b5e402..8868912b 100644 --- a/src/Savvyio.EventDriven/IntegrationEvent.cs +++ b/src/Savvyio.EventDriven/IntegrationEvent.cs @@ -1,41 +1,40 @@ using System; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Provides a default implementation of of the interface. +/// +/// +/// +public abstract record IntegrationEvent : Request, IIntegrationEvent { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public abstract record IntegrationEvent : Request, IIntegrationEvent + /// The optional identifier of the event. Default is an auto-generated UUID. + /// The optional metadata to merge with this instance. + /// + /// The following table shows the initial metadata values for an instance of . + /// + /// + /// Key + /// Initial Value + /// + /// + /// + /// eventId ?? Guid.NewGuid().ToString("N") + /// + /// + /// + /// DateTime.UtcNow + /// + /// + /// + protected IntegrationEvent(string eventId = null, IMetadata metadata = null) { - /// - /// Initializes a new instance of the class. - /// - /// The optional identifier of the event. Default is an auto-generated UUID. - /// The optional metadata to merge with this instance. - /// - /// The following table shows the initial metadata values for an instance of . - /// - /// - /// Key - /// Initial Value - /// - /// - /// - /// eventId ?? Guid.NewGuid().ToString("N") - /// - /// - /// - /// DateTime.UtcNow - /// - /// - /// - protected IntegrationEvent(string eventId = null, IMetadata metadata = null) - { - this.SetEventId(eventId ?? Guid.NewGuid().ToString("N")); - this.SetTimestamp(); - this.MergeMetadata(metadata); - } + this.SetEventId(eventId ?? Guid.NewGuid().ToString("N")); + this.SetTimestamp(); + this.MergeMetadata(metadata); } } diff --git a/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs b/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs index 0d8b2ae1..22929bb2 100644 --- a/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs +++ b/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs @@ -4,43 +4,42 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Provides a default implementation of of the interface. +/// +/// +/// +public class IntegrationEventDispatcher : FireForgetDispatcher, IIntegrationEventDispatcher { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public class IntegrationEventDispatcher : FireForgetDispatcher, IIntegrationEventDispatcher + /// The provider of service implementations. + public IntegrationEventDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - public IntegrationEventDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Publishes the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - public void Publish(IIntegrationEvent request) - { - Validator.ThrowIfNull(request); - Dispatch(request, handler => handler.Delegates); - } + /// + /// Publishes the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to publish. + public void Publish(IIntegrationEvent request) + { + Validator.ThrowIfNull(request); + Dispatch(request, handler => handler.Delegates); + } - /// - /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task PublishAsync(IIntegrationEvent request, Action setup = null) - { - Validator.ThrowIfNull(request); - return DispatchAsync(request, handler => handler.Delegates, setup); - } + /// + /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task PublishAsync(IIntegrationEvent request, Action setup = null) + { + Validator.ThrowIfNull(request); + return DispatchAsync(request, handler => handler.Delegates, setup); } } diff --git a/src/Savvyio.EventDriven/IntegrationEventExtensions.cs b/src/Savvyio.EventDriven/IntegrationEventExtensions.cs index 780f57d1..eaf9d0de 100644 --- a/src/Savvyio.EventDriven/IntegrationEventExtensions.cs +++ b/src/Savvyio.EventDriven/IntegrationEventExtensions.cs @@ -1,44 +1,43 @@ using System; using Cuemon.Extensions; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Extension methods for the interface. +/// +public static class IntegrationEventExtensions { /// - /// Extension methods for the interface. + /// Gets the string representation of the event identifier from the . /// - public static class IntegrationEventExtensions + /// The model that implements the interface. + /// The to extend. + /// The string representation of the event identifier from the . + public static string GetEventId(this T request) where T : IIntegrationEvent { - /// - /// Gets the string representation of the event identifier from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the event identifier from the . - public static string GetEventId(this T request) where T : IIntegrationEvent - { - return MetadataFactory.Get(request, MetadataDictionary.EventId).As(); - } + return MetadataFactory.Get(request, MetadataDictionary.EventId).As(); + } - /// - /// Gets the value of the timestamp from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The value of the timestamp from the . - public static DateTime GetTimestamp(this T request) where T : IIntegrationEvent - { - return MetadataFactory.Get(request, MetadataDictionary.Timestamp).As(); - } + /// + /// Gets the value of the timestamp from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The value of the timestamp from the . + public static DateTime GetTimestamp(this T request) where T : IIntegrationEvent + { + return MetadataFactory.Get(request, MetadataDictionary.Timestamp).As(); + } - /// - /// Gets the string representation of the type from the . - /// - /// The model that implements the interface. - /// The to extend. - /// The string representation of the type from the . - public static string GetMemberType(this T request) where T : IIntegrationEvent - { - return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); - } + /// + /// Gets the string representation of the type from the . + /// + /// The model that implements the interface. + /// The to extend. + /// The string representation of the type from the . + public static string GetMemberType(this T request) where T : IIntegrationEvent + { + return MetadataFactory.Get(request, MetadataDictionary.MemberType).As(); } } diff --git a/src/Savvyio.EventDriven/IntegrationEventHandler.cs b/src/Savvyio.EventDriven/IntegrationEventHandler.cs index 87223947..55501a9c 100644 --- a/src/Savvyio.EventDriven/IntegrationEventHandler.cs +++ b/src/Savvyio.EventDriven/IntegrationEventHandler.cs @@ -1,31 +1,30 @@ using Savvyio.Handlers; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Provides a generic and consistent way of handling Integration Event objects that implements the interface. This is an abstract class. +/// +/// +public abstract class IntegrationEventHandler : IIntegrationEventHandler { /// - /// Provides a generic and consistent way of handling Integration Event objects that implements the interface. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class IntegrationEventHandler : IIntegrationEventHandler + protected IntegrationEventHandler() { - /// - /// Initializes a new instance of the class. - /// - protected IntegrationEventHandler() - { - Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); - } + Delegates = HandlerFactory.CreateFireForget(RegisterDelegates); + } - /// - /// Registers the delegates responsible of handling types that implements the interface. - /// - /// The registry that store the delegates of type . - protected abstract void RegisterDelegates(IFireForgetRegistry handlers); + /// + /// Registers the delegates responsible of handling types that implements the interface. + /// + /// The registry that store the delegates of type . + protected abstract void RegisterDelegates(IFireForgetRegistry handlers); - /// - /// Gets the activator responsible of invoking delegates that handles . - /// - /// The activator responsible of invoking delegates that handles . - public IFireForgetActivator Delegates { get; } - } + /// + /// Gets the activator responsible of invoking delegates that handles . + /// + /// The activator responsible of invoking delegates that handles . + public IFireForgetActivator Delegates { get; } } diff --git a/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs b/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs index af7b4d92..ebc7f557 100644 --- a/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs @@ -1,30 +1,29 @@ -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds an implementation of the interface to (if not already registered). /// - public static class SavvyioOptionsExtensions + /// The type that implements the interface. + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddIntegrationEventHandler(this SavvyioOptions options) where TImplementation : class, IIntegrationEventHandler { - /// - /// Adds an implementation of the interface to (if not already registered). - /// - /// The type that implements the interface. - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddIntegrationEventHandler(this SavvyioOptions options) where TImplementation : class, IIntegrationEventHandler - { - options.AddHandler(); - return options; - } + options.AddHandler(); + return options; + } - /// - /// Adds a default implementation of the interface. - /// - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddIntegrationEventDispatcher(this SavvyioOptions options) - { - return options.AddDispatcher(); - } + /// + /// Adds a default implementation of the interface. + /// + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddIntegrationEventDispatcher(this SavvyioOptions options) + { + return options.AddDispatcher(); } } diff --git a/src/Savvyio.Extensions.Dapper/DapperDataSource.cs b/src/Savvyio.Extensions.Dapper/DapperDataSource.cs index 0ed92766..88a72422 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataSource.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataSource.cs @@ -2,122 +2,121 @@ using System.Data; using Cuemon; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +/// +/// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Dapper. +/// +/// +/// +public class DapperDataSource : Disposable, IDapperDataSource { + private readonly IDbConnection _dbConnection; + /// - /// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Dapper. + /// Initializes a new instance of the class. /// - /// - /// - public class DapperDataSource : Disposable, IDapperDataSource + /// The used to configure this instance. + /// + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public DapperDataSource(DapperDataSourceOptions options) { - private readonly IDbConnection _dbConnection; - - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - /// - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public DapperDataSource(DapperDataSourceOptions options) - { - Validator.ThrowIfInvalidOptions(options); - _dbConnection = options.ConnectionFactory.Invoke(); - _dbConnection.Open(); - } + Validator.ThrowIfInvalidOptions(options); + _dbConnection = options.ConnectionFactory.Invoke(); + _dbConnection.Open(); + } - /// - /// Called when this object is being disposed by either or having disposing set to true and is false. - /// - protected override void OnDisposeManagedResources() - { - _dbConnection?.Close(); - _dbConnection?.Dispose(); - } + /// + /// Called when this object is being disposed by either or having disposing set to true and is false. + /// + protected override void OnDisposeManagedResources() + { + _dbConnection?.Close(); + _dbConnection?.Dispose(); + } - /// - /// Begins a database transaction. - /// - /// An object representing the new transaction. - public IDbTransaction BeginTransaction() - { - return _dbConnection.BeginTransaction(); - } + /// + /// Begins a database transaction. + /// + /// An object representing the new transaction. + public IDbTransaction BeginTransaction() + { + return _dbConnection.BeginTransaction(); + } - /// - /// Begins a database transaction. - /// - /// One of the values. - /// An object representing the new transaction. - public IDbTransaction BeginTransaction(IsolationLevel il) - { - return _dbConnection.BeginTransaction(il); - } + /// + /// Begins a database transaction. + /// + /// One of the values. + /// An object representing the new transaction. + public IDbTransaction BeginTransaction(IsolationLevel il) + { + return _dbConnection.BeginTransaction(il); + } - /// - /// Changes the current database for an open object. - /// - /// The name of the database to use in place of the current database. - public void ChangeDatabase(string databaseName) - { - _dbConnection.ChangeDatabase(databaseName); - } + /// + /// Changes the current database for an open object. + /// + /// The name of the database to use in place of the current database. + public void ChangeDatabase(string databaseName) + { + _dbConnection.ChangeDatabase(databaseName); + } - /// - /// Closes the connection to the database. - /// - public void Close() - { - _dbConnection.Close(); - } + /// + /// Closes the connection to the database. + /// + public void Close() + { + _dbConnection.Close(); + } - /// - /// Creates and returns a Command object associated with the connection. - /// - /// A Command object associated with the connection. - public IDbCommand CreateCommand() - { - return _dbConnection.CreateCommand(); - } + /// + /// Creates and returns a Command object associated with the connection. + /// + /// A Command object associated with the connection. + public IDbCommand CreateCommand() + { + return _dbConnection.CreateCommand(); + } - /// - /// Opens a database connection with the settings specified by the property of the provider-specific Connection object. - /// - public void Open() - { - _dbConnection.Open(); - } + /// + /// Opens a database connection with the settings specified by the property of the provider-specific Connection object. + /// + public void Open() + { + _dbConnection.Open(); + } - /// - /// Gets or sets the string used to open a database. - /// - /// A string containing connection settings. - public string ConnectionString - { - get => _dbConnection.ConnectionString; - set => _dbConnection.ConnectionString = value; - } + /// + /// Gets or sets the string used to open a database. + /// + /// A string containing connection settings. + public string ConnectionString + { + get => _dbConnection.ConnectionString; + set => _dbConnection.ConnectionString = value; + } - /// - /// Gets the time to wait (in seconds) while trying to establish a connection before terminating the attempt and generating an error. - /// - /// The time (in seconds) to wait for a connection to open. The default value is 15 seconds. - public int ConnectionTimeout => _dbConnection.ConnectionTimeout; + /// + /// Gets the time to wait (in seconds) while trying to establish a connection before terminating the attempt and generating an error. + /// + /// The time (in seconds) to wait for a connection to open. The default value is 15 seconds. + public int ConnectionTimeout => _dbConnection.ConnectionTimeout; - /// - /// Gets the name of the current database or the database to be used after a connection is opened. - /// - /// The name of the current database or the name of the database to be used once a connection is open. The default value is an empty string. - public string Database => _dbConnection.Database; + /// + /// Gets the name of the current database or the database to be used after a connection is opened. + /// + /// The name of the current database or the name of the database to be used once a connection is open. The default value is an empty string. + public string Database => _dbConnection.Database; - /// - /// Gets the current state of the connection. - /// - /// One of the values. - public ConnectionState State => _dbConnection.State; - } + /// + /// Gets the current state of the connection. + /// + /// One of the values. + public ConnectionState State => _dbConnection.State; } diff --git a/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs b/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs index e047105c..5eb97a2e 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs @@ -3,36 +3,35 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +/// +/// Configuration options for . +/// +public class DapperDataSourceOptions : IValidatableParameterObject { /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - public class DapperDataSourceOptions : IValidatableParameterObject + public DapperDataSourceOptions() { - /// - /// Initializes a new instance of the class. - /// - public DapperDataSourceOptions() - { - } + } - /// - /// Gets or sets the function delegate that provides the . - /// - /// The function delegate that provides the . - public Func ConnectionFactory { get; set; } + /// + /// Gets or sets the function delegate that provides the . + /// + /// The function delegate that provides the . + public Func ConnectionFactory { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// - /// cannot be null. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(ConnectionFactory == null); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// + /// cannot be null. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(ConnectionFactory == null); } } diff --git a/src/Savvyio.Extensions.Dapper/DapperDataStore.cs b/src/Savvyio.Extensions.Dapper/DapperDataStore.cs index 353130d3..28f787f8 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataStore.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataStore.cs @@ -5,79 +5,78 @@ using Cuemon.Threading; using Savvyio.Data; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +/// +/// Represents the base class from which all implementations of should derive. This is an abstract class to serve as an abstraction layer before the actual I/O communication with a source of data using Dapper. +/// +/// The type of the DTO. +/// The type of options associated with this DTO. +/// +/// +public abstract class DapperDataStore : Disposable, IPersistentDataStore + where T : class + where TOptions : AsyncOptions, new() { /// - /// Represents the base class from which all implementations of should derive. This is an abstract class to serve as an abstraction layer before the actual I/O communication with a source of data using Dapper. + /// Initializes a new instance of the class. /// - /// The type of the DTO. - /// The type of options associated with this DTO. - /// - /// - public abstract class DapperDataStore : Disposable, IPersistentDataStore - where T : class - where TOptions : AsyncOptions, new() + /// The that handles actual I/O communication with a source of data. + protected DapperDataStore(IDapperDataSource source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - protected DapperDataStore(IDapperDataSource source) - { - Source = source; - } + Source = source; + } - /// - /// Gets the that handles actual I/O communication with a source of data. - /// - /// The that handles actual I/O communication with a source of data. - protected IDapperDataSource Source { get; } + /// + /// Gets the that handles actual I/O communication with a source of data. + /// + /// The that handles actual I/O communication with a source of data. + protected IDapperDataSource Source { get; } - /// - /// Creates the specified asynchronous in the associated . - /// - /// The object to create in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public abstract Task CreateAsync(T dto, Action setup = null); + /// + /// Creates the specified asynchronous in the associated . + /// + /// The object to create in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public abstract Task CreateAsync(T dto, Action setup = null); - /// - /// Updates the specified asynchronous in the associated . - /// - /// The object to update in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public abstract Task UpdateAsync(T dto, Action setup = null); + /// + /// Updates the specified asynchronous in the associated . + /// + /// The object to update in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public abstract Task UpdateAsync(T dto, Action setup = null); - /// - /// Loads the object from the specified asynchronous. - /// - /// The key that uniquely identifies the object. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. - public abstract Task GetByIdAsync(object id, Action setup = null); + /// + /// Loads the object from the specified asynchronous. + /// + /// The key that uniquely identifies the object. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. + public abstract Task GetByIdAsync(object id, Action setup = null); - /// - /// Finds all objects matching the specified asynchronous in the associated . - /// - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. - public abstract Task> FindAllAsync(Action setup = null); + /// + /// Finds all objects matching the specified asynchronous in the associated . + /// + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. + public abstract Task> FindAllAsync(Action setup = null); - /// - /// Deletes the specified asynchronous in the associated . - /// - /// The object to delete in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public abstract Task DeleteAsync(T dto, Action setup = null); + /// + /// Deletes the specified asynchronous in the associated . + /// + /// The object to delete in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public abstract Task DeleteAsync(T dto, Action setup = null); - /// - /// Called when this object is being disposed by either or having disposing set to true and is false. - /// - protected override void OnDisposeManagedResources() - { - Source?.Dispose(); - } + /// + /// Called when this object is being disposed by either or having disposing set to true and is false. + /// + protected override void OnDisposeManagedResources() + { + Source?.Dispose(); } } diff --git a/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs b/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs index 36164e08..79a62683 100644 --- a/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs +++ b/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs @@ -3,94 +3,93 @@ using Cuemon.Threading; using Dapper; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +/// +/// Specifies options that is related to . +/// +/// +public class DapperQueryOptions : AsyncOptions { /// - /// Specifies options that is related to . + /// Performs an implicit conversion from to . /// - /// - public class DapperQueryOptions : AsyncOptions + /// The to convert. + /// A that is equivalent to . + public static implicit operator CommandDefinition(DapperQueryOptions value) { - /// - /// Performs an implicit conversion from to . - /// - /// The to convert. - /// A that is equivalent to . - public static implicit operator CommandDefinition(DapperQueryOptions value) - { - return new CommandDefinition(value.CommandText, commandTimeout: (int)value.CommandTimeout.TotalSeconds, cancellationToken: value.CancellationToken, flags: value.CommandFlags, commandType: value.CommandType, transaction: value.Transaction, parameters: value.Parameters); - } + return new CommandDefinition(value.CommandText, commandTimeout: (int)value.CommandTimeout.TotalSeconds, cancellationToken: value.CancellationToken, flags: value.CommandFlags, commandType: value.CommandType, transaction: value.Transaction, parameters: value.Parameters); + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// default - /// - /// - /// - /// TimeSpan.FromSeconds(30) - /// - /// - /// - /// CommandFlags.Buffered - /// - /// - /// - /// CommandType.Text - /// - /// - /// - public DapperQueryOptions() - { - CommandTimeout = TimeSpan.FromSeconds(30); - CommandFlags = CommandFlags.Buffered; - CommandType = CommandType.Text; - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// default + /// + /// + /// + /// TimeSpan.FromSeconds(30) + /// + /// + /// + /// CommandFlags.Buffered + /// + /// + /// + /// CommandType.Text + /// + /// + /// + public DapperQueryOptions() + { + CommandTimeout = TimeSpan.FromSeconds(30); + CommandFlags = CommandFlags.Buffered; + CommandType = CommandType.Text; + } - /// - /// Gets or sets the parameters associated with the command. - /// - /// The parameters associated with the command. - /// This is typically the DTO. - public object Parameters { get; set; } + /// + /// Gets or sets the parameters associated with the command. + /// + /// The parameters associated with the command. + /// This is typically the DTO. + public object Parameters { get; set; } - /// - /// Gets or sets the command (sql or a stored-procedure name) to execute. - /// - /// The command (sql or a stored-procedure name) to execute. - public string CommandText { get; set; } + /// + /// Gets or sets the command (sql or a stored-procedure name) to execute. + /// + /// The command (sql or a stored-procedure name) to execute. + public string CommandText { get; set; } - /// - /// Gets or sets the timeout for the command. - /// - /// The timeout for the command. - public TimeSpan CommandTimeout { get; set; } + /// + /// Gets or sets the timeout for the command. + /// + /// The timeout for the command. + public TimeSpan CommandTimeout { get; set; } - /// - /// Gets or sets the state flags against the command. - /// - /// The state flags against the command. - public CommandFlags CommandFlags { get; set; } + /// + /// Gets or sets the state flags against the command. + /// + /// The state flags against the command. + public CommandFlags CommandFlags { get; set; } - /// - /// Gets or sets the type of command that the command-text represents. - /// - /// The type of command that the command-text represents. - public CommandType CommandType { get; set; } + /// + /// Gets or sets the type of command that the command-text represents. + /// + /// The type of command that the command-text represents. + public CommandType CommandType { get; set; } - /// - /// Gets or sets the active transaction for the command. - /// - /// The active transaction for the command. - public IDbTransaction Transaction { get; set; } - } + /// + /// Gets or sets the active transaction for the command. + /// + /// The active transaction for the command. + public IDbTransaction Transaction { get; set; } } diff --git a/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs b/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs index 9bad4c02..a3283be5 100644 --- a/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs +++ b/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs @@ -1,12 +1,11 @@ using System.Data; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +/// +/// Defines a generic way to support the actual I/O communication with a source of data - tailored to Dapper. +/// +/// +public interface IDapperDataSource : IDataSource, IDbConnection { - /// - /// Defines a generic way to support the actual I/O communication with a source of data - tailored to Dapper. - /// - /// - public interface IDapperDataSource : IDataSource, IDbConnection - { - } } diff --git a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs index 70a8ce93..37f164d1 100644 --- a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs +++ b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs @@ -6,77 +6,76 @@ using DapperExtensions; using Savvyio.Extensions.Dapper; -namespace Savvyio.Extensions.DapperExtensions +namespace Savvyio.Extensions.DapperExtensions; + +/// +/// Provides a default implementation of the class that is tailored for Plain Old CLR Objects (POCO) usage by DapperExtensions. +/// +/// The type of the DTO. +/// +public class DapperExtensionsDataStore : DapperDataStore> where T : class { /// - /// Provides a default implementation of the class that is tailored for Plain Old CLR Objects (POCO) usage by DapperExtensions. + /// Initializes a new instance of the class. /// - /// The type of the DTO. - /// - public class DapperExtensionsDataStore : DapperDataStore> where T : class + /// The that handles actual I/O communication with a source of data. + public DapperExtensionsDataStore(IDapperDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public DapperExtensionsDataStore(IDapperDataSource source) : base(source) - { - } + } - /// - /// Creates the specified asynchronous in the associated . - /// - /// The object to create in the associated . - /// The that needs to be configured. - /// A that represents the asynchronous operation. - public override Task CreateAsync(T dto, Action setup = null) - { - return Source.InsertAsync(dto); + /// + /// Creates the specified asynchronous in the associated . + /// + /// The object to create in the associated . + /// The that needs to be configured. + /// A that represents the asynchronous operation. + public override Task CreateAsync(T dto, Action setup = null) + { + return Source.InsertAsync(dto); - } + } - /// - /// Deletes the specified asynchronous in the associated . - /// - /// The object to delete in the associated . - /// The that needs to be configured. - /// A that represents the asynchronous operation. - public override Task DeleteAsync(T dto, Action setup = null) - { - return Source.DeleteAsync(dto); - } + /// + /// Deletes the specified asynchronous in the associated . + /// + /// The object to delete in the associated . + /// The that needs to be configured. + /// A that represents the asynchronous operation. + public override Task DeleteAsync(T dto, Action setup = null) + { + return Source.DeleteAsync(dto); + } - /// - /// Loads the object from the specified asynchronous. - /// - /// The key that uniquely identifies the object. - /// The that needs to be configured. - /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. - public override Task GetByIdAsync(object id, Action setup = null) - { - return Source.GetAsync(id); - } + /// + /// Loads the object from the specified asynchronous. + /// + /// The key that uniquely identifies the object. + /// The that needs to be configured. + /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. + public override Task GetByIdAsync(object id, Action setup = null) + { + return Source.GetAsync(id); + } - /// - /// Finds all objects matching the specified asynchronous in the associated . - /// - /// The that needs to be configured. - /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. - public override Task> FindAllAsync(Action> setup = null) - { - var options = setup.Configure(); - return options.Predicate == null ? Source.GetListAsync() : Source.GetListAsync(Predicates.Field(options.Predicate, options.Op, options.Value, options.Not, options.UseColumnPrefix, options.Function, options.FunctionParameters)); - } + /// + /// Finds all objects matching the specified asynchronous in the associated . + /// + /// The that needs to be configured. + /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. + public override Task> FindAllAsync(Action> setup = null) + { + var options = setup.Configure(); + return options.Predicate == null ? Source.GetListAsync() : Source.GetListAsync(Predicates.Field(options.Predicate, options.Op, options.Value, options.Not, options.UseColumnPrefix, options.Function, options.FunctionParameters)); + } - /// - /// Updates the specified asynchronous in the associated . - /// - /// The object to update in the associated . - /// The that needs to be configured. - /// A that represents the asynchronous operation. - public override Task UpdateAsync(T dto, Action setup = null) - { - return Source.UpdateAsync(dto); - } + /// + /// Updates the specified asynchronous in the associated . + /// + /// The object to update in the associated . + /// The that needs to be configured. + /// A that represents the asynchronous operation. + public override Task UpdateAsync(T dto, Action setup = null) + { + return Source.UpdateAsync(dto); } } diff --git a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs index 7d0dfa4f..ce41fe30 100644 --- a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs +++ b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs @@ -4,106 +4,105 @@ using DapperExtensions; using DapperExtensions.Predicate; -namespace Savvyio.Extensions.DapperExtensions +namespace Savvyio.Extensions.DapperExtensions; + +/// +/// Specifies options that is related to . +/// +/// +public class DapperExtensionsQueryOptions : AsyncOptions { /// - /// Specifies options that is related to . + /// Initializes a new instance of the class. /// - /// - public class DapperExtensionsQueryOptions : AsyncOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// null + /// + /// + /// + /// + /// + /// + /// + /// null + /// + /// + /// + /// false + /// + /// + /// + /// true + /// + /// + /// + /// + /// + /// + /// + /// null + /// + /// + /// + /// default + /// + /// + /// + public DapperExtensionsQueryOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// null - /// - /// - /// - /// - /// - /// - /// - /// null - /// - /// - /// - /// false - /// - /// - /// - /// true - /// - /// - /// - /// - /// - /// - /// - /// null - /// - /// - /// - /// default - /// - /// - /// - public DapperExtensionsQueryOptions() - { - Op = Operator.Eq; - Not = false; - UseColumnPrefix = true; - Function = DatabaseFunction.None; - } + Op = Operator.Eq; + Not = false; + UseColumnPrefix = true; + Function = DatabaseFunction.None; + } - /// - /// Gets or sets the predicate of the . - /// - /// The predicate of the .. - public Expression> Predicate { get; set; } + /// + /// Gets or sets the predicate of the . + /// + /// The predicate of the .. + public Expression> Predicate { get; set; } - /// - /// Gets or sets the comparison operator of the . - /// - /// The comparison operator of the . - public Operator Op { get; set; } + /// + /// Gets or sets the comparison operator of the . + /// + /// The comparison operator of the . + public Operator Op { get; set; } - /// - /// Gets or sets the value of the . - /// - /// The value of the . - public object Value { get; set; } + /// + /// Gets or sets the value of the . + /// + /// The value of the . + public object Value { get; set; } - /// - /// Gets or sets a value that inverts the comparision operator of the . - /// - /// true to invert the value of ; otherwise, false. - public bool Not { get; set; } + /// + /// Gets or sets a value that inverts the comparision operator of the . + /// + /// true to invert the value of ; otherwise, false. + public bool Not { get; set; } - /// - /// Gets or sets a value indicating whether generated SQL should have column prefix of the . - /// - /// true if to include column prefix on generated SQL; otherwise, false. - public bool UseColumnPrefix { get; set; } + /// + /// Gets or sets a value indicating whether generated SQL should have column prefix of the . + /// + /// true if to include column prefix on generated SQL; otherwise, false. + public bool UseColumnPrefix { get; set; } - /// - /// Gets or sets the database function of the . - /// - /// The database function of the . - public DatabaseFunction Function { get; set; } + /// + /// Gets or sets the database function of the . + /// + /// The database function of the . + public DatabaseFunction Function { get; set; } - /// - /// Gets or sets the parameters to the of the . - /// - /// The parameters to the of the . - public string FunctionParameters { get; set; } - } + /// + /// Gets or sets the parameters to the of the . + /// + /// The parameters to the of the . + public string FunctionParameters { get; set; } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs index 22e103e4..b04f4abe 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs @@ -1,28 +1,27 @@ using System; using Savvyio.Extensions.Dapper; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +/// +/// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Dapper. +/// +/// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class DapperDataSource : DapperDataSource, IDapperDataSource { /// - /// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Dapper. + /// Initializes a new instance of the class. /// - /// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class DapperDataSource : DapperDataSource, IDapperDataSource + /// The used to configure this instance. + /// + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public DapperDataSource(DapperDataSourceOptions options) : base(options) { - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - /// - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public DapperDataSource(DapperDataSourceOptions options) : base(options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs index 79edb7df..c3c978be 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.Dapper; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +/// +/// Configuration options for . +/// +/// +/// +public class DapperDataSourceOptions : DapperDataSourceOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class DapperDataSourceOptions : DapperDataSourceOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs index 4851f58d..8720d7d9 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs @@ -1,14 +1,13 @@ using Savvyio.Extensions.Dapper; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +/// +/// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data optimized for Dapper. +/// +/// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IDapperDataSource : IDapperDataSource, IDataSource { - /// - /// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data optimized for Dapper. - /// - /// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IDapperDataSource : IDapperDataSource, IDataSource - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs index 853d00b3..15a1528e 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs @@ -5,87 +5,86 @@ using Savvyio.Extensions.Dapper; using Savvyio.Extensions.DependencyInjection.Data; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) { - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddDapperDataSource(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + Validator.ThrowIfNull(services); + return services + .AddDapperDataSource(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddDapperDataSource>(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddDapperDataSource>(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the interface to add. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action setup = null) where TService : class, IDapperDataSource - { - Validator.ThrowIfNull(services); - return services.AddDataSource(setup); - } + /// + /// Adds an implementation of to the specified . + /// + /// The type of the interface to add. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperDataSource(this IServiceCollection services, Action setup = null) where TService : class, IDapperDataSource + { + Validator.ThrowIfNull(services); + return services.AddDataSource(setup); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the abstraction to add. - /// The type of the DTO to use. - /// The to add the service to. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperDataStore(this IServiceCollection services) - where TService : DapperDataStore - where T : class - { - Validator.ThrowIfNull(services); - return services.AddDataStore(); - } + /// + /// Adds an implementation of to the specified . + /// + /// The type of the abstraction to add. + /// The type of the DTO to use. + /// The to add the service to. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperDataStore(this IServiceCollection services) + where TService : DapperDataStore + where T : class + { + Validator.ThrowIfNull(services); + return services.AddDataStore(); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs index 5fb8e1ee..53234550 100644 --- a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs @@ -3,23 +3,22 @@ using Savvyio.Extensions.DependencyInjection.Dapper; using Savvyio.Extensions.DependencyInjection.Data; -namespace Savvyio.Extensions.DependencyInjection.DapperExtensions +namespace Savvyio.Extensions.DependencyInjection.DapperExtensions; + +/// +/// Provides a default implementation of the interface to support multiple implementations that is tailored for Plain Old CLR Objects (POCO) usage by DapperExtensions. +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class DapperExtensionsDataStore : DapperExtensionsDataStore, IPersistentDataStore, TMarker> where T : class { /// - /// Provides a default implementation of the interface to support multiple implementations that is tailored for Plain Old CLR Objects (POCO) usage by DapperExtensions. + /// Initializes a new instance of the class. /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class DapperExtensionsDataStore : DapperExtensionsDataStore, IPersistentDataStore, TMarker> where T : class + /// The that handles actual I/O communication with a source of data. + public DapperExtensionsDataStore(IDapperDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public DapperExtensionsDataStore(IDapperDataSource source) : base(source) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs index 59bb291f..185a4b28 100644 --- a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs @@ -4,42 +4,41 @@ using Savvyio.Extensions.DapperExtensions; using Savvyio.Extensions.DependencyInjection.Data; -namespace Savvyio.Extensions.DependencyInjection.DapperExtensions +namespace Savvyio.Extensions.DependencyInjection.DapperExtensions; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the DTO to use. + /// The to add the service to. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperExtensionsDataStore(this IServiceCollection services) where T : class { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the DTO to use. - /// The to add the service to. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperExtensionsDataStore(this IServiceCollection services) where T : class - { - Validator.ThrowIfNull(services); - return services.AddDataStore, T, DapperExtensionsQueryOptions>(); - } + Validator.ThrowIfNull(services); + return services.AddDataStore, T, DapperExtensionsQueryOptions>(); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the DTO to use. - /// The type used to mark the implementation that this data access object represents. Optimized for DapperExtensions. - /// The to add the service to. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddDapperExtensionsDataStore(this IServiceCollection services) where T : class - { - Validator.ThrowIfNull(services); - return services.AddDataStore, T, DapperExtensionsQueryOptions>(); - } + /// + /// Adds an implementation of to the specified . + /// + /// The type of the DTO to use. + /// The type used to mark the implementation that this data access object represents. Optimized for DapperExtensions. + /// The to add the service to. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddDapperExtensionsDataStore(this IServiceCollection services) where T : class + { + Validator.ThrowIfNull(services); + return services.AddDataStore, T, DapperExtensionsQueryOptions>(); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs index 25fceb42..8f672698 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs @@ -1,17 +1,16 @@ using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.DependencyInjection.Domain.EventSourcing +namespace Savvyio.Extensions.DependencyInjection.Domain.EventSourcing; + +/// +/// Defines a generic way to support multiple implementations traced read- and writable repositories (CRud) that is optimized for Domain Driven Design. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +public interface ITracedAggregateRepository : ITracedAggregateRepository, IReadableRepository, IWritableRepository where TEntity : class, ITracedAggregateRoot { - /// - /// Defines a generic way to support multiple implementations traced read- and writable repositories (CRud) that is optimized for Domain Driven Design. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - public interface ITracedAggregateRepository : ITracedAggregateRepository, IReadableRepository, IWritableRepository where TEntity : class, ITracedAggregateRoot - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs index 47c0ca94..8b7b5dba 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs @@ -6,41 +6,40 @@ using Savvyio.Domain; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.DependencyInjection.Domain.EventSourcing +namespace Savvyio.Extensions.DependencyInjection.Domain.EventSourcing; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the interface to add. + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddTracedAggregateRepository(this IServiceCollection services, Action setup = null) + where TService : class, ITracedAggregateRepository + where TEntity : class, ITracedAggregateRoot { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the interface to add. - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddTracedAggregateRepository(this IServiceCollection services, Action setup = null) - where TService : class, ITracedAggregateRepository - where TEntity : class, ITracedAggregateRoot + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(ITracedAggregateRepository<,>), typeof(IWritableRepository<,>), typeof(IReadableRepository<,>)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(ITracedAggregateRepository<,>), typeof(IWritableRepository<,>), typeof(IReadableRepository<,>)); + }); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs index 2c33f6b9..b6af4440 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs @@ -1,16 +1,15 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of persistent repositories (CRUD) that is optimized for Domain Driven Design. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IAggregateRepository : IAggregateRepository, IPersistentRepository where TEntity : class, IAggregateRoot { - /// - /// Defines a generic way to support multiple implementations of persistent repositories (CRUD) that is optimized for Domain Driven Design. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IAggregateRepository : IAggregateRepository, IPersistentRepository where TEntity : class, IAggregateRoot - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs index c4ba05d1..27acd258 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs @@ -5,42 +5,41 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the to add. + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddAggregateRepository(this IServiceCollection services, Action setup = null) + where TService : class, IAggregateRepository + where TEntity : class, IAggregateRoot { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddAggregateRepository(this IServiceCollection services, Action setup = null) - where TService : class, IAggregateRepository - where TEntity : class, IAggregateRoot + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IAggregateRepository<,>)); - }).AddRepository(setup); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IAggregateRepository<,>)); + }).AddRepository(setup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs index 3680ffa6..e663a944 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs @@ -3,27 +3,26 @@ using Savvyio.Extensions.DependencyInjection.Domain.EventSourcing; using Savvyio.Extensions.EFCore.Domain.EventSourcing; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design and Event Sourcing. +/// +/// The type of the entity that implements the interface. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +public class EfCoreTracedAggregateRepository : EfCoreTracedAggregateRepository, ITracedAggregateRepository + where TEntity : class, ITracedAggregateRoot { /// - /// Provides an implementation of the that is optimized for Domain Driven Design and Event Sourcing. + /// Initializes a new instance of the class. /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - public class EfCoreTracedAggregateRepository : EfCoreTracedAggregateRepository, ITracedAggregateRepository - where TEntity : class, ITracedAggregateRoot + /// The that handles actual I/O communication with a source of data. + /// The that is used when converting between and arbitrary data. + public EfCoreTracedAggregateRepository(IEfCoreDataSource source, IMarshaller marshaller) : base(source, marshaller) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - /// The that is used when converting between and arbitrary data. - public EfCoreTracedAggregateRepository(IEfCoreDataSource source, IMarshaller marshaller) : base(source, marshaller) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs index 92871961..cf1bd1ac 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs @@ -7,50 +7,49 @@ using Savvyio.Extensions.EFCore.Domain; using Savvyio.Extensions.EFCore.Domain.EventSourcing; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreTracedAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, ITracedAggregateRoot { - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreTracedAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, ITracedAggregateRoot - { - Validator.ThrowIfNull(services); - return services.AddTracedAggregateRepository, TEntity, TKey>(setup); - } + Validator.ThrowIfNull(services); + return services.AddTracedAggregateRepository, TEntity, TKey>(setup); + } - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreTracedAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, ITracedAggregateRoot - { - Validator.ThrowIfNull(services); - return services.AddTracedAggregateRepository, TEntity, TKey>(setup); - } + /// + /// Adds an to the specified . + /// + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreTracedAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, ITracedAggregateRoot + { + Validator.ThrowIfNull(services); + return services.AddTracedAggregateRepository, TEntity, TKey>(setup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs index f8c901f0..deea5c38 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs @@ -2,21 +2,20 @@ using Savvyio.Extensions.EFCore; using Savvyio.Extensions.EFCore.Domain; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design and the concept of Aggregate Root. +/// +/// +public class EfCoreAggregateDataSource : EfCoreAggregateDataSource, IEfCoreDataSource { /// - /// Provides an implementation of the that is optimized for Domain Driven Design and the concept of Aggregate Root. + /// Initializes a new instance of the class. /// - /// - public class EfCoreAggregateDataSource : EfCoreAggregateDataSource, IEfCoreDataSource + /// The that are responsible for raising domain events. + /// The used to configure this instance. + public EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options) : base(dispatcher, new EfCoreDbContext(options)) { - /// - /// Initializes a new instance of the class. - /// - /// The that are responsible for raising domain events. - /// The used to configure this instance. - public EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options) : base(dispatcher, new EfCoreDbContext(options)) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs index 3e621298..df255d64 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs @@ -2,24 +2,23 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreAggregateRepository : EfCoreRepository, IAggregateRepository where TEntity : class, IAggregateRoot { /// - /// Provides an implementation of the that is optimized for Domain Driven Design. + /// Initializes a new instance of the class. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreAggregateRepository : EfCoreRepository, IAggregateRepository where TEntity : class, IAggregateRoot + /// The that handles actual I/O communication with a source of data. + public EfCoreAggregateRepository(IEfCoreDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreAggregateRepository(IEfCoreDataSource source) : base(source) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs index d7b37061..09f7b7fa 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs @@ -7,88 +7,87 @@ using Savvyio.Extensions.EFCore; using Savvyio.Extensions.EFCore.Domain; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// The to extend. + /// The which need to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreAggregateDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) { - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The which need to be configured. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreAggregateDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services.AddDataSource(serviceSetup) - .AddUnitOfWork(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + Validator.ThrowIfNull(services); + return services.AddDataSource(serviceSetup) + .AddUnitOfWork(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The which need to be configured. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreAggregateDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services.AddDataSource>(serviceSetup) - .AddUnitOfWork>(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The which need to be configured. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreAggregateDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services.AddDataSource>(serviceSetup) + .AddUnitOfWork>(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IAggregateRoot - { - Validator.ThrowIfNull(services); - return services.AddAggregateRepository, TEntity, TKey>(setup); - } + /// + /// Adds an to the specified . + /// + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IAggregateRoot + { + Validator.ThrowIfNull(services); + return services.AddAggregateRepository, TEntity, TKey>(setup); + } - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// The to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded accordingly. - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IAggregateRoot - { - Validator.ThrowIfNull(services); - return services.AddAggregateRepository, TEntity, TKey>(setup); - } + /// + /// Adds an to the specified . + /// + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. + /// The to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded accordingly. + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreAggregateRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IAggregateRoot + { + Validator.ThrowIfNull(services); + return services.AddAggregateRepository, TEntity, TKey>(setup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs index a27c0b27..4478fb80 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs @@ -1,21 +1,20 @@ using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Provides a default implementation of the interface to support multiple implementations that does the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreDataSource : EfCoreDataSource, IEfCoreDataSource { /// - /// Provides a default implementation of the interface to support multiple implementations that does the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreDataSource : EfCoreDataSource, IEfCoreDataSource + /// The used to configure this instance. + public EfCoreDataSource(EfCoreDataSourceOptions options) : base(new EfCoreDbContext(options)) { - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - public EfCoreDataSource(EfCoreDataSourceOptions options) : base(new EfCoreDbContext(options)) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs index 8befa7c7..f8e978ef 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs @@ -1,15 +1,14 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Configuration options for . +/// +/// The type used to mark the implementation that these options represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreDataSourceOptions : EfCoreDataSourceOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// The type used to mark the implementation that these options represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreDataSourceOptions : EfCoreDataSourceOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs index e4d9a4c4..5f172961 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs @@ -1,23 +1,22 @@ using Savvyio.Extensions.DependencyInjection.Data; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Provides a default implementation of the interface to support multiple implementations that serves as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreDataStore : EfCoreDataStore, IPersistentDataStore, TMarker> where T : class { /// - /// Provides a default implementation of the interface to support multiple implementations that serves as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreDataStore : EfCoreDataStore, IPersistentDataStore, TMarker> where T : class + /// The that handles actual I/O communication with a source of data. + public EfCoreDataStore(IEfCoreDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreDataStore(IEfCoreDataSource source) : base(source) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs index 8ef9e914..1717f976 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs @@ -2,22 +2,21 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Provides a default implementation of the class to support Savvy I/O extensions of Microsoft Entity Framework Core in multiple implementations. +/// +/// The type used to mark the implementation that this context represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreDbContext : EfCoreDbContext, IDependencyInjectionMarker { /// - /// Provides a default implementation of the class to support Savvy I/O extensions of Microsoft Entity Framework Core in multiple implementations. + /// Initializes a new instance of the class. /// - /// The type used to mark the implementation that this context represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreDbContext : EfCoreDbContext, IDependencyInjectionMarker + /// The used to configure this instance. + public EfCoreDbContext(EfCoreDataSourceOptions options) : base(options) { - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - public EfCoreDbContext(EfCoreDataSourceOptions options) : base(options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs index d20191c7..5edb7a0c 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs @@ -1,24 +1,23 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Provides a default implementation of the interface to support multiple implementations that serves as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public class EfCoreRepository : EfCoreRepository, IPersistentRepository where TEntity : class, IIdentity { /// - /// Provides a default implementation of the interface to support multiple implementations that serves as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public class EfCoreRepository : EfCoreRepository, IPersistentRepository where TEntity : class, IIdentity + /// The that handles actual I/O communication with a source of data. + public EfCoreRepository(IEfCoreDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreRepository(IEfCoreDataSource source) : base(source) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs index 5772af4f..1a297904 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs @@ -1,15 +1,14 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IEfCoreDataSource : IEfCoreDataSource, IDataSource, IUnitOfWork { - /// - /// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data using Microsoft Entity Framework Core. - /// - /// The type used to mark the implementation that this data store represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IEfCoreDataSource : IEfCoreDataSource, IDataSource, IUnitOfWork - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs index 2025e245..91da561c 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs @@ -7,122 +7,121 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// The to extend. + /// The which need 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) { - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The which need 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreDataSource(this IServiceCollection services, Action dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services.AddDataSource(serviceSetup) - .AddUnitOfWork(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + Validator.ThrowIfNull(services); + return services.AddDataSource(serviceSetup) + .AddUnitOfWork(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// Adds an implementation to the specified . - /// - /// The type used to mark the implementation that this data source represents. Optimized for Microsoft Dependency Injection. - /// The to extend. - /// The which need 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services.AddDataSource>(serviceSetup) - .AddUnitOfWork>(serviceSetup) - .AddConfiguredOptions(dataSourceSetup); - } + /// + /// Adds an implementation to the specified . + /// + /// The type used to mark the implementation that this data source represents. Optimized for Microsoft Dependency Injection. + /// The to extend. + /// The which need 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreDataSource(this IServiceCollection services, Action> dataSourceSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services.AddDataSource>(serviceSetup) + .AddUnitOfWork>(serviceSetup) + .AddConfiguredOptions(dataSourceSetup); + } - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded to: , , and . - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IIdentity - { - Validator.ThrowIfNull(services); - return services.AddRepository, TEntity, TKey>(setup); - } + /// + /// Adds an to the specified . + /// + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded to: , , and . + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IIdentity + { + Validator.ThrowIfNull(services); + return services.AddRepository, TEntity, TKey>(setup); + } - /// - /// Adds an to the specified . - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// The will be type forwarded to: , , and . - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IIdentity - { - Validator.ThrowIfNull(services); - return services.AddRepository, TEntity, TKey>(setup); - } + /// + /// Adds an to the specified . + /// + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// The will be type forwarded to: , , and . + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreRepository(this IServiceCollection services, Action setup = null) where TEntity : class, IIdentity + { + Validator.ThrowIfNull(services); + return services.AddRepository, TEntity, TKey>(setup); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the DTO. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreDataStore(this IServiceCollection services, Action setup = null) where T : class - { - Validator.ThrowIfNull(services); - return services.AddDataStore, T, EfCoreQueryOptions>(setup); - } + /// + /// Adds an implementation of to the specified . + /// + /// The type of the DTO. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreDataStore(this IServiceCollection services, Action setup = null) where T : class + { + Validator.ThrowIfNull(services); + return services.AddDataStore, T, EfCoreQueryOptions>(setup); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddEfCoreDataStore(this IServiceCollection services, Action setup = null) where T : class - { - Validator.ThrowIfNull(services); - return services.AddDataStore, T, EfCoreQueryOptions>(setup); - } + /// + /// Adds an implementation of to the specified . + /// + /// The type of the DTO. + /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddEfCoreDataStore(this IServiceCollection services, Action setup = null) where T : class + { + Validator.ThrowIfNull(services); + return services.AddDataStore, T, EfCoreQueryOptions>(setup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs index 7b8580f1..30a4d831 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs @@ -4,29 +4,28 @@ using Savvyio.Extensions.NATS; using Savvyio.Extensions.NATS.Commands; -namespace Savvyio.Extensions.DependencyInjection.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 { /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class NatsCommandQueue : NatsCommandQueue, IPointToPointChannel + /// 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) { - /// - /// 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 index d92ae34b..6ac133a0 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.NATS.Commands; -namespace Savvyio.Extensions.DependencyInjection.NATS.Commands +namespace Savvyio.Extensions.DependencyInjection.NATS.Commands; + +/// +/// Configuration options for . +/// +/// +/// +public class NatsCommandQueueOptions : NatsCommandQueueOptions, IDependencyInjectionMarker { - /// - /// 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 index 42495450..cdf372cc 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs @@ -4,30 +4,29 @@ using Savvyio.Extensions.NATS; using Savvyio.Extensions.NATS.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.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 { + /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class NatsEventBus : NatsEventBus, IPublishSubscribeChannel + /// 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) { - - /// - /// 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 index 12a6f123..542ceb37 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.NATS.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven +namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven; + +/// +/// Configuration options for . +/// +/// +/// +public class NatsEventBusOptions : NatsEventBusOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class NatsEventBusOptions : NatsEventBusOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs index 9dbb1066..4c7cfa6e 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs @@ -10,87 +10,86 @@ using Savvyio.Extensions.NATS.Commands; using Savvyio.Extensions.NATS.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.NATS +namespace Savvyio.Extensions.DependencyInjection.NATS; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) { - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(natsSetup); - } + Validator.ThrowIfNull(services); + 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddNatsCommandQueue(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action natsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus, IIntegrationEvent>(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. + /// + /// cannot be null. + /// + public static IServiceCollection AddNatsEventBus(this IServiceCollection services, Action> natsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(natsSetup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs index fdec1af0..575c3b54 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs @@ -6,30 +6,29 @@ using Newtonsoft.Json; using Savvyio.Extensions.Newtonsoft.Json; -namespace Savvyio.Extensions.DependencyInjection.Newtonsoft.Json +namespace Savvyio.Extensions.DependencyInjection.Newtonsoft.Json; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// The to extend. + /// The which may be configured. Default is optimized for messaging. + /// The which may be configured. Default is . + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + /// + /// cannot be null. + /// + public static IServiceCollection AddNewtonsoftJsonMarshaller(this IServiceCollection services, Action jsonSetup = null, Action serviceSetup = null) { - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The which may be configured. Default is optimized for messaging. - /// The which may be configured. Default is . - /// A reference to so that additional calls can be chained. - /// The implementation will be type forwarded accordingly. - /// - /// cannot be null. - /// - public static IServiceCollection AddNewtonsoftJsonMarshaller(this IServiceCollection services, Action jsonSetup = null, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMarshaller(serviceSetup) - .AddConfiguredOptions(jsonSetup ?? (o => o.Settings.Formatting = Formatting.None)); - } + Validator.ThrowIfNull(services); + return services + .AddMarshaller(serviceSetup) + .AddConfiguredOptions(jsonSetup ?? (o => o.Settings.Formatting = Formatting.None)); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs index a6808ab0..49e8ad1d 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.QueueStorage; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage +namespace Savvyio.Extensions.DependencyInjection.QueueStorage; + +/// +/// Configuration options for . +/// +/// +/// +public class AzureQueueOptions : AzureQueueOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class AzureQueueOptions : AzureQueueOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs index f54cc126..98d04370 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs @@ -3,29 +3,28 @@ using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.QueueStorage.Commands; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Commands +namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Commands; + +/// +/// Provides a default implementation of the class that is optimized for Dependency Injection. +/// +/// +/// +public class AzureCommandQueue : AzureCommandQueue, IPointToPointChannel { /// - /// Provides a default implementation of the class that is optimized for Dependency Injection. + /// Initializes a new instance of the class. /// - /// - /// - public class AzureCommandQueue : AzureCommandQueue, IPointToPointChannel + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AzureCommandQueue(IMarshaller marshaller, AzureQueueOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AzureCommandQueue(IMarshaller marshaller, AzureQueueOptions options) : base(marshaller, options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs index c2a81d87..733bfbf1 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs @@ -3,30 +3,29 @@ using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.QueueStorage.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven +namespace Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven; + +/// +/// Provides a default implementation of the class that is optimized for Dependency Injection. +/// +/// +/// +public class AzureEventBus : AzureEventBus, IPublishSubscribeChannel { /// - /// Provides a default implementation of the class that is optimized for Dependency Injection. + /// Initializes a new instance of the class. /// - /// - /// - public class AzureEventBus : AzureEventBus, IPublishSubscribeChannel + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions) : base(marshaller, azureQueueOptions, azureEventBusOptions) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions) : base(marshaller, azureQueueOptions, azureEventBusOptions) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs index d3b9c04a..b4ebf0cc 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.QueueStorage.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven +namespace Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven; + +/// +/// Configuration options for . +/// +/// +/// +public class AzureEventBusOptions : AzureEventBusOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class AzureEventBusOptions : AzureEventBusOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs index 89ad7028..bf86288d 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs @@ -11,91 +11,90 @@ using Savvyio.Extensions.QueueStorage.Commands; using Savvyio.Extensions.QueueStorage.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage +namespace Savvyio.Extensions.DependencyInjection.QueueStorage; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAzureCommandQueue(this IServiceCollection services, Action azureQueueSetup, Action serviceSetup = null) { - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAzureCommandQueue(this IServiceCollection services, Action azureQueueSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(azureQueueSetup); - } + Validator.ThrowIfNull(services); + return services + .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(azureQueueSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAzureCommandQueue(this IServiceCollection services, Action> azureQueueSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(azureQueueSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAzureCommandQueue(this IServiceCollection services, Action> azureQueueSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(azureQueueSetup); + } - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The that needs to be configured. - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAzureEventBus(this IServiceCollection services, Action azureQueueSetup, Action azureEventBusSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(azureQueueSetup) - .AddConfiguredOptions(azureEventBusSetup); - } + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAzureEventBus(this IServiceCollection services, Action azureQueueSetup, Action azureEventBusSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(azureQueueSetup) + .AddConfiguredOptions(azureEventBusSetup); + } - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The that needs to be configured. - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAzureEventBus(this IServiceCollection services, Action> azureQueueSetup, Action> azureEventBusSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(azureQueueSetup) - .AddConfiguredOptions(azureEventBusSetup); - } + /// + /// Adds an implementation to the specified . + /// + /// The to extend. + /// The that needs to be configured. + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAzureEventBus(this IServiceCollection services, Action> azureQueueSetup, Action> azureEventBusSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(azureQueueSetup) + .AddConfiguredOptions(azureEventBusSetup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs index 5dc12e57..f3f4ae8b 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs @@ -4,29 +4,28 @@ using Savvyio.Extensions.RabbitMQ; using Savvyio.Extensions.RabbitMQ.Commands; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands; + +/// +/// Provides a default implementation of the class for messages holding an implementation. +/// +/// +/// +public class RabbitMqCommandQueue : RabbitMqCommandQueue, IPointToPointChannel { /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class RabbitMqCommandQueue : RabbitMqCommandQueue, IPointToPointChannel + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the RabbitMQ command queue. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public RabbitMqCommandQueue(IMarshaller marshaller, RabbitMqCommandQueueOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The marshaller used for serializing and deserializing messages. - /// The options used to configure the RabbitMQ command queue. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public RabbitMqCommandQueue(IMarshaller marshaller, RabbitMqCommandQueueOptions options) : base(marshaller, options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs index 0c7acf79..399074b5 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.RabbitMQ.Commands; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands; + +/// +/// Configuration options for . +/// +/// +/// +public class RabbitMqCommandQueueOptions : RabbitMqCommandQueueOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class RabbitMqCommandQueueOptions : RabbitMqCommandQueueOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs index 89acf907..7913b50a 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs @@ -4,30 +4,29 @@ using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.RabbitMQ; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven; + +/// +/// Provides a default implementation of the class for messages holding an implementation. +/// +/// +/// +public class RabbitMqEventBus : RabbitMqEventBus, IPublishSubscribeChannel { + /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class RabbitMqEventBus : RabbitMqEventBus, IPublishSubscribeChannel + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the RabbitMQ event bus. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public RabbitMqEventBus(IMarshaller marshaller, RabbitMqEventBusOptions options) : base(marshaller, options) { - - /// - /// Initializes a new instance of the class. - /// - /// The marshaller used for serializing and deserializing messages. - /// The options used to configure the RabbitMQ event bus. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public RabbitMqEventBus(IMarshaller marshaller, RabbitMqEventBusOptions options) : base(marshaller, options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs index 45ee9611..5e806663 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.RabbitMQ.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven; + +/// +/// Configuration options for . +/// +/// +/// +public class RabbitMqEventBusOptions : RabbitMqEventBusOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class RabbitMqEventBusOptions : RabbitMqEventBusOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs index 20569427..7a9d018e 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs @@ -10,87 +10,86 @@ using Savvyio.Extensions.RabbitMQ.Commands; using Savvyio.Extensions.RabbitMQ.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddRabbitMqCommandQueue(this IServiceCollection services, Action rabbitMqSetup, Action serviceSetup = null) { - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddRabbitMqCommandQueue(this IServiceCollection services, Action rabbitMqSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(rabbitMqSetup); - } + Validator.ThrowIfNull(services); + return services + .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(rabbitMqSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddRabbitMqCommandQueue(this IServiceCollection services, Action> rabbitMqSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(rabbitMqSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddRabbitMqCommandQueue(this IServiceCollection services, Action> rabbitMqSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(rabbitMqSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddRabbitMqEventBus(this IServiceCollection services, Action rabbitMqSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(rabbitMqSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddRabbitMqEventBus(this IServiceCollection services, Action rabbitMqSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(rabbitMqSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddRabbitMqEventBus(this IServiceCollection services, Action> rabbitMqSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(rabbitMqSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddRabbitMqEventBus(this IServiceCollection services, Action> rabbitMqSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(rabbitMqSetup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs index 7391234d..604a0146 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs @@ -4,29 +4,28 @@ using Savvyio.Extensions.SimpleQueueService; using Savvyio.Extensions.SimpleQueueService.Commands; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Commands +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Commands; + +/// +/// Provides a default implementation of the class tailored for messages holding an implementation. +/// +/// +/// +public class AmazonCommandQueue : AmazonCommandQueue, IPointToPointChannel { /// - /// Provides a default implementation of the class tailored for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class AmazonCommandQueue : AmazonCommandQueue, IPointToPointChannel + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options) : base(marshaller, options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs index f295e0a2..157e0011 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.SimpleQueueService.Commands; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Commands +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Commands; + +/// +/// Configuration options for . +/// +/// +/// +public class AmazonCommandQueueOptions : AmazonCommandQueueOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class AmazonCommandQueueOptions : AmazonCommandQueueOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs index 38026c7f..7f052fba 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs @@ -4,29 +4,28 @@ using Savvyio.Extensions.SimpleQueueService; using Savvyio.Extensions.SimpleQueueService.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.EventDriven; + +/// +/// Provides a default implementation of the class tailored for messages holding an implementation. +/// +/// +/// +public class AmazonEventBus : AmazonEventBus, IPublishSubscribeChannel { /// - /// Provides a default implementation of the class tailored for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class AmazonEventBus : AmazonEventBus, IPublishSubscribeChannel + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options) : base(marshaller, options) - { - } } } diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs index 037e6aec..67290608 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.SimpleQueueService.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.EventDriven; + +/// +/// Configuration options for . +/// +/// +/// +public class AmazonEventBusOptions : AmazonEventBusOptions, IDependencyInjectionMarker { - /// - /// Configuration options for . - /// - /// - /// - public class AmazonEventBusOptions : AmazonEventBusOptions, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs index 91dc80c2..30462d0f 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs @@ -10,87 +10,86 @@ using Savvyio.Extensions.SimpleQueueService.Commands; using Savvyio.Extensions.SimpleQueueService.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAmazonCommandQueue(this IServiceCollection services, Action awsSetup, Action serviceSetup = null) { - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAmazonCommandQueue(this IServiceCollection services, Action awsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(awsSetup); - } + Validator.ThrowIfNull(services); + return services + .AddMessageQueue(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(awsSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAmazonCommandQueue(this IServiceCollection services, Action> awsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(awsSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAmazonCommandQueue(this IServiceCollection services, Action> awsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageQueue, ICommand>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(awsSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAmazonEventBus(this IServiceCollection services, Action awsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(awsSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAmazonEventBus(this IServiceCollection services, Action awsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(awsSetup); + } - /// - /// 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. - /// - /// cannot be null. - /// - public static IServiceCollection AddAmazonEventBus(this IServiceCollection services, Action> awsSetup, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) - .AddConfiguredOptions(awsSetup); - } + /// + /// 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. + /// + /// cannot be null. + /// + public static IServiceCollection AddAmazonEventBus(this IServiceCollection services, Action> awsSetup, Action serviceSetup = null) + { + Validator.ThrowIfNull(services); + return services + .AddMessageBus, IIntegrationEvent>(serviceSetup ?? (o => o.Lifetime = ServiceLifetime.Singleton)) + .AddConfiguredOptions(awsSetup); } } diff --git a/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs index 96aa6cfd..05312bdb 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs @@ -5,30 +5,29 @@ using Cuemon; using Savvyio.Extensions.Text.Json; -namespace Savvyio.Extensions.DependencyInjection.Text.Json +namespace Savvyio.Extensions.DependencyInjection.Text.Json; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation to the specified . /// - public static class ServiceCollectionExtensions + /// The to extend. + /// The which may be configured. Default is optimized for messaging. + /// The which may be configured. Default is . + /// A reference to so that additional calls can be chained. + /// The implementation will be type forwarded accordingly. + /// + /// cannot be null. + /// + public static IServiceCollection AddJsonMarshaller(this IServiceCollection services, Action jsonSetup = null, Action serviceSetup = null) { - /// - /// Adds an implementation to the specified . - /// - /// The to extend. - /// The which may be configured. Default is optimized for messaging. - /// The which may be configured. Default is . - /// A reference to so that additional calls can be chained. - /// The implementation will be type forwarded accordingly. - /// - /// cannot be null. - /// - public static IServiceCollection AddJsonMarshaller(this IServiceCollection services, Action jsonSetup = null, Action serviceSetup = null) - { - Validator.ThrowIfNull(services); - return services - .AddMarshaller(serviceSetup) - .AddConfiguredOptions(jsonSetup ?? (o => o.Settings.WriteIndented = false)); - } + Validator.ThrowIfNull(services); + return services + .AddMarshaller(serviceSetup) + .AddConfiguredOptions(jsonSetup ?? (o => o.Settings.WriteIndented = false)); } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs index 5a43a23d..97a874fb 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs @@ -1,16 +1,15 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of data persistence based on the Data Access Object pattern aka DAO. +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IDataStore : IDataStore, IDependencyInjectionMarker where T : class { - /// - /// Defines a generic way to support multiple implementations of data persistence based on the Data Access Object pattern aka DAO. - /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IDataStore : IDataStore, IDependencyInjectionMarker where T : class - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs index 46db0440..6e2676b8 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs @@ -1,15 +1,14 @@ using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of deletable data access objects (cruD). +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IDeletableDataStore : IDataStore, IDeletableDataStore where T : class { - /// - /// Defines a generic way to support multiple implementations of deletable data access objects (cruD). - /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IDeletableDataStore : IDataStore, IDeletableDataStore where T : class - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs index 753e3440..bbfd0b18 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs @@ -1,22 +1,21 @@ using Cuemon.Threading; using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of the actual I/O communication with a data store that is responsible of persisting data (CRUD). +/// +/// The type of the DTO. +/// The type of the options associated with this DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +/// +/// +public interface IPersistentDataStore : IPersistentDataStore, IWritableDataStore, IReadableDataStore, ISearchableDataStore, IDeletableDataStore + where T : class + where TOptions : AsyncOptions, new() { - /// - /// Defines a generic way to support multiple implementations of the actual I/O communication with a data store that is responsible of persisting data (CRUD). - /// - /// The type of the DTO. - /// The type of the options associated with this DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - /// - /// - public interface IPersistentDataStore : IPersistentDataStore, IWritableDataStore, IReadableDataStore, ISearchableDataStore, IDeletableDataStore - where T : class - where TOptions : AsyncOptions, new() - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs index 91857352..88e79af6 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs @@ -1,15 +1,14 @@ using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of readable data access objects (cRud). +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IReadableDataStore : IDataStore, IReadableDataStore where T : class { - /// - /// Defines a generic way to support multiple implementations of readable data access objects (cRud). - /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IReadableDataStore : IDataStore, IReadableDataStore where T : class - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs index d388074a..3ecadbe1 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs @@ -1,19 +1,18 @@ using Cuemon.Threading; using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of searchable data access objects (cRud). +/// +/// The type of the DTO. +/// The type of the options associated with this DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface ISearchableDataStore : IDataStore, ISearchableDataStore + where T : class + where TOptions : AsyncOptions, new() { - /// - /// Defines a generic way to support multiple implementations of searchable data access objects (cRud). - /// - /// The type of the DTO. - /// The type of the options associated with this DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface ISearchableDataStore : IDataStore, ISearchableDataStore - where T : class - where TOptions : AsyncOptions, new() - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs index 8a4d61a2..a61a07e7 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs @@ -1,15 +1,14 @@ using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Defines a generic way to support multiple implementations of writable data access objects (CrUd). +/// +/// The type of the DTO. +/// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IWritableDataStore : IDataStore, IWritableDataStore where T : class { - /// - /// Defines a generic way to support multiple implementations of writable data access objects (CrUd). - /// - /// The type of the DTO. - /// The type used to mark the implementation that this data access object represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IWritableDataStore : IDataStore, IWritableDataStore where T : class - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs index dc08e3c6..4867555a 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs @@ -6,69 +6,68 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Data; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the to add. + /// The type of the DTO to use. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddDataStore(this IServiceCollection services, Action setup = null) + where TService : class, IPersistentDataStore + where T : class { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the DTO to use. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddDataStore(this IServiceCollection services, Action setup = null) - where TService : class, IPersistentDataStore - where T : class - { - return AddDataStore(services, setup); - } + return AddDataStore(services, setup); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the DTO to use. - /// The type of the options associated with . - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddDataStore(this IServiceCollection services, Action setup = null) - where TService : class, IPersistentDataStore - where T : class - where TOptions : AsyncOptions, new() + /// + /// Adds an implementation of to the specified . + /// + /// The type of the to add. + /// The type of the DTO to use. + /// The type of the options associated with . + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddDataStore(this IServiceCollection services, Action setup = null) + where TService : class, IPersistentDataStore + where T : class + where TOptions : AsyncOptions, new() + { + Validator.ThrowIfNull(services); + var options = Patterns.Configure(setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = Patterns.Configure(setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IDataStore<>)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IDataStore<>)); + }); } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs index 97770d55..972e3faa 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs @@ -1,16 +1,15 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of deletable repositories (cruD). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IDeletableRepository : IRepository, IDeletableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of deletable repositories (cruD). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IDeletableRepository : IRepository, IDeletableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs index c398a2f0..1973c8d2 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs @@ -1,18 +1,17 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of persistent repositories (CRUD). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +/// +public interface IPersistentRepository : IPersistentRepository, IWritableRepository, IReadableRepository, ISearchableRepository, IDeletableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of persistent repositories (CRUD). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - /// - public interface IPersistentRepository : IPersistentRepository, IWritableRepository, IReadableRepository, ISearchableRepository, IDeletableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs index b2482edc..310ab7d9 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs @@ -1,16 +1,15 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of readable repositories (cRud). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IReadableRepository : IRepository, IReadableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of readable repositories (cRud). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IReadableRepository : IRepository, IReadableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs index 1ea0c9e1..af426d72 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs @@ -1,17 +1,16 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of persistent data access based on the Repository pattern. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IRepository : IRepository, IDependencyInjectionMarker where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of persistent data access based on the Repository pattern. - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IRepository : IRepository, IDependencyInjectionMarker where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs index 851db2fd..c6a5257b 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs @@ -1,16 +1,15 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of searchable repositories (cRud). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface ISearchableRepository : IRepository, ISearchableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of searchable repositories (cRud). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface ISearchableRepository : IRepository, ISearchableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs index 4f0fb72d..85ea8626 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs @@ -1,15 +1,14 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations that bundles transactions from multiple calls into a single unit. +/// +/// The type used to mark the implementation that this UoW represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IUnitOfWork : IUnitOfWork, IDependencyInjectionMarker { - /// - /// Defines a generic way to support multiple implementations that bundles transactions from multiple calls into a single unit. - /// - /// The type used to mark the implementation that this UoW represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IUnitOfWork : IUnitOfWork, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs index fffec0b2..a0373f2e 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs @@ -1,16 +1,15 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Defines a generic way to support multiple implementations of writable repositories (CrUd). +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IWritableRepository : IRepository, IWritableRepository where TEntity : class, IIdentity { - /// - /// Defines a generic way to support multiple implementations of writable repositories (CrUd). - /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The type used to mark the implementation that this repository represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IWritableRepository : IRepository, IWritableRepository where TEntity : class, IIdentity - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs index 71e50062..7eaf9011 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs @@ -5,68 +5,67 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Domain +namespace Savvyio.Extensions.DependencyInjection.Domain; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the to add. + /// The type of the entity. + /// The type of the key that uniquely identifies the entity. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddRepository(this IServiceCollection services, Action setup = null) + where TService : class, IPersistentRepository + where TEntity : class, IIdentity { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static IServiceCollection AddRepository(this IServiceCollection services, Action setup = null) - where TService : class, IPersistentRepository - where TEntity : class, IIdentity + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IRepository<,>)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IRepository<,>)); + }); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - public static IServiceCollection AddUnitOfWork(this IServiceCollection services, Action setup = null) where TService : class, IUnitOfWork + /// + /// Adds an implementation of to the specified . + /// + /// The type of the to add. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + public static IServiceCollection AddUnitOfWork(this IServiceCollection services, Action setup = null) where TService : class, IUnitOfWork + { + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); + var unitOfWorkType = typeof(IUnitOfWork); + if (typeof(TService).TryGetDependencyInjectionMarker(out var markerType)) { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Scoped)).Configure(); - var unitOfWorkType = typeof(IUnitOfWork); - if (typeof(TService).TryGetDependencyInjectionMarker(out var markerType)) - { - unitOfWorkType = typeof(IUnitOfWork<>).MakeGenericType(markerType); - } - return services.Add(unitOfWorkType, p => p.GetRequiredService(), options.Lifetime); + unitOfWorkType = typeof(IUnitOfWork<>).MakeGenericType(markerType); } + return services.Add(unitOfWorkType, p => p.GetRequiredService(), options.Lifetime); } } diff --git a/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs b/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs index 8e781ad8..f2cabfde 100644 --- a/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs @@ -1,14 +1,13 @@ using Cuemon.Extensions.DependencyInjection; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +/// +/// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data. +/// +/// The type used to mark the implementation that this data source represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IDataSource : IDataSource, IDependencyInjectionMarker { - /// - /// Defines a generic way to support multiple implementations that does the actual I/O communication with a source of data. - /// - /// The type used to mark the implementation that this data source represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IDataSource : IDataSource, IDependencyInjectionMarker - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs index f8baef5c..781b74fa 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs @@ -1,16 +1,15 @@ using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a bus that is used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this queue represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +public interface IPointToPointChannel : IPointToPointChannel, ISender, IReceiver where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a bus that is used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this queue represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - public interface IPointToPointChannel : IPointToPointChannel, ISender, IReceiver where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs index 5ff86d52..d5e7a2fa 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs @@ -1,16 +1,15 @@ using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a bus that is used for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this bus represents. Optimized for Microsoft Dependency Injection. +/// +/// +/// +public interface IPublishSubscribeChannel : IPublishSubscribeChannel, IPublisher, ISubscriber where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a bus that is used for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this bus represents. Optimized for Microsoft Dependency Injection. - /// - /// - /// - public interface IPublishSubscribeChannel : IPublishSubscribeChannel, IPublisher, ISubscriber where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs index 21b4dbe2..d9e11d96 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs @@ -1,16 +1,15 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a publisher/sender channel for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IPublisher : IPublisher, IDependencyInjectionMarker where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a publisher/sender channel for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IPublisher : IPublisher, IDependencyInjectionMarker where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs index 75b9cb4e..37cddc2b 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs @@ -1,16 +1,15 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a consumer/receiver channel used by subsystems to receive a command and perform one or more actions (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface IReceiver : IReceiver, IDependencyInjectionMarker where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a consumer/receiver channel used by subsystems to receive a command and perform one or more actions (e.g., change the state). - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface IReceiver : IReceiver, IDependencyInjectionMarker where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs index 99695fd3..8524d8a3 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs @@ -1,16 +1,15 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a producer/sender channel used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface ISender : ISender, IDependencyInjectionMarker where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a producer/sender channel used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface ISender : ISender, IDependencyInjectionMarker where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs index 20da3812..417a5175 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs @@ -1,16 +1,15 @@ using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Defines a generic way to support multiple implementations of a subscriber/receiver channel used by subsystems to subscribe to messages (typically events) to be made aware of something that has happened. +/// +/// The type of the model to invoke on a handler. +/// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. +/// +/// +public interface ISubscriber : ISubscriber, IDependencyInjectionMarker where TRequest : IRequest { - /// - /// Defines a generic way to support multiple implementations of a subscriber/receiver channel used by subsystems to subscribe to messages (typically events) to be made aware of something that has happened. - /// - /// The type of the model to invoke on a handler. - /// The type used to mark the implementation that this channel represents. Optimized for Microsoft Dependency Injection. - /// - /// - public interface ISubscriber : ISubscriber, IDependencyInjectionMarker where TRequest : IRequest - { - } } diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs index 3ccab36b..220293d5 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs @@ -5,55 +5,54 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Messaging; -namespace Savvyio.Extensions.DependencyInjection.Messaging +namespace Savvyio.Extensions.DependencyInjection.Messaging; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the to add. + /// The type of the model to invoke on a handler. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + public static IServiceCollection AddMessageQueue(this IServiceCollection services, Action setup = null) where TService : class, IPointToPointChannel where TRequest : IRequest { - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the model to invoke on a handler. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - public static IServiceCollection AddMessageQueue(this IServiceCollection services, Action setup = null) where TService : class, IPointToPointChannel where TRequest : IRequest + Validator.ThrowIfNull(services); + var options = Patterns.Configure(setup, o => o.Lifetime = ServiceLifetime.Singleton); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = Patterns.Configure(setup, o => o.Lifetime = ServiceLifetime.Singleton); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IPointToPointChannel<>), typeof(IReceiver<>), typeof(ISender<>)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IPointToPointChannel<>), typeof(IReceiver<>), typeof(ISender<>)); + }); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The type of the model to invoke on a handler. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - public static IServiceCollection AddMessageBus(this IServiceCollection services, Action setup = null) where TService : class, IPublishSubscribeChannel where TRequest : IRequest + /// + /// Adds an implementation of to the specified . + /// + /// The type of the to add. + /// The type of the model to invoke on a handler. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + public static IServiceCollection AddMessageBus(this IServiceCollection services, Action setup = null) where TService : class, IPublishSubscribeChannel where TRequest : IRequest + { + Validator.ThrowIfNull(services); + var options = Patterns.Configure(setup, o => o.Lifetime = ServiceLifetime.Singleton); + return services.Add(o => { - Validator.ThrowIfNull(services); - var options = Patterns.Configure(setup, o => o.Lifetime = ServiceLifetime.Singleton); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IPublishSubscribeChannel<>), typeof(ISubscriber<>), typeof(IPublisher<>)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IPublishSubscribeChannel<>), typeof(ISubscriber<>), typeof(IPublisher<>)); + }); } } diff --git a/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs b/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs index 0a3af6dd..214c219a 100644 --- a/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs @@ -6,118 +6,117 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Dispatchers; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +/// +/// Specifies options that is related to setting up Savvy I/O services. +/// +public class SavvyioDependencyInjectionOptions : SavvyioOptions { + private readonly IList _assemblies = new List(); + private readonly ServiceLocatorOptions _serviceLocatorOptions = new(); + /// - /// Specifies options that is related to setting up Savvy I/O services. + /// Initializes a new instance of the class. /// - public class SavvyioDependencyInjectionOptions : SavvyioOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// false + /// + /// + /// + /// false + /// + /// + /// + /// false + /// + /// + /// + /// + /// + /// + /// + /// p => new ServiceLocator(p.GetServices) + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// null + /// + /// + /// + public SavvyioDependencyInjectionOptions() { - private readonly IList _assemblies = new List(); - private readonly ServiceLocatorOptions _serviceLocatorOptions = new(); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// false - /// - /// - /// - /// false - /// - /// - /// - /// false - /// - /// - /// - /// - /// - /// - /// - /// p => new ServiceLocator(p.GetServices) - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// null - /// - /// - /// - public SavvyioDependencyInjectionOptions() - { - HandlerServicesLifetime = ServiceLifetime.Transient; - DispatcherServicesLifetime = ServiceLifetime.Transient; - ServiceLocatorImplementationFactory = _serviceLocatorOptions.ImplementationFactory; - ServiceLocatorLifetime = _serviceLocatorOptions.Lifetime; - } + HandlerServicesLifetime = ServiceLifetime.Transient; + DispatcherServicesLifetime = ServiceLifetime.Transient; + ServiceLocatorImplementationFactory = _serviceLocatorOptions.ImplementationFactory; + ServiceLocatorLifetime = _serviceLocatorOptions.Lifetime; + } - /// - /// Gets or sets the function delegate that creates an instance of an implementation. - /// - /// The function delegate that creates an instance of an implementation. - public Func ServiceLocatorImplementationFactory { get; set; } + /// + /// Gets or sets the function delegate that creates an instance of an implementation. + /// + /// The function delegate that creates an instance of an implementation. + public Func ServiceLocatorImplementationFactory { get; set; } - /// - /// Gets or sets the lifetime of the . - /// - /// The lifetime of the . - public ServiceLifetime ServiceLocatorLifetime { get; set; } + /// + /// Gets or sets the lifetime of the . + /// + /// The lifetime of the . + public ServiceLifetime ServiceLocatorLifetime { get; set; } - /// - /// Gets or sets the lifetime of the handler services. - /// - /// The lifetime of the handler services. - public ServiceLifetime HandlerServicesLifetime { get; set; } + /// + /// Gets or sets the lifetime of the handler services. + /// + /// The lifetime of the handler services. + public ServiceLifetime HandlerServicesLifetime { get; set; } - /// - /// Gets or sets the lifetime of the dispatcher services. - /// - /// The lifetime of the dispatcher services. - public ServiceLifetime DispatcherServicesLifetime { get; set; } + /// + /// Gets or sets the lifetime of the dispatcher services. + /// + /// The lifetime of the dispatcher services. + public ServiceLifetime DispatcherServicesLifetime { get; set; } - /// - /// Gets the assemblies to scan for dispatcher- and handler- types. - /// - /// The assemblies to scan for dispatcher- and handler- types. - public IEnumerable AssembliesToScan => _assemblies.Count == 0 ? Enumerable.Empty() : _assemblies; + /// + /// Gets the assemblies to scan for dispatcher- and handler- types. + /// + /// The assemblies to scan for dispatcher- and handler- types. + public IEnumerable AssembliesToScan => _assemblies.Count == 0 ? Enumerable.Empty() : _assemblies; - /// - /// Adds the specified range of to be included when scanning for dispatcher- and handler- types. - /// - /// The assemblies to include in the scan. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioDependencyInjectionOptions AddAssemblyRangeToScan(params Assembly[] assemblies) - { - _assemblies.AddRange(assemblies); - return this; - } + /// + /// Adds the specified range of to be included when scanning for dispatcher- and handler- types. + /// + /// The assemblies to include in the scan. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioDependencyInjectionOptions AddAssemblyRangeToScan(params Assembly[] assemblies) + { + _assemblies.AddRange(assemblies); + return this; + } - /// - /// Adds the specified to be included when scanning for dispatcher- and handler- types. - /// - /// The assembly to include in the scan. - /// A reference to this instance so that additional configuration calls can be chained. - public SavvyioDependencyInjectionOptions AddAssemblyToScan(Assembly assembly) - { - _assemblies.Add(assembly); - return this; - } + /// + /// Adds the specified to be included when scanning for dispatcher- and handler- types. + /// + /// The assembly to include in the scan. + /// A reference to this instance so that additional configuration calls can be chained. + public SavvyioDependencyInjectionOptions AddAssemblyToScan(Assembly assembly) + { + _assemblies.Add(assembly); + return this; } } diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs index c34b64ce..9a4ee94f 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs @@ -10,257 +10,256 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Dispatchers; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +/// +/// Extension methods for the interface. +/// +public static class ServiceCollectionExtensions { /// - /// Extension methods for the interface. + /// Registers the specified as a triple-configuration for both compatibility with (and outside the confines of) Microsoft Dependency Injection e.g., IOptions<TOptions>, Action<TOptions> and TOptions. + /// + /// The options type to be configured. + /// The to add the services to. + /// The which need to be configured by the delegate. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public static IServiceCollection AddConfiguredOptions(this IServiceCollection services, Action setup) where TOptions : class, IParameterObject, new() + { + Validator.ThrowIfNull(services); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + return services + .Configure(setup) // support for IOptions + .AddSingleton(setup) // support for Action + .AddSingleton(options); // support for TOptions + } + + /// + /// Adds an implementation of to the specified . /// - public static class ServiceCollectionExtensions + /// The type of the to add. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddMarshaller(this IServiceCollection services, Action setup = null) where TService : class, IMarshaller { - /// - /// Registers the specified as a triple-configuration for both compatibility with (and outside the confines of) Microsoft Dependency Injection e.g., IOptions<TOptions>, Action<TOptions> and TOptions. - /// - /// The options type to be configured. - /// The to add the services to. - /// The which need to be configured by the delegate. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public static IServiceCollection AddConfiguredOptions(this IServiceCollection services, Action setup) where TOptions : class, IParameterObject, new() + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); + return services.Add(o => { - Validator.ThrowIfNull(services); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - return services - .Configure(setup) // support for IOptions - .AddSingleton(setup) // support for Action - .AddSingleton(options); // support for TOptions - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IMarshaller)); + }); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddMarshaller(this IServiceCollection services, Action setup = null) where TService : class, IMarshaller + /// + /// Adds an implementation of to the specified . + /// + /// The type of the to add. + /// The to add the service to. + /// The function delegate that creates the service. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static IServiceCollection AddMarshaller(this IServiceCollection services, Func implementationFactory, Action setup = null) where TService : class, IMarshaller + { + Validator.ThrowIfNull(services); + Validator.ThrowIfNull(implementationFactory); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); + return services.Add(implementationFactory, o => { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IMarshaller)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IMarshaller)); + }); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The to add the service to. - /// The function delegate that creates the service. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null -or- - /// cannot be null. - /// - public static IServiceCollection AddMarshaller(this IServiceCollection services, Func implementationFactory, Action setup = null) where TService : class, IMarshaller + /// + /// Adds an implementation of to the specified . + /// + /// The type of the to add. + /// The to add the service to. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. + /// + /// + /// + /// + /// cannot be null. + /// + public static IServiceCollection AddDataSource(this IServiceCollection services, Action setup = null) where TService : class, IDataSource + { + Validator.ThrowIfNull(services); + var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); + return services.Add(o => { - Validator.ThrowIfNull(services); - Validator.ThrowIfNull(implementationFactory); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); - return services.Add(implementationFactory, o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IMarshaller)); - }); - } + o.Lifetime = options.Lifetime; + o.NestedTypePredicate = type => type.HasInterfaces(typeof(IDataSource)); + }); + } - /// - /// Adds an implementation of to the specified . - /// - /// The type of the to add. - /// The to add the service to. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// If the underlying type of implements interface then this is automatically handled. Also, the implementation will be type forwarded accordingly. - /// - /// - /// - /// - /// cannot be null. - /// - public static IServiceCollection AddDataSource(this IServiceCollection services, Action setup = null) where TService : class, IDataSource + /// + /// Adds Savvy I/O service locator used to resolve necessary dependencies. + /// + /// The to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddServiceLocator(this IServiceCollection services, Action setup = null) + { + Validator.ThrowIfNull(services); + var options = setup.Configure(); + services.TryAdd(typeof(IServiceLocator), options.ImplementationFactory, options.Lifetime); + return services; + } + + /// + /// Adds the to the specified if it was allowed included from . + /// + /// The to add the service to. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddHandlerServicesDescriptor(this IServiceCollection services) + { + Validator.ThrowIfNull(services); + if (services.Any(sd => sd.ServiceType == typeof(HandlerServicesDescriptor))) { - Validator.ThrowIfNull(services); - var options = (setup ?? (o => o.Lifetime = ServiceLifetime.Singleton)).Configure(); - return services.Add(o => - { - o.Lifetime = options.Lifetime; - o.NestedTypePredicate = type => type.HasInterfaces(typeof(IDataSource)); - }); + services.AddSingleton(provider => provider.GetRequiredService()); } + return services; + } - /// - /// Adds Savvy I/O service locator used to resolve necessary dependencies. - /// - /// The to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddServiceLocator(this IServiceCollection services, Action setup = null) + /// + /// Adds Savvy I/O related dispatcher- and handler- types to the specified . + /// + /// The to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static IServiceCollection AddSavvyIO(this IServiceCollection services, Action setup = null) + { + Validator.ThrowIfNull(services); + var options = setup.Configure(); + + if (options.AssembliesToScan != null) { - Validator.ThrowIfNull(services); - var options = setup.Configure(); - services.TryAdd(typeof(IServiceLocator), options.ImplementationFactory, options.Lifetime); - return services; + if (options.AllowDispatcherDiscovery) { options.AddDispatchers(options.AssembliesToScan.ToArray()); } + if (options.AllowHandlerDiscovery) { options.AddHandlers(options.AssembliesToScan.ToArray()); } } - /// - /// Adds the to the specified if it was allowed included from . - /// - /// The to add the service to. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddHandlerServicesDescriptor(this IServiceCollection services) + var descriptors = new Dictionary>>(); + foreach (var handlerType in options.HandlerImplementationTypes) { - Validator.ThrowIfNull(services); - if (services.Any(sd => sd.ServiceType == typeof(HandlerServicesDescriptor))) - { - services.AddSingleton(provider => provider.GetRequiredService()); - } - return services; + var handlerTypeServices = handlerType.GetInterfaces().Where(type => type.HasInterfaces(options.HandlerServiceTypes.ToArray())); + AddHandlersWithOptionalDescriptors(services, handlerType, handlerTypeServices, descriptors, options); } - /// - /// Adds Savvy I/O related dispatcher- and handler- types to the specified . - /// - /// The to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static IServiceCollection AddSavvyIO(this IServiceCollection services, Action setup = null) + if (options.IncludeHandlerServicesDescriptor) { - Validator.ThrowIfNull(services); - var options = setup.Configure(); - - if (options.AssembliesToScan != null) - { - if (options.AllowDispatcherDiscovery) { options.AddDispatchers(options.AssembliesToScan.ToArray()); } - if (options.AllowHandlerDiscovery) { options.AddHandlers(options.AssembliesToScan.ToArray()); } - } - - var descriptors = new Dictionary>>(); - foreach (var handlerType in options.HandlerImplementationTypes) - { - var handlerTypeServices = handlerType.GetInterfaces().Where(type => type.HasInterfaces(options.HandlerServiceTypes.ToArray())); - AddHandlersWithOptionalDescriptors(services, handlerType, handlerTypeServices, descriptors, options); - } - - if (options.IncludeHandlerServicesDescriptor) - { - services.AddSingleton(new HandlerServicesDescriptor(descriptors.Where(pair => pair.Key.HasInterfaces(options.HandlerServiceTypes.ToArray())).GroupBy(pair => pair.Key), options.HandlerServiceTypes)); - } + services.AddSingleton(new HandlerServicesDescriptor(descriptors.Where(pair => pair.Key.HasInterfaces(options.HandlerServiceTypes.ToArray())).GroupBy(pair => pair.Key), options.HandlerServiceTypes)); + } - AddDispatchers(services, options); + AddDispatchers(services, options); - return services.AddServiceLocator(o => - { - o.ImplementationFactory = options.ServiceLocatorImplementationFactory; - o.Lifetime = options.ServiceLocatorLifetime; - }); - } + return services.AddServiceLocator(o => + { + o.ImplementationFactory = options.ServiceLocatorImplementationFactory; + o.Lifetime = options.ServiceLocatorLifetime; + }); + } - private static void AddHandlersWithOptionalDescriptors(IServiceCollection services, Type handlerType, IEnumerable handlerTypeServices, Dictionary>> descriptors, SavvyioDependencyInjectionOptions options) + private static void AddHandlersWithOptionalDescriptors(IServiceCollection services, Type handlerType, IEnumerable handlerTypeServices, Dictionary>> descriptors, SavvyioDependencyInjectionOptions options) + { + foreach (var handlerTypeService in handlerTypeServices) { - foreach (var handlerTypeService in handlerTypeServices) - { - var handlers = new Hierarchy(); - if (options.IncludeHandlerServicesDescriptor) { handlers.Add(handlerType); } + var handlers = new Hierarchy(); + if (options.IncludeHandlerServicesDescriptor) { handlers.Add(handlerType); } - var handlerTypeInterfaceModel = handlerTypeService.GetInterface("IHandler`1")?.GenericTypeArguments.SingleOrDefault(); - foreach (var method in handlerType.GetTypeInfo().DeclaredMembers.Where(m => MemberIsMethodOrLambdaWithHandlerTypeInterface(m, handlerTypeInterfaceModel))) + var handlerTypeInterfaceModel = handlerTypeService.GetInterface("IHandler`1")?.GenericTypeArguments.SingleOrDefault(); + foreach (var method in handlerType.GetTypeInfo().DeclaredMembers.Where(m => MemberIsMethodOrLambdaWithHandlerTypeInterface(m, handlerTypeInterfaceModel))) + { + if (options.IncludeHandlerServicesDescriptor) { handlers.Add(method); } + if (!services.Any(sd => sd.ServiceType == handlerTypeService && sd.ImplementationType == handlerType)) { - if (options.IncludeHandlerServicesDescriptor) { handlers.Add(method); } - if (!services.Any(sd => sd.ServiceType == handlerTypeService && sd.ImplementationType == handlerType)) - { - services.Add(handlerTypeService, handlerType, options.HandlerServicesLifetime); - } + services.Add(handlerTypeService, handlerType, options.HandlerServicesLifetime); } - - AddDescriptors(handlers, handlerTypeService, descriptors, options); } + + AddDescriptors(handlers, handlerTypeService, descriptors, options); } + } - private static void AddDescriptors(Hierarchy handlers, Type handlerTypeService, Dictionary>> descriptors, SavvyioDependencyInjectionOptions options) + private static void AddDescriptors(Hierarchy handlers, Type handlerTypeService, Dictionary>> descriptors, SavvyioDependencyInjectionOptions options) + { + if (options.IncludeHandlerServicesDescriptor) { - if (options.IncludeHandlerServicesDescriptor) + if (descriptors.TryGetValue(handlerTypeService, out var list)) { - if (descriptors.TryGetValue(handlerTypeService, out var list)) - { - list.Add(handlers); - } - else - { - descriptors.Add(handlerTypeService, new List>() { handlers }); - } + list.Add(handlers); + } + else + { + descriptors.Add(handlerTypeService, new List>() { handlers }); } } + } - private static void AddDispatchers(IServiceCollection services, SavvyioDependencyInjectionOptions options) + private static void AddDispatchers(IServiceCollection services, SavvyioDependencyInjectionOptions options) + { + foreach (var dispatcherType in options.DispatcherImplementationTypes) { - foreach (var dispatcherType in options.DispatcherImplementationTypes) + var dispatcherTypeServices = dispatcherType.GetInterfaces().Where(type => type.HasInterfaces(options.DispatcherServiceTypes.ToArray())); + foreach (var dispatcherTypeService in dispatcherTypeServices) { - var dispatcherTypeServices = dispatcherType.GetInterfaces().Where(type => type.HasInterfaces(options.DispatcherServiceTypes.ToArray())); - foreach (var dispatcherTypeService in dispatcherTypeServices) - { - services.TryAdd(dispatcherTypeService, dispatcherType, options.DispatcherServicesLifetime); - } + services.TryAdd(dispatcherTypeService, dispatcherType, options.DispatcherServicesLifetime); } } + } - private static bool MemberIsMethodOrLambdaWithHandlerTypeInterface(MemberInfo m, Type handlerTypeInterfaceModel) + private static bool MemberIsMethodOrLambdaWithHandlerTypeInterface(MemberInfo m, Type handlerTypeInterfaceModel) + { + switch (m.MemberType) { - switch (m.MemberType) - { - case MemberTypes.Method: - if (m is MethodInfo mi) - { - var parameters = mi.GetParameters(); - return parameters.Any(p => p.ParameterType.HasInterfaces(handlerTypeInterfaceModel)); - } - break; - case MemberTypes.NestedType: - if (m is Type nt) + case MemberTypes.Method: + if (m is MethodInfo mi) + { + var parameters = mi.GetParameters(); + return parameters.Any(p => p.ParameterType.HasInterfaces(handlerTypeInterfaceModel)); + } + break; + case MemberTypes.NestedType: + if (m is Type nt) + { + foreach (var nestedMethod in nt.GetRuntimeMethods()) { - foreach (var nestedMethod in nt.GetRuntimeMethods()) + var parameters = nestedMethod.GetParameters(); + if (parameters.Any(p => p.ParameterType.HasInterfaces(handlerTypeInterfaceModel))) { - var parameters = nestedMethod.GetParameters(); - if (parameters.Any(p => p.ParameterType.HasInterfaces(handlerTypeInterfaceModel))) - { - return true; - } + return true; } } - break; - } - return false; + } + break; } + return false; } } diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs index 2f0e755f..09eb2ac2 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs @@ -3,39 +3,38 @@ using Microsoft.Extensions.DependencyInjection; using Savvyio.Dispatchers; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +/// +/// Configuration options for . +/// +/// +public class ServiceLocatorOptions : ServiceOptions { /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - /// - public class ServiceLocatorOptions : ServiceOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// p => new ServiceLocator(p.GetServices) + /// + /// + /// + public ServiceLocatorOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// p => new ServiceLocator(p.GetServices) - /// - /// - /// - public ServiceLocatorOptions() - { - ImplementationFactory = p => new ServiceLocator(p.GetServices); - } - - /// - /// Gets or sets the function delegate that creates an instance of an implementation. - /// - /// The function delegate that creates an instance of an implementation. - public Func ImplementationFactory { get; set; } + ImplementationFactory = p => new ServiceLocator(p.GetServices); } + + /// + /// Gets or sets the function delegate that creates an instance of an implementation. + /// + /// The function delegate that creates an instance of an implementation. + public Func ImplementationFactory { get; set; } } diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs index d0685379..2e0bf161 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs @@ -2,23 +2,22 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +/// +/// Extension methods for the interface. +/// +public static class ServiceProviderExtensions { /// - /// Extension methods for the interface. + /// Writes the handler discoveries to with . /// - public static class ServiceProviderExtensions + /// The type used to categorize the log messages. + /// The service provider used to resolve services. + public static void WriteHandlerDiscoveriesToLog(this IServiceProvider provider) { - /// - /// Writes the handler discoveries to with . - /// - /// The type used to categorize the log messages. - /// The service provider used to resolve services. - public static void WriteHandlerDiscoveriesToLog(this IServiceProvider provider) - { - var descriptor = provider.GetRequiredService(); - var logger = provider.GetRequiredService>(); - logger.LogInformation("{HandlerDiscoveries}", descriptor.ToString()); - } + var descriptor = provider.GetRequiredService(); + var logger = provider.GetRequiredService>(); + logger.LogInformation("{HandlerDiscoveries}", descriptor.ToString()); } } diff --git a/src/Savvyio.Extensions.Dispatchers/IMediator.cs b/src/Savvyio.Extensions.Dispatchers/IMediator.cs index a091353b..217b6c2c 100644 --- a/src/Savvyio.Extensions.Dispatchers/IMediator.cs +++ b/src/Savvyio.Extensions.Dispatchers/IMediator.cs @@ -3,16 +3,15 @@ using Savvyio.EventDriven; using Savvyio.Queries; -namespace Savvyio.Extensions +namespace Savvyio.Extensions; + +/// +/// Defines a mediator to encapsulate requests (Fire-and-Forget/In-Only) and request/response (Request-Reply/In-Out) message exchange patterns. +/// +/// +/// +/// +/// +public interface IMediator : ICommandDispatcher, IDomainEventDispatcher, IIntegrationEventDispatcher, IQueryDispatcher { - /// - /// Defines a mediator to encapsulate requests (Fire-and-Forget/In-Only) and request/response (Request-Reply/In-Out) message exchange patterns. - /// - /// - /// - /// - /// - public interface IMediator : ICommandDispatcher, IDomainEventDispatcher, IIntegrationEventDispatcher, IQueryDispatcher - { - } } diff --git a/src/Savvyio.Extensions.Dispatchers/Mediator.cs b/src/Savvyio.Extensions.Dispatchers/Mediator.cs index 435245cd..80f6ec19 100644 --- a/src/Savvyio.Extensions.Dispatchers/Mediator.cs +++ b/src/Savvyio.Extensions.Dispatchers/Mediator.cs @@ -7,112 +7,111 @@ using Savvyio.EventDriven; using Savvyio.Queries; -namespace Savvyio.Extensions +namespace Savvyio.Extensions; + +/// +/// Provides a default implementation of the interface. +/// +/// +public class Mediator : IMediator { + private readonly CommandDispatcher _commandDispatcher; + private readonly DomainEventDispatcher _domainEventDispatcher; + private readonly IntegrationEventDispatcher _integrationEventDispatcher; + private readonly QueryDispatcher _queryDispatcher; + /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// - public class Mediator : IMediator + /// The provider of service implementations. + public Mediator(IServiceLocator serviceLocator) { - private readonly CommandDispatcher _commandDispatcher; - private readonly DomainEventDispatcher _domainEventDispatcher; - private readonly IntegrationEventDispatcher _integrationEventDispatcher; - private readonly QueryDispatcher _queryDispatcher; - - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - public Mediator(IServiceLocator serviceLocator) - { - _commandDispatcher = new CommandDispatcher(serviceLocator); - _domainEventDispatcher = new DomainEventDispatcher(serviceLocator); - _integrationEventDispatcher = new IntegrationEventDispatcher(serviceLocator); - _queryDispatcher = new QueryDispatcher(serviceLocator); - } + _commandDispatcher = new CommandDispatcher(serviceLocator); + _domainEventDispatcher = new DomainEventDispatcher(serviceLocator); + _integrationEventDispatcher = new IntegrationEventDispatcher(serviceLocator); + _queryDispatcher = new QueryDispatcher(serviceLocator); + } - /// - /// Commits the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - public void Commit(ICommand request) - { - _commandDispatcher.Commit(request); - } + /// + /// Commits the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to commit. + public void Commit(ICommand request) + { + _commandDispatcher.Commit(request); + } - /// - /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to commit. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task CommitAsync(ICommand request, Action setup = null) - { - return _commandDispatcher.CommitAsync(request, setup); - } + /// + /// Commits the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to commit. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task CommitAsync(ICommand request, Action setup = null) + { + return _commandDispatcher.CommitAsync(request, setup); + } - /// - /// Raises the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to raise. - public void Raise(IDomainEvent request) - { - _domainEventDispatcher.Raise(request); - } + /// + /// Raises the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to raise. + public void Raise(IDomainEvent request) + { + _domainEventDispatcher.Raise(request); + } - /// - /// Raises the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to raise. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task RaiseAsync(IDomainEvent request, Action setup = null) - { - return _domainEventDispatcher.RaiseAsync(request, setup); - } + /// + /// Raises the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to raise. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task RaiseAsync(IDomainEvent request, Action setup = null) + { + return _domainEventDispatcher.RaiseAsync(request, setup); + } - /// - /// Publishes the specified using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - public void Publish(IIntegrationEvent request) - { - _integrationEventDispatcher.Publish(request); - } + /// + /// Publishes the specified using Fire-and-Forget/In-Only MEP. + /// + /// The to publish. + public void Publish(IIntegrationEvent request) + { + _integrationEventDispatcher.Publish(request); + } - /// - /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. - /// - /// The to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - public Task PublishAsync(IIntegrationEvent request, Action setup = null) - { - return _integrationEventDispatcher.PublishAsync(request, setup); - } + /// + /// Publishes the specified asynchronous using Fire-and-Forget/In-Only MEP. + /// + /// The to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public Task PublishAsync(IIntegrationEvent request, Action setup = null) + { + return _integrationEventDispatcher.PublishAsync(request, setup); + } - /// - /// Queries the specified using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// The outcome of the query operation. - public TResult Query(IQuery request) - { - return _queryDispatcher.Query(request); - } + /// + /// Queries the specified using Request-Reply/In-Out MEP. + /// + /// The type of the result to return. + /// The to request. + /// The outcome of the query operation. + public TResult Query(IQuery request) + { + return _queryDispatcher.Query(request); + } - /// - /// Queries the specified asynchronous using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. - public Task QueryAsync(IQuery request, Action setup = null) - { - return _queryDispatcher.QueryAsync(request, setup); - } + /// + /// Queries the specified asynchronous using Request-Reply/In-Out MEP. + /// + /// The type of the result to return. + /// The to request. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. + public Task QueryAsync(IQuery request, Action setup = null) + { + return _queryDispatcher.QueryAsync(request, setup); } } diff --git a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs index dd49abf1..f4ee35de 100644 --- a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs @@ -8,69 +8,68 @@ using Savvyio.Reflection; using System.Runtime.CompilerServices; -namespace Savvyio.Extensions +namespace Savvyio.Extensions; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds an implementation of the interface. + /// + /// The type of the implementation to use. + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + /// The implementation will be type forwarded to: , , and . + public static SavvyioOptions AddMediator(this SavvyioOptions options) where TImplementation : class, IMediator + { + options.AddDispatcher(); + options.AddDispatcher(); + options.AddDispatcher(); + options.AddDispatcher(); + options.AddDispatcher(); + return options; + } + + /// + /// Enforce automatic discovery of handlers implementing the interface using either or lightweight . /// - public static class SavvyioOptionsExtensions + /// The to extend. + /// true to use brute assembly scanning for all interface implementations throughout the application domain; otherwise, false. + /// A reference to so that additional configuration calls can be chained. + [MethodImpl(MethodImplOptions.NoInlining)] + public static SavvyioOptions UseAutomaticDispatcherDiscovery(this SavvyioOptions options, bool bruteAssemblyScanning = false) { - /// - /// Adds an implementation of the interface. - /// - /// The type of the implementation to use. - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - /// The implementation will be type forwarded to: , , and . - public static SavvyioOptions AddMediator(this SavvyioOptions options) where TImplementation : class, IMediator + if (bruteAssemblyScanning) { - options.AddDispatcher(); - options.AddDispatcher(); - options.AddDispatcher(); - options.AddDispatcher(); - options.AddDispatcher(); - return options; + options.AddDispatchers(AssemblyContext.CurrentDomainAssemblies.ToArray()); } - - /// - /// Enforce automatic discovery of handlers implementing the interface using either or lightweight . - /// - /// The to extend. - /// true to use brute assembly scanning for all interface implementations throughout the application domain; otherwise, false. - /// A reference to so that additional configuration calls can be chained. - [MethodImpl(MethodImplOptions.NoInlining)] - public static SavvyioOptions UseAutomaticDispatcherDiscovery(this SavvyioOptions options, bool bruteAssemblyScanning = false) + else { - if (bruteAssemblyScanning) - { - options.AddDispatchers(AssemblyContext.CurrentDomainAssemblies.ToArray()); - } - else - { - options.AddDispatchers(Assembly.GetCallingAssembly()); - } - return options; + options.AddDispatchers(Assembly.GetCallingAssembly()); } + return options; + } - /// - /// Enforce automatic discovery of dispatchers implementing the interface using either or lightweight . - /// - /// The to extend. - /// true to use brute assembly scanning for all interface implementations throughout the application domain; otherwise, false. - /// A reference to so that additional configuration calls can be chained. - [MethodImpl(MethodImplOptions.NoInlining)] - public static SavvyioOptions UseAutomaticHandlerDiscovery(this SavvyioOptions options, bool bruteAssemblyScanning = false) + /// + /// Enforce automatic discovery of dispatchers implementing the interface using either or lightweight . + /// + /// The to extend. + /// true to use brute assembly scanning for all interface implementations throughout the application domain; otherwise, false. + /// A reference to so that additional configuration calls can be chained. + [MethodImpl(MethodImplOptions.NoInlining)] + public static SavvyioOptions UseAutomaticHandlerDiscovery(this SavvyioOptions options, bool bruteAssemblyScanning = false) + { + if (bruteAssemblyScanning) { - if (bruteAssemblyScanning) - { - options.AddHandlers(AssemblyContext.CurrentDomainAssemblies.ToArray()); - } - else - { - options.AddHandlers(Assembly.GetCallingAssembly()); - } - return options; - + options.AddHandlers(AssemblyContext.CurrentDomainAssemblies.ToArray()); } + else + { + options.AddHandlers(Assembly.GetCallingAssembly()); + } + return options; + } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs index d35a4cce..087b7cfe 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs @@ -5,82 +5,81 @@ using Savvyio.Domain; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Provides a generic way for EF Core to surrogate and support an implementation of . +/// +/// The type of the entity that implements the interface. +/// The type of the key that uniquely identifies the entity. +/// +public class EfCoreTracedAggregateEntity : ITracedAggregateRoot where TEntity : class, IEntity, ITracedAggregateRoot { + private readonly IMetadataDictionary _metadata; + private readonly IReadOnlyList _events; + private readonly TKey _id; + private readonly DateTime _timestamp; + private readonly long _version; + private readonly string _type; + private readonly byte[] _payload; + + EfCoreTracedAggregateEntity() // efcore + { + } + /// - /// Provides a generic way for EF Core to surrogate and support an implementation of . + /// Initializes a new instance of the class. /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// - public class EfCoreTracedAggregateEntity : ITracedAggregateRoot where TEntity : class, IEntity, ITracedAggregateRoot + /// The traced aggregate to convert into this EF Core compatible instance. + /// The traced domain event to convert into this EF Core compatible instance. + /// The that is used when converting into a serialized format. + public EfCoreTracedAggregateEntity(TEntity aggregate, ITracedDomainEvent domainEvent, IMarshaller marshaller) { - private readonly IMetadataDictionary _metadata; - private readonly IReadOnlyList _events; - private readonly TKey _id; - private readonly DateTime _timestamp; - private readonly long _version; - private readonly string _type; - private readonly byte[] _payload; - - EfCoreTracedAggregateEntity() // efcore - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The traced aggregate to convert into this EF Core compatible instance. - /// The traced domain event to convert into this EF Core compatible instance. - /// The that is used when converting into a serialized format. - public EfCoreTracedAggregateEntity(TEntity aggregate, ITracedDomainEvent domainEvent, IMarshaller marshaller) - { - _id = aggregate.Id; - _version = domainEvent.GetAggregateVersion(); - _type = domainEvent.GetMemberType(); - _timestamp = domainEvent.GetTimestamp(); - _payload = domainEvent.ToByteArray(marshaller); - _metadata = aggregate.Metadata; - _events = domainEvent.Yield().ToList(); - } + _id = aggregate.Id; + _version = domainEvent.GetAggregateVersion(); + _type = domainEvent.GetMemberType(); + _timestamp = domainEvent.GetTimestamp(); + _payload = domainEvent.ToByteArray(marshaller); + _metadata = aggregate.Metadata; + _events = domainEvent.Yield().ToList(); + } - /// - /// Gets the value of the identifier associated with an aggregate. - /// - /// The value of the identifier associated with an aggregate. - public TKey Id => _id; + /// + /// Gets the value of the identifier associated with an aggregate. + /// + /// The value of the identifier associated with an aggregate. + public TKey Id => _id; - /// - /// Gets the timestamp of the traced domain event. - /// - /// The timestamp of the traced domain event. - public DateTime Timestamp => _timestamp; + /// + /// Gets the timestamp of the traced domain event. + /// + /// The timestamp of the traced domain event. + public DateTime Timestamp => _timestamp; - /// - /// Gets the version of the aggregate from the traced domain event. - /// - /// The version of the aggregate from the traced domain event. - public long Version => _version; + /// + /// Gets the version of the aggregate from the traced domain event. + /// + /// The version of the aggregate from the traced domain event. + public long Version => _version; - /// - /// Gets the CLR type of the traced domain event. - /// - /// The CLR type of the traced domain event. - public string Type => _type; + /// + /// Gets the CLR type of the traced domain event. + /// + /// The CLR type of the traced domain event. + public string Type => _type; - /// - /// Gets the payload of the traced domain event. - /// - /// The payload of the traced domain event. - public byte[] Payload => _payload; + /// + /// Gets the payload of the traced domain event. + /// + /// The payload of the traced domain event. + public byte[] Payload => _payload; - IMetadataDictionary IMetadata.Metadata => _metadata; + IMetadataDictionary IMetadata.Metadata => _metadata; - IReadOnlyList IAggregateRoot.Events => _events; + IReadOnlyList IAggregateRoot.Events => _events; - void IAggregateRoot.RemoveAllEvents() - { - // empty as we do not want to clear events due to dehydrate/rehydrate - } + void IAggregateRoot.RemoveAllEvents() + { + // empty as we do not want to clear events due to dehydrate/rehydrate } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs index b53bf85e..2f9ebfee 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs @@ -2,25 +2,24 @@ using Cuemon.Extensions.IO; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Extension methods for the class. +/// +public static class EfCoreTracedAggregateEntityExtensions { /// - /// Extension methods for the class. + /// Converts the specified into an implementation of interface equivalent to . /// - public static class EfCoreTracedAggregateEntityExtensions + /// The type of the entity that implements the interface. + /// The type of the key that uniquely identifies the entity. + /// The entity to convert. + /// The originating type of . + /// The that is used when converting the specified into a deserialized version of . + /// A new instance of an implementation. + public static ITracedDomainEvent ToTracedDomainEvent(this EfCoreTracedAggregateEntity entity, Type tracedDomainEventType, IMarshaller marshaller) where TEntity : class, ITracedAggregateRoot { - /// - /// Converts the specified into an implementation of interface equivalent to . - /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// The entity to convert. - /// The originating type of . - /// The that is used when converting the specified into a deserialized version of . - /// A new instance of an implementation. - public static ITracedDomainEvent ToTracedDomainEvent(this EfCoreTracedAggregateEntity entity, Type tracedDomainEventType, IMarshaller marshaller) where TEntity : class, ITracedAggregateRoot - { - return (ITracedDomainEvent)marshaller.Deserialize(entity.Payload.ToStream(), tracedDomainEventType); - } + return (ITracedDomainEvent)marshaller.Deserialize(entity.Payload.ToStream(), tracedDomainEventType); } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs index 99189a4b..361526b8 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs @@ -1,248 +1,247 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Configuration options for . +/// +public class EfCoreTracedAggregateEntityOptions : IParameterObject { + private string _payloadColumnType; + private string _payloadColumnName; + private string _typeColumnType; + private string _typeColumnName; + private string _timestampColumnType; + private string _timestampColumnName; + private string _compositePrimaryKeyVersionColumnType; + private string _compositePrimaryKeyVersionColumnName; + private string _compositePrimaryKeyIdColumnType; + private string _compositePrimaryKeyIdColumnName; + private string _tableName; + /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - public class EfCoreTracedAggregateEntityOptions : IParameterObject + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// DomainEvents + /// + /// + /// + /// id + /// + /// + /// + /// uniqueidentifier + /// + /// + /// + /// version + /// + /// + /// + /// int + /// + /// + /// + /// timestamp + /// + /// + /// + /// datetime + /// + /// + /// + /// type + /// + /// + /// + /// varchar(1024) + /// + /// + /// + /// payload + /// + /// + /// + /// varchar(max) + /// + /// + /// + public EfCoreTracedAggregateEntityOptions() { - private string _payloadColumnType; - private string _payloadColumnName; - private string _typeColumnType; - private string _typeColumnName; - private string _timestampColumnType; - private string _timestampColumnName; - private string _compositePrimaryKeyVersionColumnType; - private string _compositePrimaryKeyVersionColumnName; - private string _compositePrimaryKeyIdColumnType; - private string _compositePrimaryKeyIdColumnName; - private string _tableName; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// DomainEvents - /// - /// - /// - /// id - /// - /// - /// - /// uniqueidentifier - /// - /// - /// - /// version - /// - /// - /// - /// int - /// - /// - /// - /// timestamp - /// - /// - /// - /// datetime - /// - /// - /// - /// type - /// - /// - /// - /// varchar(1024) - /// - /// - /// - /// payload - /// - /// - /// - /// varchar(max) - /// - /// - /// - public EfCoreTracedAggregateEntityOptions() - { - TableName = "DomainEvents"; - CompositePrimaryKeyIdColumnName = "id"; - CompositePrimaryKeyIdColumnType = "uniqueidentifier"; - CompositePrimaryKeyVersionColumnName = "version"; - CompositePrimaryKeyVersionColumnType = "int"; - TimestampColumnName = "timestamp"; - TimestampColumnType = "datetime"; - TypeColumnName = "clrtype"; - TypeColumnType = "varchar(1024)"; - PayloadColumnName = "payload"; - PayloadColumnType = "varchar(max)"; - } + TableName = "DomainEvents"; + CompositePrimaryKeyIdColumnName = "id"; + CompositePrimaryKeyIdColumnType = "uniqueidentifier"; + CompositePrimaryKeyVersionColumnName = "version"; + CompositePrimaryKeyVersionColumnType = "int"; + TimestampColumnName = "timestamp"; + TimestampColumnType = "datetime"; + TypeColumnName = "clrtype"; + TypeColumnType = "varchar(1024)"; + PayloadColumnName = "payload"; + PayloadColumnType = "varchar(max)"; + } - /// - /// Gets or sets the table name of the Event Sourcing schema. - /// - /// The table name of the Event Sourcing schema. - public string TableName + /// + /// Gets or sets the table name of the Event Sourcing schema. + /// + /// The table name of the Event Sourcing schema. + public string TableName + { + get => _tableName; + set { - get => _tableName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _tableName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _tableName = value; } + } - /// - /// Gets or sets the identifier part of the composite PK column name of the Event Sourcing schema. - /// - /// The identifier part of the composite PK column name of the Event Sourcing schema. - public string CompositePrimaryKeyIdColumnName + /// + /// Gets or sets the identifier part of the composite PK column name of the Event Sourcing schema. + /// + /// The identifier part of the composite PK column name of the Event Sourcing schema. + public string CompositePrimaryKeyIdColumnName + { + get => _compositePrimaryKeyIdColumnName; + set { - get => _compositePrimaryKeyIdColumnName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _compositePrimaryKeyIdColumnName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _compositePrimaryKeyIdColumnName = value; } + } - /// - /// Gets or sets the identifier part composite PK column type of the Event Sourcing schema. - /// - /// The identifier part of the composite PK column type of the Event Sourcing schema. - public string CompositePrimaryKeyIdColumnType + /// + /// Gets or sets the identifier part composite PK column type of the Event Sourcing schema. + /// + /// The identifier part of the composite PK column type of the Event Sourcing schema. + public string CompositePrimaryKeyIdColumnType + { + get => _compositePrimaryKeyIdColumnType; + set { - get => _compositePrimaryKeyIdColumnType; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _compositePrimaryKeyIdColumnType = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _compositePrimaryKeyIdColumnType = value; } + } - /// - /// Gets or sets the version part of the composite PK column name of the Event Sourcing schema. - /// - /// The version part of the composite PK column name of the Event Sourcing schema. - public string CompositePrimaryKeyVersionColumnName + /// + /// Gets or sets the version part of the composite PK column name of the Event Sourcing schema. + /// + /// The version part of the composite PK column name of the Event Sourcing schema. + public string CompositePrimaryKeyVersionColumnName + { + get => _compositePrimaryKeyVersionColumnName; + set { - get => _compositePrimaryKeyVersionColumnName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _compositePrimaryKeyVersionColumnName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _compositePrimaryKeyVersionColumnName = value; } + } - /// - /// Gets or sets the version part composite PK column type of the Event Sourcing schema. - /// - /// The version part of the composite PK column type of the Event Sourcing schema. - public string CompositePrimaryKeyVersionColumnType + /// + /// Gets or sets the version part composite PK column type of the Event Sourcing schema. + /// + /// The version part of the composite PK column type of the Event Sourcing schema. + public string CompositePrimaryKeyVersionColumnType + { + get => _compositePrimaryKeyVersionColumnType; + set { - get => _compositePrimaryKeyVersionColumnType; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _compositePrimaryKeyVersionColumnType = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _compositePrimaryKeyVersionColumnType = value; } + } - /// - /// Gets or sets the timestamp column name of the Event Sourcing schema. - /// - /// The timestamp column name of the Event Sourcing schema. - public string TimestampColumnName + /// + /// Gets or sets the timestamp column name of the Event Sourcing schema. + /// + /// The timestamp column name of the Event Sourcing schema. + public string TimestampColumnName + { + get => _timestampColumnName; + set { - get => _timestampColumnName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _timestampColumnName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _timestampColumnName = value; } + } - /// - /// Gets or sets the timestamp column type of the Event Sourcing schema. - /// - /// The timestamp column type of the Event Sourcing schema. - public string TimestampColumnType + /// + /// Gets or sets the timestamp column type of the Event Sourcing schema. + /// + /// The timestamp column type of the Event Sourcing schema. + public string TimestampColumnType + { + get => _timestampColumnType; + set { - get => _timestampColumnType; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _timestampColumnType = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _timestampColumnType = value; } + } - /// - /// Gets or sets the CLR type column name of the Event Sourcing schema. - /// - /// The CLR type column name of the Event Sourcing schema. - public string TypeColumnName + /// + /// Gets or sets the CLR type column name of the Event Sourcing schema. + /// + /// The CLR type column name of the Event Sourcing schema. + public string TypeColumnName + { + get => _typeColumnName; + set { - get => _typeColumnName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _typeColumnName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _typeColumnName = value; } + } - /// - /// Gets or sets the CLR type column type of the Event Sourcing schema. - /// - /// The CLR type column type of the Event Sourcing schema. - public string TypeColumnType + /// + /// Gets or sets the CLR type column type of the Event Sourcing schema. + /// + /// The CLR type column type of the Event Sourcing schema. + public string TypeColumnType + { + get => _typeColumnType; + set { - get => _typeColumnType; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _typeColumnType = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _typeColumnType = value; } + } - /// - /// Gets or sets the payload (serialized data) column name of the Event Sourcing schema. - /// - /// The payload (serialized data) column name of the Event Sourcing schema. - public string PayloadColumnName + /// + /// Gets or sets the payload (serialized data) column name of the Event Sourcing schema. + /// + /// The payload (serialized data) column name of the Event Sourcing schema. + public string PayloadColumnName + { + get => _payloadColumnName; + set { - get => _payloadColumnName; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _payloadColumnName = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _payloadColumnName = value; } + } - /// - /// Gets or sets the payload (serialized data) column type of the Event Sourcing schema. - /// - /// The payload (serialized data) column type of the Event Sourcing schema. - public string PayloadColumnType + /// + /// Gets or sets the payload (serialized data) column type of the Event Sourcing schema. + /// + /// The payload (serialized data) column type of the Event Sourcing schema. + public string PayloadColumnType + { + get => _payloadColumnType; + set { - get => _payloadColumnType; - set - { - Validator.ThrowIfNullOrWhitespace(value); - _payloadColumnType = value; - } + Validator.ThrowIfNullOrWhitespace(value); + _payloadColumnType = value; } } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs index 7f3e07c6..9025388a 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs @@ -8,78 +8,77 @@ using Savvyio.Domain; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design and Event Sourcing. +/// +/// The type of the entity that implements the interface. +/// The type of the key that uniquely identifies the entity. +/// +/// +public class EfCoreTracedAggregateRepository : ITracedAggregateRepository + where TEntity : class, IEntity, ITracedAggregateRoot { + private readonly EfCoreRepository, TKey> _repository; + private readonly IMarshaller _marshaller; + /// - /// Provides an implementation of the that is optimized for Domain Driven Design and Event Sourcing. + /// Initializes a new instance of the class. /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// - /// - public class EfCoreTracedAggregateRepository : ITracedAggregateRepository - where TEntity : class, IEntity, ITracedAggregateRoot + /// The that handles actual I/O communication with a source of data. + /// The that is used when converting between and arbitrary data. + public EfCoreTracedAggregateRepository(IEfCoreDataSource source, IMarshaller marshaller) { - private readonly EfCoreRepository, TKey> _repository; - private readonly IMarshaller _marshaller; + _repository = new EfCoreRepository, TKey>(source); + _marshaller = marshaller; + } - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - /// The that is used when converting between and arbitrary data. - public EfCoreTracedAggregateRepository(IEfCoreDataSource source, IMarshaller marshaller) + /// + /// Loads an aggregate from the specified asynchronous. + /// + /// The key that uniquely identifies the aggregate. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. + /// + /// does not have a suitable constructor. + /// + public async Task GetByIdAsync(TKey id, Action setup = null) + { + var entities = await _repository.FindAllAsync(entity => entity.Id.Equals(id), setup).ConfigureAwait(false); + var events = entities.OrderBy(entity => entity.Version).Select(entity => entity.ToTracedDomainEvent(Type.GetType(entity.Type), _marshaller)); + try { - _repository = new EfCoreRepository, TKey>(source); - _marshaller = marshaller; + return ActivatorFactory.CreateInstance, TEntity>(id, events, o => o.Flags = new MemberReflection()); } - - /// - /// Loads an aggregate from the specified asynchronous. - /// - /// The key that uniquely identifies the aggregate. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. - /// - /// does not have a suitable constructor. - /// - public async Task GetByIdAsync(TKey id, Action setup = null) + catch (MissingMethodException e) { - var entities = await _repository.FindAllAsync(entity => entity.Id.Equals(id), setup).ConfigureAwait(false); - var events = entities.OrderBy(entity => entity.Version).Select(entity => entity.ToTracedDomainEvent(Type.GetType(entity.Type), _marshaller)); - try - { - return ActivatorFactory.CreateInstance, TEntity>(id, events, o => o.Flags = new MemberReflection()); - } - catch (MissingMethodException e) - { - throw new MissingMethodException($"Constructor on type '{typeof(TEntity).Name}' not found. Please add a private constructor with this signature: '{typeof(TEntity).Name}({typeof(TKey).Name}, {typeof(IEnumerable).ToFriendlyName()})'.", e); - } + throw new MissingMethodException($"Constructor on type '{typeof(TEntity).Name}' not found. Please add a private constructor with this signature: '{typeof(TEntity).Name}({typeof(TKey).Name}, {typeof(IEnumerable).ToFriendlyName()})'.", e); } + } - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The aggregate to add. - public void Add(TEntity entity) + /// + /// Marks the specified to be added in the data store when is called. + /// + /// The aggregate to add. + public void Add(TEntity entity) + { + foreach (var current in entity.Events) { - foreach (var current in entity.Events) - { - _repository.Add(new EfCoreTracedAggregateEntity(entity, current, _marshaller)); - } - entity.RemoveAllEvents(); + _repository.Add(new EfCoreTracedAggregateEntity(entity, current, _marshaller)); } + entity.RemoveAllEvents(); + } - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The aggregates to add. - public void AddRange(IEnumerable entities) + /// + /// Marks the specified to be added in the data store when is called. + /// + /// The aggregates to add. + public void AddRange(IEnumerable entities) + { + foreach (var entity in entities) { - foreach (var entity in entities) - { - Add(entity); - } + Add(entity); } } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs index d54cd593..81f5204f 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs @@ -3,44 +3,43 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Extension methods for the class. +/// +public static class ModelBuilderExtensions { /// - /// Extension methods for the class. + /// Adds a default implementation of an EF Core compatible Event Sourcing model. /// - public static class ModelBuilderExtensions + /// The type of the entity that implements the interface. + /// The type of the key that uniquely identifies the entity. + /// The to extend. + /// The which may be configured. + /// A reference to so that additional configuration calls can be chained. + public static ModelBuilder AddEventSourcing(this ModelBuilder mb, Action setup = null) where TEntity : class, ITracedAggregateRoot { - /// - /// Adds a default implementation of an EF Core compatible Event Sourcing model. - /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// The to extend. - /// The which may be configured. - /// A reference to so that additional configuration calls can be chained. - public static ModelBuilder AddEventSourcing(this ModelBuilder mb, Action setup = null) where TEntity : class, ITracedAggregateRoot + var options = setup.Configure(); + return mb.Entity>(entity => { - var options = setup.Configure(); - return mb.Entity>(entity => - { - entity.ToTable(options.TableName); - entity.HasKey(es => new { es.Id, es.Version }); - entity.Property(es => es.Id) - .HasColumnName(options.CompositePrimaryKeyIdColumnName) - .HasColumnType(options.CompositePrimaryKeyIdColumnType); - entity.Property(es => es.Version) - .HasColumnName(options.CompositePrimaryKeyVersionColumnName) - .HasColumnType(options.CompositePrimaryKeyVersionColumnType); - entity.Property(es => es.Timestamp) - .HasColumnName(options.TimestampColumnName) - .HasColumnType(options.TimestampColumnType); - entity.Property(es => es.Type) - .HasColumnName(options.TypeColumnName) - .HasColumnType(options.TypeColumnType); - entity.Property(es => es.Payload) - .HasColumnName(options.PayloadColumnName) - .HasColumnType(options.PayloadColumnType); - }); - } + entity.ToTable(options.TableName); + entity.HasKey(es => new { es.Id, es.Version }); + entity.Property(es => es.Id) + .HasColumnName(options.CompositePrimaryKeyIdColumnName) + .HasColumnType(options.CompositePrimaryKeyIdColumnType); + entity.Property(es => es.Version) + .HasColumnName(options.CompositePrimaryKeyVersionColumnName) + .HasColumnType(options.CompositePrimaryKeyVersionColumnType); + entity.Property(es => es.Timestamp) + .HasColumnName(options.TimestampColumnName) + .HasColumnType(options.TimestampColumnType); + entity.Property(es => es.Type) + .HasColumnName(options.TypeColumnName) + .HasColumnType(options.TypeColumnType); + entity.Property(es => es.Payload) + .HasColumnName(options.PayloadColumnName) + .HasColumnType(options.PayloadColumnType); + }); } } diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs index 521c58f2..7adc9d03 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs @@ -1,23 +1,22 @@ using Cuemon.Extensions.IO; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +/// +/// Extension methods for the interface. +/// +public static class TracedDomainEventExtensions { /// - /// Extension methods for the interface. + /// Converts the specified into an array of bytes. /// - public static class TracedDomainEventExtensions + /// The domain event to convert. + /// The that is used when converting into an array of bytes. + /// A byte[] that is equivalent to . + public static byte[] ToByteArray(this ITracedDomainEvent domainEvent, IMarshaller marshaller) { - /// - /// Converts the specified into an array of bytes. - /// - /// The domain event to convert. - /// The that is used when converting into an array of bytes. - /// A byte[] that is equivalent to . - public static byte[] ToByteArray(this ITracedDomainEvent domainEvent, IMarshaller marshaller) - { - var bytes = marshaller.Serialize(domainEvent, typeof(ITracedDomainEvent)).ToByteArray(); - return bytes; - } + var bytes = marshaller.Serialize(domainEvent, typeof(ITracedDomainEvent)).ToByteArray(); + return bytes; } } diff --git a/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs index 9d210f74..fbde6e15 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs @@ -7,55 +7,54 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore.Domain +namespace Savvyio.Extensions.EFCore.Domain; + +/// +/// Extension methods for the interface. +/// +public static class DomainEventDispatcherExtensions { /// - /// Extension methods for the interface. + /// Raises domain events from the specified to handlers that implements the interface. /// - public static class DomainEventDispatcherExtensions + /// The to extend. + /// The to extract aggregate(s) and publish domain events from. + public static void RaiseMany(this IDomainEventDispatcher dispatcher, DbContext context) { - /// - /// Raises domain events from the specified to handlers that implements the interface. - /// - /// The to extend. - /// The to extract aggregate(s) and publish domain events from. - public static void RaiseMany(this IDomainEventDispatcher dispatcher, DbContext context) + var domainEvents = ExtractDomainEvents(context); + foreach (var de in domainEvents) { - var domainEvents = ExtractDomainEvents(context); - foreach (var de in domainEvents) - { - dispatcher.Raise(de); - } + dispatcher.Raise(de); } + } - /// - /// Asynchronously raises domain events from the specified to handlers that implements the interface. - /// - /// The to extend. - /// The to extract aggregate(s) and publish domain events from. - /// The which may be configured. - /// A that represents the asynchronous operation. - public static async Task RaiseManyAsync(this IDomainEventDispatcher dispatcher, DbContext context, Action setup = null) + /// + /// Asynchronously raises domain events from the specified to handlers that implements the interface. + /// + /// The to extend. + /// The to extract aggregate(s) and publish domain events from. + /// The which may be configured. + /// A that represents the asynchronous operation. + public static async Task RaiseManyAsync(this IDomainEventDispatcher dispatcher, DbContext context, Action setup = null) + { + var domainEvents = ExtractDomainEvents(context); + foreach (var de in domainEvents) { - var domainEvents = ExtractDomainEvents(context); - foreach (var de in domainEvents) - { - await dispatcher.RaiseAsync(de, setup).ConfigureAwait(false); - } + await dispatcher.RaiseAsync(de, setup).ConfigureAwait(false); } + } - private static IEnumerable ExtractDomainEvents(DbContext context) + private static IEnumerable ExtractDomainEvents(DbContext context) + { + var entries = context.ChangeTracker.Entries>().Where(entry => entry.Entity.Events.Any()).ToList(); + foreach (var aggregate in entries.Select(entry => entry.Entity)) { - var entries = context.ChangeTracker.Entries>().Where(entry => entry.Entity.Events.Any()).ToList(); - foreach (var aggregate in entries.Select(entry => entry.Entity)) + var events = aggregate.Events.ToList(); + var eventsType = events.First().GetType(); + if (eventsType.HasInterfaces(typeof(IDomainEvent))) { aggregate.RemoveAllEvents(); } + foreach (var e in events) { - var events = aggregate.Events.ToList(); - var eventsType = events.First().GetType(); - if (eventsType.HasInterfaces(typeof(IDomainEvent))) { aggregate.RemoveAllEvents(); } - foreach (var e in events) - { - yield return e.MergeMetadata(aggregate); - } + yield return e.MergeMetadata(aggregate); } } } diff --git a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs index c1533ed1..316186b9 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs @@ -5,49 +5,48 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore.Domain +namespace Savvyio.Extensions.EFCore.Domain; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design and the concept of Aggregate Root. +/// +/// +public class EfCoreAggregateDataSource : EfCoreDataSource { + private readonly IDomainEventDispatcher _dispatcher; + /// - /// Provides an implementation of the that is optimized for Domain Driven Design and the concept of Aggregate Root. + /// Initializes a new instance of the class. /// - /// - public class EfCoreAggregateDataSource : EfCoreDataSource + /// The that are responsible for raising domain events. + /// The to associate with this data store. + protected EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, DbContext dbContext) : base(dbContext) { - private readonly IDomainEventDispatcher _dispatcher; - - /// - /// Initializes a new instance of the class. - /// - /// The that are responsible for raising domain events. - /// The to associate with this data store. - protected EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, DbContext dbContext) : base(dbContext) - { - _dispatcher = dispatcher; - } + _dispatcher = dispatcher; + } - /// - /// Initializes a new instance of the class. - /// - /// The that are responsible for raising domain events. - /// The used to configure this instance. - public EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options) : base(options) - { - _dispatcher = dispatcher; - } + /// + /// Initializes a new instance of the class. + /// + /// The that are responsible for raising domain events. + /// The used to configure this instance. + public EfCoreAggregateDataSource(IDomainEventDispatcher dispatcher, EfCoreDataSourceOptions options) : base(options) + { + _dispatcher = dispatcher; + } - /// - /// Saves the different implementations as one transaction towards a data store asynchronous. - /// - /// The which may be configured. - /// A that represents the asynchronous operation. - /// Will, just before is called, extract and call for all aggregate roots contained within the backing . - public override async Task SaveChangesAsync(Action setup = null) + /// + /// Saves the different implementations as one transaction towards a data store asynchronous. + /// + /// The which may be configured. + /// A that represents the asynchronous operation. + /// Will, just before is called, extract and call for all aggregate roots contained within the backing . + public override async Task SaveChangesAsync(Action setup = null) + { + if (_dispatcher != null) { - if (_dispatcher != null) - { - await _dispatcher.RaiseManyAsync(DbContext, setup).ConfigureAwait(false); - } - await base.SaveChangesAsync(setup).ConfigureAwait(false); + await _dispatcher.RaiseManyAsync(DbContext, setup).ConfigureAwait(false); } + await base.SaveChangesAsync(setup).ConfigureAwait(false); } } diff --git a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs index 2a3dad65..4780b453 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs @@ -1,21 +1,20 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore.Domain +namespace Savvyio.Extensions.EFCore.Domain; + +/// +/// Provides an implementation of the that is optimized for Domain Driven Design. +/// +/// The type of the entity that implements the interface. +/// The type of the key that uniquely identifies the entity. +/// +public class EfCoreAggregateRepository : EfCoreRepository, IAggregateRepository where TEntity : class, IAggregateRoot { /// - /// Provides an implementation of the that is optimized for Domain Driven Design. + /// Initializes a new instance of the class. /// - /// The type of the entity that implements the interface. - /// The type of the key that uniquely identifies the entity. - /// - public class EfCoreAggregateRepository : EfCoreRepository, IAggregateRepository where TEntity : class, IAggregateRoot + /// The that handles actual I/O communication with a source of data. + public EfCoreAggregateRepository(IEfCoreDataSource source) : base(source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreAggregateRepository(IEfCoreDataSource source) : base(source) - { - } } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs index 1f6a7c89..7689b3c1 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs @@ -6,63 +6,62 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// +/// +public class EfCoreDataSource : Disposable, IEfCoreDataSource { /// - /// Provides a default implementation of the interface to support the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// - /// - public class EfCoreDataSource : Disposable, IEfCoreDataSource + /// The to associate with this data store. + protected EfCoreDataSource(DbContext dbContext) { - /// - /// Initializes a new instance of the class. - /// - /// The to associate with this data store. - protected EfCoreDataSource(DbContext dbContext) - { - DbContext = dbContext; - } + DbContext = dbContext; + } - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - public EfCoreDataSource(EfCoreDataSourceOptions options) - { - DbContext = new EfCoreDbContext(options); - } + /// + /// Initializes a new instance of the class. + /// + /// The used to configure this instance. + public EfCoreDataSource(EfCoreDataSourceOptions options) + { + DbContext = new EfCoreDbContext(options); + } - /// - /// Gets the session of this data source. - /// - /// The session of this data source. - public DbContext DbContext { get; } + /// + /// Gets the session of this data source. + /// + /// The session of this data source. + public DbContext DbContext { get; } - /// - /// Creates a that can be used to query and save instances of . - /// - /// The type of entity for which a set should be returned. - /// A set for the given entity type. - public DbSet Set() where TEntity : class => DbContext.Set(); + /// + /// Creates a that can be used to query and save instances of . + /// + /// The type of entity for which a set should be returned. + /// A set for the given entity type. + public DbSet Set() where TEntity : class => DbContext.Set(); - /// - /// Saves the different implementations as one transaction towards a data store asynchronous. - /// - /// The which may be configured. - /// A that represents the asynchronous operation. - public virtual async Task SaveChangesAsync(Action setup = null) - { - var options = setup.Configure(); - await DbContext.SaveChangesAsync(options.CancellationToken).ConfigureAwait(false); - } + /// + /// Saves the different implementations as one transaction towards a data store asynchronous. + /// + /// The which may be configured. + /// A that represents the asynchronous operation. + public virtual async Task SaveChangesAsync(Action setup = null) + { + var options = setup.Configure(); + await DbContext.SaveChangesAsync(options.CancellationToken).ConfigureAwait(false); + } - /// - /// Called when this object is being disposed by either or having disposing set to true and is false. - /// - protected override void OnDisposeManagedResources() - { - DbContext?.Dispose(); - } + /// + /// Called when this object is being disposed by either or having disposing set to true and is false. + /// + protected override void OnDisposeManagedResources() + { + DbContext?.Dispose(); } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs index 685199a1..cba02726 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs @@ -2,36 +2,35 @@ using Cuemon.Configuration; using Microsoft.EntityFrameworkCore; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Configuration options for . +/// +public class EfCoreDataSourceOptions : IParameterObject { /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - public class EfCoreDataSourceOptions : IParameterObject + public EfCoreDataSourceOptions() { - /// - /// Initializes a new instance of the class. - /// - public EfCoreDataSourceOptions() - { - } + } - /// - /// Gets or sets the delegate responsible for configuring the model of the . - /// - /// The delegate responsible for configuring the model of the . - public Action ModelConstructor { get; set; } + /// + /// Gets or sets the delegate responsible for configuring the model of the . + /// + /// The delegate responsible for configuring the model of the . + public Action ModelConstructor { get; set; } - /// - /// Gets or sets the delegate responsible for configuring defaults and conventions of the . - /// - /// The delegate responsible for configuring defaults and conventions of the . - public Action ConventionsConfigurator { get; set; } + /// + /// Gets or sets the delegate responsible for configuring defaults and conventions of the . + /// + /// The delegate responsible for configuring defaults and conventions of the . + public Action ConventionsConfigurator { get; set; } - /// - /// Gets or sets the delegate responsible for configuring the . - /// - /// The delegate responsible for configuring the . - public Action ContextConfigurator { get; set; } - } + /// + /// Gets or sets the delegate responsible for configuring the . + /// + /// The delegate responsible for configuring the . + public Action ContextConfigurator { get; set; } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs index 7c63fa6b..5d500281 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs @@ -9,96 +9,95 @@ using Savvyio.Data; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Provides a default implementation of the interface to serve as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type of the DTO. +/// +/// +public class EfCoreDataStore : IPersistentDataStore> where T : class { /// - /// Provides a default implementation of the interface to serve as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// The type of the DTO. - /// - /// - public class EfCoreDataStore : IPersistentDataStore> where T : class + /// The that handles actual I/O communication with a source of data. + public EfCoreDataStore(IEfCoreDataSource source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreDataStore(IEfCoreDataSource source) - { - Validator.ThrowIfNull(source); - Set = source.Set(); - UnitOfWork = source; - } + Validator.ThrowIfNull(source); + Set = source.Set(); + UnitOfWork = source; + } - /// - /// Gets a that can be used to query and save instances of . - /// - /// The that can be used to query and save instances of . - protected DbSet Set { get; } + /// + /// Gets a that can be used to query and save instances of . + /// + /// The that can be used to query and save instances of . + protected DbSet Set { get; } - /// - /// Gets a that can be used to save instances of . - /// - /// The that can be used to save instances of . - protected IUnitOfWork UnitOfWork { get; } + /// + /// Gets a that can be used to save instances of . + /// + /// The that can be used to save instances of . + protected IUnitOfWork UnitOfWork { get; } - /// - /// Creates the specified asynchronous in the associated . - /// - /// The object to create in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public virtual async Task CreateAsync(T dto, Action setup = null) - { - Set.Add(dto); - await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); - } + /// + /// Creates the specified asynchronous in the associated . + /// + /// The object to create in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public virtual async Task CreateAsync(T dto, Action setup = null) + { + Set.Add(dto); + await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); + } - /// - /// Updates the specified asynchronous in the associated . - /// - /// The object to update in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public virtual async Task UpdateAsync(T dto, Action setup = null) - { - Set.Update(dto); - await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); - } + /// + /// Updates the specified asynchronous in the associated . + /// + /// The object to update in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public virtual async Task UpdateAsync(T dto, Action setup = null) + { + Set.Update(dto); + await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); + } - /// - /// Loads the object from the specified asynchronous. - /// - /// The key that uniquely identifies the object. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. - public virtual Task GetByIdAsync(object id, Action setup = null) - { - var options = setup.Configure(); - return Set.FindAsync(new[] { id }, options.CancellationToken).AsTask(); - } + /// + /// Loads the object from the specified asynchronous. + /// + /// The key that uniquely identifies the object. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the object of the operation or null if not found. + public virtual Task GetByIdAsync(object id, Action setup = null) + { + var options = setup.Configure(); + return Set.FindAsync(new[] { id }, options.CancellationToken).AsTask(); + } - /// - /// Finds all objects matching the specified asynchronous in the associated . - /// - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. - public virtual async Task> FindAllAsync(Action> setup = null) - { - var options = setup.Configure(); - return await (options.Predicate == null ? Set.ToListAsync(options.CancellationToken).ConfigureAwait(false) : Set.Where(options.Predicate).ToListAsync(options.CancellationToken).ConfigureAwait(false)); - } + /// + /// Finds all objects matching the specified asynchronous in the associated . + /// + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the matching objects of the operation or an empty sequence if no match was found. + public virtual async Task> FindAllAsync(Action> setup = null) + { + var options = setup.Configure(); + return await (options.Predicate == null ? Set.ToListAsync(options.CancellationToken).ConfigureAwait(false) : Set.Where(options.Predicate).ToListAsync(options.CancellationToken).ConfigureAwait(false)); + } - /// - /// Deletes the specified asynchronous in the associated . - /// - /// The object to delete in the associated . - /// The which may be configured. - /// A that represents the asynchronous operation. - public virtual async Task DeleteAsync(T dto, Action setup = null) - { - Set.Remove(dto); - await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); - } + /// + /// Deletes the specified asynchronous in the associated . + /// + /// The object to delete in the associated . + /// The which may be configured. + /// A that represents the asynchronous operation. + public virtual async Task DeleteAsync(T dto, Action setup = null) + { + Set.Remove(dto); + await UnitOfWork.SaveChangesAsync(setup).ConfigureAwait(false); } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs b/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs index 32201fab..cd4918ed 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs @@ -1,85 +1,84 @@ using Cuemon.Configuration; using Microsoft.EntityFrameworkCore; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Provides a default implementation of the class to support Savvy I/O extensions of Microsoft Entity Framework Core. +/// +/// +/// +public class EfCoreDbContext : DbContext, IConfigurable { /// - /// Provides a default implementation of the class to support Savvy I/O extensions of Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// - /// - public class EfCoreDbContext : DbContext, IConfigurable + /// The used to configure this instance. + public EfCoreDbContext(EfCoreDataSourceOptions options) { - /// - /// Initializes a new instance of the class. - /// - /// The used to configure this instance. - public EfCoreDbContext(EfCoreDataSourceOptions options) - { - Options = options ?? new EfCoreDataSourceOptions(); - } - - /// - /// - /// Override this method to configure the database (and other options) to be used for this context. - /// This method is called for each instance of the context that is created. - /// The base implementation does nothing. - /// - /// - /// In situations where an instance of may or may not have been passed - /// to the constructor, you can use to determine if - /// the options have already been set, and skip some or all of the logic in - /// . - /// - /// - /// A builder used to create or modify options for this context. Databases (and other extensions) - /// typically define extension methods on this object that allow you to configure the context. - /// See DbContext lifetime, configuration, and initialization - /// for more information. - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - base.OnConfiguring(optionsBuilder); - Options.ContextConfigurator?.Invoke(optionsBuilder); - } + Options = options ?? new EfCoreDataSourceOptions(); + } - /// - /// Override this method to set defaults and configure conventions before they run. This method is invoked before - /// . - /// - /// The builder being used to set defaults and configure conventions that will be used to build the model for this context. - /// If a model is explicitly set on the options for this context (via ) - /// then this method will not be run. - protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - base.ConfigureConventions(configurationBuilder); - Options.ConventionsConfigurator?.Invoke(configurationBuilder); - } + /// + /// + /// Override this method to configure the database (and other options) to be used for this context. + /// This method is called for each instance of the context that is created. + /// The base implementation does nothing. + /// + /// + /// In situations where an instance of may or may not have been passed + /// to the constructor, you can use to determine if + /// the options have already been set, and skip some or all of the logic in + /// . + /// + /// + /// A builder used to create or modify options for this context. Databases (and other extensions) + /// typically define extension methods on this object that allow you to configure the context. + /// See DbContext lifetime, configuration, and initialization + /// for more information. + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + Options.ContextConfigurator?.Invoke(optionsBuilder); + } - /// - /// Override this method to further configure the model that was discovered by convention from the entity types - /// exposed in properties on your derived context. The resulting model may be cached - /// and re-used for subsequent instances of your derived context. - /// - /// The builder being used to construct the model for this context. Databases (and other extensions) typically - /// define extension methods on this object that allow you to configure aspects of the model that are specific - /// to a given database. - /// - /// If a model is explicitly set on the options for this context (via ) - /// then this method will not be run. - /// - /// - /// See Modeling entity types and relationships for more information. - /// - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - Options.ModelConstructor?.Invoke(modelBuilder); - } + /// + /// Override this method to set defaults and configure conventions before they run. This method is invoked before + /// . + /// + /// The builder being used to set defaults and configure conventions that will be used to build the model for this context. + /// If a model is explicitly set on the options for this context (via ) + /// then this method will not be run. + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + Options.ConventionsConfigurator?.Invoke(configurationBuilder); + } - /// - /// Gets the configured options of this instance. - /// - /// The configured options of this instance. - public EfCoreDataSourceOptions Options { get; } + /// + /// Override this method to further configure the model that was discovered by convention from the entity types + /// exposed in properties on your derived context. The resulting model may be cached + /// and re-used for subsequent instances of your derived context. + /// + /// The builder being used to construct the model for this context. Databases (and other extensions) typically + /// define extension methods on this object that allow you to configure aspects of the model that are specific + /// to a given database. + /// + /// If a model is explicitly set on the options for this context (via ) + /// then this method will not be run. + /// + /// + /// See Modeling entity types and relationships for more information. + /// + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + Options.ModelConstructor?.Invoke(modelBuilder); } + + /// + /// Gets the configured options of this instance. + /// + /// The configured options of this instance. + public EfCoreDataSourceOptions Options { get; } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs b/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs index 6f2fc628..6b97a884 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs @@ -2,42 +2,41 @@ using System.Linq.Expressions; using Cuemon.Threading; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Specifies options that is related to . +/// +/// +public class EfCoreQueryOptions : AsyncOptions { /// - /// Specifies options that is related to . + /// Initializes a new instance of the class. /// - /// - public class EfCoreQueryOptions : AsyncOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// null + /// + /// + /// + /// default + /// + /// + /// + public EfCoreQueryOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// null - /// - /// - /// - /// default - /// - /// - /// - public EfCoreQueryOptions() - { - } - - /// - /// Gets or sets the predicate that matches one or more objects to retrieve in the associated . - /// - /// The predicate that matches one or more objects to retrieve in the associated . - public Expression> Predicate { get; set; } } + + /// + /// Gets or sets the predicate that matches one or more objects to retrieve in the associated . + /// + /// The predicate that matches one or more objects to retrieve in the associated . + public Expression> Predicate { get; set; } } diff --git a/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs b/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs index 094ced42..ebb2a772 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs @@ -9,90 +9,89 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Provides a default implementation of the interface to serve as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. +/// +/// The type of the entity. +/// The type of the key that uniquely identifies the entity. +/// +public class EfCoreRepository : IPersistentRepository where TEntity : class, IIdentity { /// - /// Provides a default implementation of the interface to serve as an abstraction layer before the actual I/O communication with a source of data using Microsoft Entity Framework Core. + /// Initializes a new instance of the class. /// - /// The type of the entity. - /// The type of the key that uniquely identifies the entity. - /// - public class EfCoreRepository : IPersistentRepository where TEntity : class, IIdentity + /// The that handles actual I/O communication with a source of data. + public EfCoreRepository(IEfCoreDataSource source) { - /// - /// Initializes a new instance of the class. - /// - /// The that handles actual I/O communication with a source of data. - public EfCoreRepository(IEfCoreDataSource source) - { - Validator.ThrowIfNull(source); - Set = source.Set(); - } + Validator.ThrowIfNull(source); + Set = source.Set(); + } - /// - /// Gets the associated for this repository. - /// - /// The associated for this repository. - protected DbSet Set { get; } + /// + /// Gets the associated for this repository. + /// + /// The associated for this repository. + protected DbSet Set { get; } - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The entity to add. - public virtual void Add(TEntity entity) - { - Set.Add(entity); - } + /// + /// Marks the specified to be added in the data store when is called. + /// + /// The entity to add. + public virtual void Add(TEntity entity) + { + Set.Add(entity); + } - /// - /// Marks the specified to be added in the data store when is called. - /// - /// The entities to add. - public virtual void AddRange(IEnumerable entities) - { - Set.AddRange(entities); - } + /// + /// Marks the specified to be added in the data store when is called. + /// + /// The entities to add. + public virtual void AddRange(IEnumerable entities) + { + Set.AddRange(entities); + } - /// - /// Loads the entity from the specified asynchronous. - /// - /// The key that uniquely identifies the entity. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. - public virtual Task GetByIdAsync(TKey id, Action setup = null) - { - var options = setup.Configure(); - return Set.FindAsync(new object[] { id }, options.CancellationToken).AsTask(); - } + /// + /// Loads the entity from the specified asynchronous. + /// + /// The key that uniquely identifies the entity. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the entity of the operation or null if not found. + public virtual Task GetByIdAsync(TKey id, Action setup = null) + { + var options = setup.Configure(); + return Set.FindAsync(new object[] { id }, options.CancellationToken).AsTask(); + } - /// - /// Finds all entities matching the specified asynchronous. - /// - /// The predicate that matches the entities to retrieve. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result either contains the matching entities of the operation or an empty sequence if no match was found. - public virtual async Task> FindAllAsync(Expression> predicate = null, Action setup = null) - { - var options = setup.Configure(); - return await (predicate == null ? Set.ToListAsync(options.CancellationToken).ConfigureAwait(false) : Set.Where(predicate).ToListAsync(options.CancellationToken).ConfigureAwait(false)); - } + /// + /// Finds all entities matching the specified asynchronous. + /// + /// The predicate that matches the entities to retrieve. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result either contains the matching entities of the operation or an empty sequence if no match was found. + public virtual async Task> FindAllAsync(Expression> predicate = null, Action setup = null) + { + var options = setup.Configure(); + return await (predicate == null ? Set.ToListAsync(options.CancellationToken).ConfigureAwait(false) : Set.Where(predicate).ToListAsync(options.CancellationToken).ConfigureAwait(false)); + } - /// - /// Marks the specified to be removed from the data store when is called. - /// - /// The entity to remove. - public virtual void Remove(TEntity entity) - { - Set.Remove(entity); - } + /// + /// Marks the specified to be removed from the data store when is called. + /// + /// The entity to remove. + public virtual void Remove(TEntity entity) + { + Set.Remove(entity); + } - /// - /// Marks the specified to be removed from the data store when is called. - /// - /// The entities to remove. - public virtual void RemoveRange(IEnumerable entities) - { - Set.RemoveRange(entities); - } + /// + /// Marks the specified to be removed from the data store when is called. + /// + /// The entities to remove. + public virtual void RemoveRange(IEnumerable entities) + { + Set.RemoveRange(entities); } } diff --git a/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs b/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs index ed1967b3..2317c035 100644 --- a/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs +++ b/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs @@ -1,19 +1,18 @@ using Microsoft.EntityFrameworkCore; using Savvyio.Domain; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +/// +/// Defines a generic way to support the actual I/O communication with a source of data - tailored to Microsoft Entity Framework Core. +/// +/// +public interface IEfCoreDataSource : IDataSource, IUnitOfWork { /// - /// Defines a generic way to support the actual I/O communication with a source of data - tailored to Microsoft Entity Framework Core. + /// Creates a that can be used to query and save instances of . /// - /// - public interface IEfCoreDataSource : IDataSource, IUnitOfWork - { - /// - /// Creates a that can be used to query and save instances of . - /// - /// The type of entity for which a set should be returned. - /// A set for the given entity type. - DbSet Set() where TEntity : class; - } + /// The type of entity for which a set should be returned. + /// A set for the given entity type. + DbSet Set() where TEntity : class; } diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs index 965da06c..2821fa41 100644 --- a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs @@ -14,199 +14,198 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +/// +/// Provides a NATS JetStream implementation of the for command messages. +/// +/// +/// +public class NatsCommandQueue : NatsMessage, IPointToPointChannel { + private readonly NatsCommandQueueOptions _options; + /// - /// Provides a NATS JetStream implementation of the for command messages. + /// Initializes a new instance of the class. /// - /// - /// - public class NatsCommandQueue : NatsMessage, IPointToPointChannel + /// 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) { - private readonly NatsCommandQueueOptions _options; + Validator.ThrowIfInvalidOptions(options); + _options = 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) + /// + /// 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 context = CreateJetStreamContext(); + foreach (var message in messages) { - Validator.ThrowIfInvalidOptions(options); - _options = options; + await PublishMessageAsync(context, _options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), new NatsHeaders() + { + { "type", message.GetType().ToFullNameIncludingAssemblyName() } + }).ConfigureAwait(false); } + } - /// - /// 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) + /// + /// 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 consumer = await CreateConsumerAsync(new StreamConfig(streamName, [_options.Subject]) { - var context = CreateJetStreamContext(); - foreach (var message in messages) - { - await PublishMessageAsync(context, _options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), new NatsHeaders() - { - { "type", message.GetType().ToFullNameIncludingAssemblyName() } - }).ConfigureAwait(false); - } - } + Retention = StreamConfigRetention.Workqueue + }, new ConsumerConfig(consumerName) + { + }, options.CancellationToken).ConfigureAwait(false); - /// - /// 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) + await foreach (var message in FetchMessagesAsync(consumer, new NatsJSFetchOpts() + { + Expires = _options.Expires == TimeSpan.Zero ? null : _options.Expires, + MaxMsgs = _options.MaxMessages, + IdleHeartbeat = _options.Heartbeat == TimeSpan.Zero ? null : _options.Heartbeat + }, cancellationToken: options.CancellationToken)) { - Validator.ThrowIfInvalidConfigurator(setup, out var options); - - var streamName = _options.StreamName; - var consumerName = _options.ConsumerName; - - var consumer = await CreateConsumerAsync(new StreamConfig(streamName, [_options.Subject]) - { - Retention = StreamConfigRetention.Workqueue - }, new ConsumerConfig(consumerName) + 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(ReceivedNatsMessage), message); + deserialized.Acknowledged += OnMessageAcknowledgedAsync; + if (_options.AutoAcknowledge) { - }, options.CancellationToken).ConfigureAwait(false); - - await foreach (var message in FetchMessagesAsync(consumer, 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(ReceivedNatsMessage), message); - deserialized.Acknowledged += OnMessageAcknowledgedAsync; - if (_options.AutoAcknowledge) - { - await deserialized.AcknowledgeAsync().ConfigureAwait(false); - } - yield return deserialized; + 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 = (ReceivedNatsMessage)e.Properties[nameof(ReceivedNatsMessage)]; - await message.AcknowledgeAsync(ct).ConfigureAwait(false); - if (sender is IAcknowledgeable ack) { ack.Acknowledged -= OnMessageAcknowledgedAsync; } - } + /// + /// 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 = (ReceivedNatsMessage)e.Properties[nameof(ReceivedNatsMessage)]; + await message.AcknowledgeAsync(ct).ConfigureAwait(false); + if (sender is IAcknowledgeable ack) { ack.Acknowledged -= OnMessageAcknowledgedAsync; } + } - /// - /// Publishes a serialized message to NATS JetStream. - /// - /// The JetStream context to use for publishing. - /// The subject to publish to. - /// The serialized message payload. - /// The message headers. - /// A task that represents the asynchronous operation. - protected virtual async Task PublishMessageAsync(INatsJSContext context, string subject, string message, NatsHeaders headers) + /// + /// Publishes a serialized message to NATS JetStream. + /// + /// The JetStream context to use for publishing. + /// The subject to publish to. + /// The serialized message payload. + /// The message headers. + /// A task that represents the asynchronous operation. + protected virtual async Task PublishMessageAsync(INatsJSContext context, string subject, string message, NatsHeaders headers) + { + await context.PublishAsync(subject, message, headers: headers).ConfigureAwait(false); + } + + /// + /// Creates or updates the stream and consumer used by receive operations. + /// + /// The stream configuration. + /// The consumer configuration. + /// The cancellation token of the asynchronous operation. + /// A consumer that can fetch messages. + protected virtual async Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) + { + var context = CreateJetStreamContext(); + await context.CreateOrUpdateStreamAsync(streamConfig, cancellationToken).ConfigureAwait(false); + return await context.CreateOrUpdateConsumerAsync(streamConfig.Name, consumerConfig, cancellationToken).ConfigureAwait(false); + } + + /// + /// Creates a NATS JetStream context used by send and receive operations. + /// + /// An for JetStream operations. + protected virtual INatsJSContext CreateJetStreamContext() + { + return NatsClient.CreateJetStreamContext(); + } + + /// + /// Fetches messages from the specified NATS JetStream consumer. + /// + /// The consumer to fetch messages from. + /// The fetch options. + /// The cancellation token of the asynchronous operation. + /// An asynchronous sequence of received NATS messages. + protected virtual async IAsyncEnumerable FetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) + { + await foreach (var message in consumer.FetchAsync(opts: options, cancellationToken: cancellationToken).ConfigureAwait(false)) { - await context.PublishAsync(subject, message, headers: headers).ConfigureAwait(false); + yield return new ReceivedNatsMessage(message.Headers, message.Data, ct => message.AckAsync(cancellationToken: ct).AsTask()); } + } + + /// + /// Represents a NATS message received from JetStream. + /// + protected sealed class ReceivedNatsMessage + { + private readonly Func _acknowledgeAsync; /// - /// Creates or updates the stream and consumer used by receive operations. + /// Initializes a new instance of the class. /// - /// The stream configuration. - /// The consumer configuration. - /// The cancellation token of the asynchronous operation. - /// A consumer that can fetch messages. - protected virtual async Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) + /// The NATS message headers. + /// The NATS message payload. + /// The delegate used to acknowledge the message. + public ReceivedNatsMessage(NatsHeaders headers, string data, Func acknowledgeAsync) { - var context = CreateJetStreamContext(); - await context.CreateOrUpdateStreamAsync(streamConfig, cancellationToken).ConfigureAwait(false); - return await context.CreateOrUpdateConsumerAsync(streamConfig.Name, consumerConfig, cancellationToken).ConfigureAwait(false); + Headers = headers; + Data = data; + _acknowledgeAsync = acknowledgeAsync; } /// - /// Creates a NATS JetStream context used by send and receive operations. + /// Gets the NATS message headers. /// - /// An for JetStream operations. - protected virtual INatsJSContext CreateJetStreamContext() - { - return NatsClient.CreateJetStreamContext(); - } + public NatsHeaders Headers { get; } /// - /// Fetches messages from the specified NATS JetStream consumer. + /// Gets the NATS message payload. /// - /// The consumer to fetch messages from. - /// The fetch options. - /// The cancellation token of the asynchronous operation. - /// An asynchronous sequence of received NATS messages. - protected virtual async IAsyncEnumerable FetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) - { - await foreach (var message in consumer.FetchAsync(opts: options, cancellationToken: cancellationToken).ConfigureAwait(false)) - { - yield return new ReceivedNatsMessage(message.Headers, message.Data, ct => message.AckAsync(cancellationToken: ct).AsTask()); - } - } + public string Data { get; } /// - /// Represents a NATS message received from JetStream. + /// Acknowledges the message. /// - protected sealed class ReceivedNatsMessage + /// The cancellation token of the asynchronous operation. + /// A task that represents the asynchronous operation. + public Task AcknowledgeAsync(CancellationToken cancellationToken) { - private readonly Func _acknowledgeAsync; - - /// - /// Initializes a new instance of the class. - /// - /// The NATS message headers. - /// The NATS message payload. - /// The delegate used to acknowledge the message. - public ReceivedNatsMessage(NatsHeaders headers, string data, Func acknowledgeAsync) - { - Headers = headers; - Data = data; - _acknowledgeAsync = acknowledgeAsync; - } - - /// - /// Gets the NATS message headers. - /// - public NatsHeaders Headers { get; } - - /// - /// Gets the NATS message payload. - /// - public string Data { get; } - - /// - /// Acknowledges the message. - /// - /// The cancellation token of the asynchronous operation. - /// A task that represents the asynchronous operation. - public Task AcknowledgeAsync(CancellationToken cancellationToken) - { - return _acknowledgeAsync(cancellationToken); - } + return _acknowledgeAsync(cancellationToken); } } } diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs index 7b636e1c..6da177bf 100644 --- a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs @@ -1,118 +1,117 @@ using System; using Cuemon; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +/// +/// Configuration options for . +/// +/// +public class NatsCommandQueueOptions : NatsMessageOptions { + private int _maxMessages; + private TimeSpan _expires; + /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - /// - public class NatsCommandQueueOptions : NatsMessageOptions + /// + /// 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() { - 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; - } + 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 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 + /// + /// 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 { - get => _expires; - set + _expires = value; + if (_expires >= TimeSpan.FromSeconds(30)) { - _expires = value; - if (_expires >= TimeSpan.FromSeconds(30)) - { - Heartbeat = TimeSpan.FromSeconds(5); - } + 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 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 stream. + /// + public string StreamName { get; set; } - /// - /// Gets or sets the name of the NATS consumer. - /// - public string ConsumerName { 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; } + /// + /// 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(); - } + /// + /// 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 index ed03bfd2..d249d243 100644 --- a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs @@ -11,122 +11,121 @@ using System.Threading; using System.Threading.Tasks; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +/// +/// Provides a NATS implementation of the for integration event messages. +/// +/// +/// +public class NatsEventBus : NatsMessage, IPublishSubscribeChannel { + private readonly NatsEventBusOptions _options; + /// - /// Provides a NATS implementation of the for integration event messages. + /// Initializes a new instance of the class. /// - /// - /// - public class NatsEventBus : NatsMessage, IPublishSubscribeChannel + /// 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) { - private readonly NatsEventBusOptions _options; + Validator.ThrowIfInvalidOptions(options); + _options = 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 PublishMessageAsync(_options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), new NatsHeaders() + { + { "type", message.GetType().ToFullNameIncludingAssemblyName() } + }, options.CancellationToken).ConfigureAwait(false); + } - /// - /// 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) + /// + /// 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 SubscribeMessagesAsync(_options.Subject, new NatsSubOpts() + { + }, cancellationToken: options.CancellationToken)) { - Validator.ThrowIfInvalidConfigurator(setup, out var options); - await PublishMessageAsync(_options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), new NatsHeaders() - { - { "type", message.GetType().ToFullNameIncludingAssemblyName() } - }, options.CancellationToken).ConfigureAwait(false); + 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); } + } - /// - /// 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) + /// + /// Publishes a serialized message to NATS. + /// + /// The subject to publish to. + /// The serialized message payload. + /// The message headers. + /// The cancellation token of the asynchronous operation. + /// A task that represents the asynchronous operation. + protected virtual async Task PublishMessageAsync(string subject, string message, NatsHeaders headers, CancellationToken cancellationToken) + { + await NatsClient.PublishAsync(subject, message, headers: headers, cancellationToken: cancellationToken).ConfigureAwait(false); + } + + /// + /// Subscribes to NATS messages. + /// + /// The subject to subscribe to. + /// The subscription options. + /// The cancellation token of the asynchronous operation. + /// An asynchronous sequence of received NATS messages. + protected virtual async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) + { + await foreach (var message in NatsClient.SubscribeAsync(subject, opts: options, cancellationToken: cancellationToken).ConfigureAwait(false)) { - Validator.ThrowIfInvalidConfigurator(setup, out var options); - await foreach (var message in SubscribeMessagesAsync(_options.Subject, 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); - } + yield return new ReceivedNatsMessage(message.Headers, message.Data); } + } + /// + /// Represents a NATS message received from a subscription. + /// + protected sealed class ReceivedNatsMessage + { /// - /// Publishes a serialized message to NATS. + /// Initializes a new instance of the class. /// - /// The subject to publish to. - /// The serialized message payload. - /// The message headers. - /// The cancellation token of the asynchronous operation. - /// A task that represents the asynchronous operation. - protected virtual async Task PublishMessageAsync(string subject, string message, NatsHeaders headers, CancellationToken cancellationToken) + /// The NATS message headers. + /// The NATS message payload. + public ReceivedNatsMessage(NatsHeaders headers, string data) { - await NatsClient.PublishAsync(subject, message, headers: headers, cancellationToken: cancellationToken).ConfigureAwait(false); + Headers = headers; + Data = data; } /// - /// Subscribes to NATS messages. + /// Gets the NATS message headers. /// - /// The subject to subscribe to. - /// The subscription options. - /// The cancellation token of the asynchronous operation. - /// An asynchronous sequence of received NATS messages. - protected virtual async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) - { - await foreach (var message in NatsClient.SubscribeAsync(subject, opts: options, cancellationToken: cancellationToken).ConfigureAwait(false)) - { - yield return new ReceivedNatsMessage(message.Headers, message.Data); - } - } + public NatsHeaders Headers { get; } /// - /// Represents a NATS message received from a subscription. + /// Gets the NATS message payload. /// - protected sealed class ReceivedNatsMessage - { - /// - /// Initializes a new instance of the class. - /// - /// The NATS message headers. - /// The NATS message payload. - public ReceivedNatsMessage(NatsHeaders headers, string data) - { - Headers = headers; - Data = data; - } - - /// - /// Gets the NATS message headers. - /// - public NatsHeaders Headers { get; } - - /// - /// Gets the NATS message payload. - /// - public string Data { get; } - } + public string Data { get; } } } diff --git a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs index 9174ae42..84558b8f 100644 --- a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +/// +/// Configuration options for . +/// +/// +public class NatsEventBusOptions : NatsMessageOptions { - /// - /// Configuration options for . - /// - /// - public class NatsEventBusOptions : NatsMessageOptions - { - } } diff --git a/src/Savvyio.Extensions.NATS/NatsMessage.cs b/src/Savvyio.Extensions.NATS/NatsMessage.cs index 87112765..8bcab7ec 100644 --- a/src/Savvyio.Extensions.NATS/NatsMessage.cs +++ b/src/Savvyio.Extensions.NATS/NatsMessage.cs @@ -6,59 +6,58 @@ using NATS.Client.Core; using Savvyio.Diagnostics; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +/// +/// Provides a base class for NATS message operations, supporting asynchronous disposal and message serialization. +/// +public abstract class NatsMessage : AsyncDisposable, IHealthCheckProvider { /// - /// Provides a base class for NATS message operations, supporting asynchronous disposal and message serialization. + /// Initializes a new instance of the class with the specified marshaller and options. /// - public abstract class NatsMessage : AsyncDisposable, IHealthCheckProvider + /// 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) { - /// - /// 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); - } + 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 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; } + /// + /// 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); } - } - /// - /// Gets the instance used for probing the health status of the NATS server. - /// - /// instance representing the active connection to the NATS server. - public INatsConnection GetHealthCheckTarget() - { - return NatsClient.Connection; - } + /// + /// 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); } + } + /// + /// Gets the instance used for probing the health status of the NATS server. + /// + /// instance representing the active connection to the NATS server. + public INatsConnection GetHealthCheckTarget() + { + return NatsClient.Connection; } } diff --git a/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs index 7e52f359..c0c23e5b 100644 --- a/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs +++ b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs @@ -2,60 +2,59 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +/// +/// Configuration options that is related to NATS. +/// +/// +public class NatsMessageOptions : IValidatableParameterObject { /// - /// Configuration options that is related to NATS. + /// Initializes a new instance of the class with default values. /// - /// - public class NatsMessageOptions : IValidatableParameterObject + /// + /// 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() { - /// - /// 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"); - } + 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 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; } + /// + /// 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)); - } + /// + /// 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.Newtonsoft.Json/Bootstrapper.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Bootstrapper.cs index 44d2a3fe..5b2b4956 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Bootstrapper.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Bootstrapper.cs @@ -1,30 +1,29 @@ using Codebelt.Extensions.Newtonsoft.Json.Formatters; using System.Threading; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +internal static class Bootstrapper { - internal static class Bootstrapper - { - private static readonly Lock PadLock = new(); - private static bool _initialized; + private static readonly Lock PadLock = new(); + private static bool _initialized; - internal static void Initialize() + internal static void Initialize() + { + if (!_initialized) { - if (!_initialized) + lock (PadLock) { - lock (PadLock) + if (!_initialized) { - if (!_initialized) + _initialized = true; + NewtonsoftJsonFormatterOptions.DefaultConverters += list => { - _initialized = true; - NewtonsoftJsonFormatterOptions.DefaultConverters += list => - { - list.AddRequestConverter(); - list.AddMetadataDictionaryConverter(); - list.AddMessageConverter(); - list.AddSingleValueObjectConverter(); - }; - } + list.AddRequestConverter(); + list.AddMetadataDictionaryConverter(); + list.AddMessageConverter(); + list.AddSingleValueObjectConverter(); + }; } } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/AggregateRootConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/AggregateRootConverter.cs index 003c02c3..6a0860e7 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/AggregateRootConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/AggregateRootConverter.cs @@ -12,143 +12,142 @@ using Newtonsoft.Json; using Savvyio.Domain; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +/// +/// Converts an to or from JSON. +/// +/// The type of the key that uniquely identifies an aggregate. +/// +public class AggregateRootConverter : JsonConverter> { + private readonly ActivatorOptions _options; + /// - /// Converts an to or from JSON. + /// Initializes a new instance of the class. /// - /// The type of the key that uniquely identifies an aggregate. - /// - public class AggregateRootConverter : JsonConverter> + /// The which may be configured. + public AggregateRootConverter(Action setup = null) { - private readonly ActivatorOptions _options; + _options = Patterns.Configure(setup); + } - /// - /// Initializes a new instance of the class. - /// - /// The which may be configured. - public AggregateRootConverter(Action setup = null) - { - _options = Patterns.Configure(setup); - } + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, AggregateRoot value, JsonSerializer serializer) + { + var properties = value.GetType().GetRuntimePropertiesExceptOf>().Where(pi => pi.CanRead).ToList(); + writer.WriteStartObject(); + writer.WritePropertyName(nameof(value.Id), serializer); + writer.WriteValue(value.Id); - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, AggregateRoot value, JsonSerializer serializer) + foreach (var property in properties) { - var properties = value.GetType().GetRuntimePropertiesExceptOf>().Where(pi => pi.CanRead).ToList(); - writer.WriteStartObject(); - writer.WritePropertyName(nameof(value.Id), serializer); - writer.WriteValue(value.Id); - - foreach (var property in properties) - { - writer.WritePropertyName(property.Name, serializer); - writer.WriteObject(property.GetValue(value), serializer); - } - - writer.WriteEndObject(); + writer.WritePropertyName(property.Name, serializer); + writer.WriteObject(property.GetValue(value), serializer); } - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. If there is no existing value then null will be used. - /// The existing value has a value. - /// The calling serializer. - /// The object value. - public override AggregateRoot ReadJson(JsonReader reader, Type objectType, AggregateRoot existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var idProperty = objectType.GetProperty(nameof(IEntity.Id), _options.Flags); - var properties = objectType.GetRuntimePropertiesExceptOf>().Where(pi => pi.CanRead).ToList(); - if (idProperty != null) { properties.Insert(0, idProperty); } + writer.WriteEndObject(); + } - var propertyData = ReadPropertyData(reader, properties, serializer); + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. If there is no existing value then null will be used. + /// The existing value has a value. + /// The calling serializer. + /// The object value. + public override AggregateRoot ReadJson(JsonReader reader, Type objectType, AggregateRoot existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var idProperty = objectType.GetProperty(nameof(IEntity.Id), _options.Flags); + var properties = objectType.GetRuntimePropertiesExceptOf>().Where(pi => pi.CanRead).ToList(); + if (idProperty != null) { properties.Insert(0, idProperty); } - var result = CreateAggregateRoot(objectType, properties, propertyData); - if (result != null) { return result; } + var propertyData = ReadPropertyData(reader, properties, serializer); - throw ExceptionInsights.Embed(new InvalidOperationException($"Unable to deserialize {objectType.FullName}; consider adding a custom converter for this type."), MethodBase.GetCurrentMethod(), Arguments.ToArray(reader, objectType, existingValue, hasExistingValue, serializer)); - } + var result = CreateAggregateRoot(objectType, properties, propertyData); + if (result != null) { return result; } - private List ReadPropertyData(JsonReader reader, List properties, JsonSerializer serializer) - { - var propertyData = new List(); - if (reader.TokenType != JsonToken.StartObject) { return propertyData; } - - var depth = reader.Depth; - while (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - var propertyName = (string)reader.Value; - var matchingProperty = properties.FirstOrDefault(pi => pi.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); - if (matchingProperty != null) - { - reader.Read(); - propertyData.Add(ReadDataPair(reader, matchingProperty, serializer)); - } - break; - } - - if (reader.Depth == depth && reader.TokenType == JsonToken.EndObject) { break; } - } + throw ExceptionInsights.Embed(new InvalidOperationException($"Unable to deserialize {objectType.FullName}; consider adding a custom converter for this type."), MethodBase.GetCurrentMethod(), Arguments.ToArray(reader, objectType, existingValue, hasExistingValue, serializer)); + } - return propertyData; - } + private List ReadPropertyData(JsonReader reader, List properties, JsonSerializer serializer) + { + var propertyData = new List(); + if (reader.TokenType != JsonToken.StartObject) { return propertyData; } - private DataPair ReadDataPair(JsonReader reader, PropertyInfo matchingProperty, JsonSerializer serializer) + var depth = reader.Depth; + while (reader.Read()) { - if (matchingProperty.PropertyType.HasTypes(typeof(SingleValueObject<>))) + switch (reader.TokenType) { - return new DataPair(matchingProperty.Name, serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + case JsonToken.PropertyName: + var propertyName = (string)reader.Value; + var matchingProperty = properties.FirstOrDefault(pi => pi.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); + if (matchingProperty != null) + { + reader.Read(); + propertyData.Add(ReadDataPair(reader, matchingProperty, serializer)); + } + break; } - return new DataPair(matchingProperty.Name, ParserFactory.FromObject().Parse(reader.Value?.ToString(), matchingProperty.PropertyType, o => o.FormatProvider = _options.FormatProvider) ?? serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + if (reader.Depth == depth && reader.TokenType == JsonToken.EndObject) { break; } } - private AggregateRoot CreateAggregateRoot(Type objectType, List properties, List propertyData) - { - var ctors = objectType.GetConstructors(_options.Flags).ToList(); - if (ctors.Count == 0) { return null; } + return propertyData; + } - var matchingCtor = ctors.SingleOrDefault(info => MatchesConstructor(info, propertyData)); - if (matchingCtor != null) - { - return matchingCtor.Invoke(propertyData.Select(pair => pair.Value).ToArray()) as AggregateRoot; - } + private DataPair ReadDataPair(JsonReader reader, PropertyInfo matchingProperty, JsonSerializer serializer) + { + if (matchingProperty.PropertyType.HasTypes(typeof(SingleValueObject<>))) + { + return new DataPair(matchingProperty.Name, serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + } - var defaultCtor = ctors.SingleOrDefault(ci => ci.GetParameters().Length == 0); - if (defaultCtor == null) { return null; } + return new DataPair(matchingProperty.Name, ParserFactory.FromObject().Parse(reader.Value?.ToString(), matchingProperty.PropertyType, o => o.FormatProvider = _options.FormatProvider) ?? serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + } - return PopulateDefaultConstructed(defaultCtor, properties, propertyData); - } + private AggregateRoot CreateAggregateRoot(Type objectType, List properties, List propertyData) + { + var ctors = objectType.GetConstructors(_options.Flags).ToList(); + if (ctors.Count == 0) { return null; } - private static bool MatchesConstructor(ConstructorInfo info, List propertyData) + var matchingCtor = ctors.SingleOrDefault(info => MatchesConstructor(info, propertyData)); + if (matchingCtor != null) { - var paramters = info.GetParameters().ToList(); - return paramters.Count == propertyData.Count && paramters.Select(pi => pi.ParameterType).SequenceEqual(propertyData.Select(pair => pair.Type)); + return matchingCtor.Invoke(propertyData.Select(pair => pair.Value).ToArray()) as AggregateRoot; } - private static AggregateRoot PopulateDefaultConstructed(ConstructorInfo defaultCtor, List properties, List propertyData) + var defaultCtor = ctors.SingleOrDefault(ci => ci.GetParameters().Length == 0); + if (defaultCtor == null) { return null; } + + return PopulateDefaultConstructed(defaultCtor, properties, propertyData); + } + + private static bool MatchesConstructor(ConstructorInfo info, List propertyData) + { + var paramters = info.GetParameters().ToList(); + return paramters.Count == propertyData.Count && paramters.Select(pi => pi.ParameterType).SequenceEqual(propertyData.Select(pair => pair.Type)); + } + + private static AggregateRoot PopulateDefaultConstructed(ConstructorInfo defaultCtor, List properties, List propertyData) + { + var ar = defaultCtor.Invoke(Array.Empty()) as AggregateRoot; + foreach (var property in properties) { - var ar = defaultCtor.Invoke(Array.Empty()) as AggregateRoot; - foreach (var property in properties) + if (property.CanWrite) { - if (property.CanWrite) - { - property.SetValue(ar, propertyData.SingleOrDefault(pair => pair.Name.Equals(property.Name, StringComparison.OrdinalIgnoreCase))?.Value); - } + property.SetValue(ar, propertyData.SingleOrDefault(pair => pair.Name.Equals(property.Name, StringComparison.OrdinalIgnoreCase))?.Value); } - - return ar; } + + return ar; } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs index 516abe48..8ba7ee57 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs @@ -13,172 +13,171 @@ using Savvyio.Messaging.Cryptography; using Savvyio.Reflection; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +/// +/// Converts an (or derived) to or from JSON. +/// +/// +public class MessageConverter : JsonConverter { + internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && + ti is { IsAbstract: false, IsInterface: false })).ToList()); + /// - /// Converts an (or derived) to or from JSON. + /// Writes the JSON representation of the object. /// - /// - public class MessageConverter : JsonConverter + /// The to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && - ti is { IsAbstract: false, IsInterface: false })).ToList()); - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (value == null) { return; } - var objectType = value.GetType(); - var requestType = objectType.GetGenericArguments()[0]; - var converter = (JsonConverter)Activator.CreateInstance( - typeof(MessageConverter<>).MakeGenericType(requestType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - converter.WriteJson(writer, value, serializer); - } + if (value == null) { return; } + var objectType = value.GetType(); + var requestType = objectType.GetGenericArguments()[0]; + var converter = (JsonConverter)Activator.CreateInstance( + typeof(MessageConverter<>).MakeGenericType(requestType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; + converter.WriteJson(writer, value, serializer); + } - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var requestType = objectType.GetGenericArguments()[0]; - var converter = (JsonConverter)Activator.CreateInstance( - typeof(MessageConverter<>).MakeGenericType(requestType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - return converter.ReadJson(reader, objectType, existingValue, serializer); - } + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var requestType = objectType.GetGenericArguments()[0]; + var converter = (JsonConverter)Activator.CreateInstance( + typeof(MessageConverter<>).MakeGenericType(requestType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; + return converter.ReadJson(reader, objectType, existingValue, serializer); + } - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// true if this instance can convert the specified object type; otherwise, false. - public override bool CanConvert(Type objectType) - { - return (objectType.IsGenericType && - objectType.GetGenericTypeDefinition().HasInterfaces(typeof(IMessage<>))); - } + /// + /// Determines whether this instance can convert the specified object type. + /// + /// Type of the object. + /// true if this instance can convert the specified object type; otherwise, false. + public override bool CanConvert(Type objectType) + { + return (objectType.IsGenericType && + objectType.GetGenericTypeDefinition().HasInterfaces(typeof(IMessage<>))); } +} - internal sealed class MessageConverter : JsonConverter> where T : IRequest +internal sealed class MessageConverter : JsonConverter> where T : IRequest +{ + public MessageConverter() { - public MessageConverter() + } + + public override void WriteJson(JsonWriter writer, IMessage value, JsonSerializer serializer) + { + writer.WriteStartObject(); + writer.WritePropertyName(nameof(value.Id), serializer); + writer.WriteValue(value.Id); + writer.WritePropertyName(nameof(value.Source), serializer); + writer.WriteValue(value.Source); + writer.WritePropertyName(nameof(value.Type), serializer); + writer.WriteValue(value.Type); + writer.WritePropertyName(nameof(value.Time), serializer); + writer.WriteObject(value.Time, serializer); + writer.WritePropertyName(nameof(value.Data), serializer); + writer.WriteObject(value.Data, serializer); + + if (value.GetType().HasInterfaces(typeof(ICloudEvent<>))) { + dynamic ce = value; + writer.WritePropertyName(nameof(ICloudEvent.Specversion), serializer); + writer.WriteValue(ce.Specversion); } - public override void WriteJson(JsonWriter writer, IMessage value, JsonSerializer serializer) + if (value is ISignedMessage sm) { - writer.WriteStartObject(); - writer.WritePropertyName(nameof(value.Id), serializer); - writer.WriteValue(value.Id); - writer.WritePropertyName(nameof(value.Source), serializer); - writer.WriteValue(value.Source); - writer.WritePropertyName(nameof(value.Type), serializer); - writer.WriteValue(value.Type); - writer.WritePropertyName(nameof(value.Time), serializer); - writer.WriteObject(value.Time, serializer); - writer.WritePropertyName(nameof(value.Data), serializer); - writer.WriteObject(value.Data, serializer); - - if (value.GetType().HasInterfaces(typeof(ICloudEvent<>))) - { - dynamic ce = value; - writer.WritePropertyName(nameof(ICloudEvent.Specversion), serializer); - writer.WriteValue(ce.Specversion); - } - - if (value is ISignedMessage sm) - { - writer.WritePropertyName(nameof(sm.Signature), serializer); - writer.WriteValue(sm.Signature); - } + writer.WritePropertyName(nameof(sm.Signature), serializer); + writer.WriteValue(sm.Signature); + } - if (value is IDictionary dictionary) + if (value is IDictionary dictionary) + { + foreach (var kvp in dictionary) { - foreach (var kvp in dictionary) - { - writer.WritePropertyName(kvp.Key); - writer.WriteObject(kvp.Value, serializer); - } + writer.WritePropertyName(kvp.Key); + writer.WriteObject(kvp.Value, serializer); } - - writer.WriteEndObject(); } - public override IMessage ReadJson(JsonReader reader, Type objectType, IMessage existingValue, bool hasExistingValue, JsonSerializer serializer) + writer.WriteEndObject(); + } + + public override IMessage ReadJson(JsonReader reader, Type objectType, IMessage existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var idKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Id)); + var sourceKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Source)); + var timeKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Time)); + var typeKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Type)); + var dataKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Data)); + var metadataKey = serializer.ResolvePropertyKeyByConvention(nameof(IMetadata.Metadata)); + var memberTypeKey = serializer.ResolveDictionaryKeyByConvention(nameof(MetadataDictionary.MemberType)); + var signatureKey = serializer.ResolvePropertyKeyByConvention(nameof(ISignedMessage.Signature)); + + var document = JObject.Load(reader); + var id = document.Root[idKey]!.Value(); + var source = document.Root[sourceKey]!.Value().ToUri(); + var type = document.Root[typeKey]!.Value(); + var memberType = Type.GetType(document.Root[dataKey]![metadataKey]![memberTypeKey]!.Value()); + var time = document.Root[timeKey]!.Value().ToUniversalTime(); + var data = (T)serializer.Deserialize(document.Root[dataKey].CreateReader(), memberType); + + var message = new Message(id, source, type, data, time); + + if (objectType.HasInterfaces(typeof(ICloudEvent<>))) { - var idKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Id)); - var sourceKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Source)); - var timeKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Time)); - var typeKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Type)); - var dataKey = serializer.ResolvePropertyKeyByConvention(nameof(IMessage.Data)); - var metadataKey = serializer.ResolvePropertyKeyByConvention(nameof(IMetadata.Metadata)); - var memberTypeKey = serializer.ResolveDictionaryKeyByConvention(nameof(MetadataDictionary.MemberType)); - var signatureKey = serializer.ResolvePropertyKeyByConvention(nameof(ISignedMessage.Signature)); - - var document = JObject.Load(reader); - var id = document.Root[idKey]!.Value(); - var source = document.Root[sourceKey]!.Value().ToUri(); - var type = document.Root[typeKey]!.Value(); - var memberType = Type.GetType(document.Root[dataKey]![metadataKey]![memberTypeKey]!.Value()); - var time = document.Root[timeKey]!.Value().ToUniversalTime(); - var data = (T)serializer.Deserialize(document.Root[dataKey].CreateReader(), memberType); - - var message = new Message(id, source, type, data, time); - - if (objectType.HasInterfaces(typeof(ICloudEvent<>))) - { - var specVersionKey = serializer.ResolvePropertyKeyByConvention(nameof(ICloudEvent.Specversion)); + var specVersionKey = serializer.ResolvePropertyKeyByConvention(nameof(ICloudEvent.Specversion)); - var requestType = objectType.GetGenericArguments()[0]; - var cloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.CloudEvent", StringComparison.Ordinal)); - var specVersion = document.Root[specVersionKey]!.Value(); - var cloudEvent = Activator.CreateInstance(cloudEventType.MakeGenericType(requestType), [message, specVersion]) as IMessage; + var requestType = objectType.GetGenericArguments()[0]; + var cloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.CloudEvent", StringComparison.Ordinal)); + var specVersion = document.Root[specVersionKey]!.Value(); + var cloudEvent = Activator.CreateInstance(cloudEventType.MakeGenericType(requestType), [message, specVersion]) as IMessage; - if (objectType.HasInterfaces(typeof(ISignedCloudEvent<>))) - { - var signedCloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.Cryptography.SignedCloudEvent", StringComparison.Ordinal)); - var signature = document.Root[signatureKey]!.Value(); + if (objectType.HasInterfaces(typeof(ISignedCloudEvent<>))) + { + var signedCloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.Cryptography.SignedCloudEvent", StringComparison.Ordinal)); + var signature = document.Root[signatureKey]!.Value(); - return Activator.CreateInstance(signedCloudEventType.MakeGenericType(requestType), [cloudEvent, signature]) as IMessage; - } + return Activator.CreateInstance(signedCloudEventType.MakeGenericType(requestType), [cloudEvent, signature]) as IMessage; + } - var reservedKeys = new[] { idKey, sourceKey, timeKey, typeKey, dataKey, metadataKey, signatureKey, specVersionKey }; + var reservedKeys = new[] { idKey, sourceKey, timeKey, typeKey, dataKey, metadataKey, signatureKey, specVersionKey }; - if (cloudEvent is IDictionary dictionary) + if (cloudEvent is IDictionary dictionary) + { + foreach (var property in document.Properties().Where(jp => !reservedKeys.Contains(jp.Name))) { - foreach (var property in document.Properties().Where(jp => !reservedKeys.Contains(jp.Name))) - { - dictionary.Add(property.Name, property.Value.ToObject(null, serializer)); - } + dictionary.Add(property.Name, property.Value.ToObject(null, serializer)); } - - return cloudEvent; } - if (objectType.HasInterfaces(typeof(ISignedMessage<>))) - { - var signature = document.Root[signatureKey]!.Value(); - return new SignedMessage(message, signature); - } + return cloudEvent; + } - return message; + if (objectType.HasInterfaces(typeof(ISignedMessage<>))) + { + var signature = document.Root[signatureKey]!.Value(); + return new SignedMessage(message, signature); } + + return message; } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs index ea4c41d8..10246fea 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs @@ -6,99 +6,98 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +/// +/// Converts an to or from JSON. +/// +/// +public class RequestConverter : JsonConverter { /// - /// Converts an to or from JSON. + /// Initializes a new instance of the class. /// - /// - public class RequestConverter : JsonConverter + public RequestConverter() { - /// - /// Initializes a new instance of the class. - /// - public RequestConverter() - { - } + } - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - /// - /// This method is not implemented and should not be used. - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + /// + /// This method is not implemented and should not be used. + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } - /// - /// Gets a value indicating whether this can write JSON. - /// - /// true if this can write JSON; otherwise, false. - public override bool CanWrite { get; } = false; + /// + /// Gets a value indicating whether this can write JSON. + /// + /// true if this can write JSON; otherwise, false. + public override bool CanWrite { get; } = false; - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - /// - /// This deserializer only supports rehydration of implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent. - /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + /// + /// This deserializer only supports rehydration of implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent. + /// + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var document = JObject.Load(reader); + var instance = RuntimeHelpers.GetUninitializedObject(objectType); + var properties = objectType.GetAllProperties(); + var jProperties = document.Properties().ToList(); + foreach (var property in properties.Where(pi => jProperties.Exists(jp => jp.Name.Equals(serializer.ResolvePropertyKeyByConvention(pi.Name), StringComparison.OrdinalIgnoreCase)))) { - var document = JObject.Load(reader); - var instance = RuntimeHelpers.GetUninitializedObject(objectType); - var properties = objectType.GetAllProperties(); - var jProperties = document.Properties().ToList(); - foreach (var property in properties.Where(pi => jProperties.Exists(jp => jp.Name.Equals(serializer.ResolvePropertyKeyByConvention(pi.Name), StringComparison.OrdinalIgnoreCase)))) + var jProperty = jProperties.Single(jp => jp.Name.Equals(serializer.ResolvePropertyKeyByConvention(property.Name), StringComparison.OrdinalIgnoreCase)); + if (document.Root[jProperty.Name] != null) { - var jProperty = jProperties.Single(jp => jp.Name.Equals(serializer.ResolvePropertyKeyByConvention(property.Name), StringComparison.OrdinalIgnoreCase)); - if (document.Root[jProperty.Name] != null) - { - var value = serializer.Deserialize(document.Root[jProperty.Name].CreateReader(), property.PropertyType); - SetPropertyOrField(instance, objectType, property, value); - } + var value = serializer.Deserialize(document.Root[jProperty.Name].CreateReader(), property.PropertyType); + SetPropertyOrField(instance, objectType, property, value); } - return instance as IRequest; - } + return instance as IRequest; - private static void SetPropertyOrField(object instance, Type objectType, PropertyInfo property, object value) - { - if (property.CanWrite) - { - property.SetValue(instance, value); - return; - } - - var field = property.IsAutoProperty() - ? objectType.GetAllFields().SingleOrDefault(fi => fi.Name.StartsWith($"<{property.Name}>", StringComparison.Ordinal)) - : objectType.GetAllFields().SingleOrDefault(fi => fi.Name.Equals($"_{property.Name}>", StringComparison.OrdinalIgnoreCase)); - if (field == null) - { - throw new NotSupportedException($"This deserializer only supports rehydration of {nameof(IRequest)} implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent."); - } + } - field.SetValue(instance, value); + private static void SetPropertyOrField(object instance, Type objectType, PropertyInfo property, object value) + { + if (property.CanWrite) + { + property.SetValue(instance, value); + return; } - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// true if this instance can convert the specified object type; otherwise, false. - public override bool CanConvert(Type objectType) + var field = property.IsAutoProperty() + ? objectType.GetAllFields().SingleOrDefault(fi => fi.Name.StartsWith($"<{property.Name}>", StringComparison.Ordinal)) + : objectType.GetAllFields().SingleOrDefault(fi => fi.Name.Equals($"_{property.Name}>", StringComparison.OrdinalIgnoreCase)); + if (field == null) { - return typeof(IRequest).IsAssignableFrom(objectType); + throw new NotSupportedException($"This deserializer only supports rehydration of {nameof(IRequest)} implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent."); } + + field.SetValue(instance, value); + } + + /// + /// Determines whether this instance can convert the specified object type. + /// + /// Type of the object. + /// true if this instance can convert the specified object type; otherwise, false. + public override bool CanConvert(Type objectType) + { + return typeof(IRequest).IsAssignableFrom(objectType); } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs index 18b7a226..5b6b93e1 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs @@ -7,89 +7,88 @@ using Newtonsoft.Json; using Savvyio.Domain; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +/// +/// Converts a to or from JSON. +/// +/// +public class SingleValueObjectConverter : JsonConverter { /// - /// Converts a to or from JSON. + /// Initializes a new instance of the class. /// - /// - public class SingleValueObjectConverter : JsonConverter + public SingleValueObjectConverter() { - /// - /// Initializes a new instance of the class. - /// - public SingleValueObjectConverter() - { - } + } - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (value == null) { return; } - var objectType = value.GetType(); - var valueType = objectType.GetInheritedTypes().Single(type => type.IsGenericType - && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; - var converter = (JsonConverter)Activator.CreateInstance( - typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - converter.WriteJson(writer, value, serializer); - } + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) { return; } + var objectType = value.GetType(); + var valueType = objectType.GetInheritedTypes().Single(type => type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; + var converter = (JsonConverter)Activator.CreateInstance( + typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; + converter.WriteJson(writer, value, serializer); + } - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var valueType = objectType.GetInheritedTypes().Single(type => type.IsGenericType - && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; - var converter = (JsonConverter)Activator.CreateInstance( - typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - return converter.ReadJson(reader, objectType, existingValue, serializer); - } + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var valueType = objectType.GetInheritedTypes().Single(type => type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; + var converter = (JsonConverter)Activator.CreateInstance( + typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; + return converter.ReadJson(reader, objectType, existingValue, serializer); + } - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// true if this instance can convert the specified object type; otherwise, false. - public override bool CanConvert(Type objectType) - { - return objectType.HasTypes(typeof(SingleValueObject<>)); - } + /// + /// Determines whether this instance can convert the specified object type. + /// + /// Type of the object. + /// true if this instance can convert the specified object type; otherwise, false. + public override bool CanConvert(Type objectType) + { + return objectType.HasTypes(typeof(SingleValueObject<>)); } +} - internal sealed class SingleValueObjectConverter : JsonConverter> +internal sealed class SingleValueObjectConverter : JsonConverter> +{ + public SingleValueObjectConverter() { - public SingleValueObjectConverter() - { - } + } - public override void WriteJson(JsonWriter writer, SingleValueObject value, JsonSerializer serializer) - { - writer.WriteObject(value.Value, serializer); - } + public override void WriteJson(JsonWriter writer, SingleValueObject value, JsonSerializer serializer) + { + writer.WriteObject(value.Value, serializer); + } - public override SingleValueObject ReadJson(JsonReader reader, Type objectType, SingleValueObject existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var valueType = typeof(T); - return Activator.CreateInstance(objectType, serializer.Deserialize(reader, valueType)) as SingleValueObject; - } + public override SingleValueObject ReadJson(JsonReader reader, Type objectType, SingleValueObject existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var valueType = typeof(T); + return Activator.CreateInstance(objectType, serializer.Deserialize(reader, valueType)) as SingleValueObject; } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/ValueObjectConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/ValueObjectConverter.cs index 757a49eb..7274a11c 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/ValueObjectConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/ValueObjectConverter.cs @@ -13,154 +13,153 @@ using Newtonsoft.Json; using Savvyio.Domain; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +/// +/// Converts a to or from JSON. +/// +/// +public class ValueObjectConverter : JsonConverter { + private readonly ActivatorOptions _options; + /// - /// Converts a to or from JSON. + /// Initializes a new instance of the class. /// - /// - public class ValueObjectConverter : JsonConverter + /// The which may be configured. + public ValueObjectConverter(Action setup = null) { - private readonly ActivatorOptions _options; + _options = Patterns.Configure(setup); + } - /// - /// Initializes a new instance of the class. - /// - /// The which may be configured. - public ValueObjectConverter(Action setup = null) - { - _options = Patterns.Configure(setup); - } + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, ValueObject value, JsonSerializer serializer) + { + var properties = value.GetType().GetRuntimePropertiesExceptOf().Where(pi => pi.CanRead).ToList(); + writer.WriteStartObject(); - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, ValueObject value, JsonSerializer serializer) + foreach (var property in properties) { - var properties = value.GetType().GetRuntimePropertiesExceptOf().Where(pi => pi.CanRead).ToList(); - writer.WriteStartObject(); - - foreach (var property in properties) + writer.WritePropertyName(property.Name, serializer); + if (property.PropertyType.HasTypes(typeof(SingleValueObject<>))) { - writer.WritePropertyName(property.Name, serializer); - if (property.PropertyType.HasTypes(typeof(SingleValueObject<>))) - { - var svo = property.GetValue(value); - writer.WriteValue(svo.GetType().GetProperty("Value").GetValue(svo)); - } - else - { - writer.WriteObject(property.GetValue(value), serializer); - } + var svo = property.GetValue(value); + writer.WriteValue(svo.GetType().GetProperty("Value").GetValue(svo)); + } + else + { + writer.WriteObject(property.GetValue(value), serializer); } - - writer.WriteEndObject(); } - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. If there is no existing value then null will be used. - /// The existing value has a value. - /// The calling serializer. - /// The object value. - public override ValueObject ReadJson(JsonReader reader, Type objectType, ValueObject existingValue, bool hasExistingValue, JsonSerializer serializer) + writer.WriteEndObject(); + } + + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. If there is no existing value then null will be used. + /// The existing value has a value. + /// The calling serializer. + /// The object value. + public override ValueObject ReadJson(JsonReader reader, Type objectType, ValueObject existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var properties = objectType.GetRuntimePropertiesExceptOf().Where(pi => pi.CanRead).ToList(); + if (properties.Count == 1 && objectType.HasTypes(typeof(SingleValueObject<>))) { - var properties = objectType.GetRuntimePropertiesExceptOf().Where(pi => pi.CanRead).ToList(); - if (properties.Count == 1 && objectType.HasTypes(typeof(SingleValueObject<>))) + var property = properties.Single(); + if (property.DeclaringType?.IsAssignableFrom(objectType) ?? false) { - var property = properties.Single(); - if (property.DeclaringType?.IsAssignableFrom(objectType) ?? false) - { - return Activator.CreateInstance(objectType, _options.Flags, _options.Binder, new[] { Decorator.Enclose(reader.Value).ChangeType(property.PropertyType) }, _options.FormatProvider as CultureInfo) as ValueObject; - } + return Activator.CreateInstance(objectType, _options.Flags, _options.Binder, new[] { Decorator.Enclose(reader.Value).ChangeType(property.PropertyType) }, _options.FormatProvider as CultureInfo) as ValueObject; } - - var propertyData = ReadPropertyData(reader, properties, serializer); - - var result = CreateValueObject(objectType, properties, propertyData); - if (result != null) { return result; } - - throw ExceptionInsights.Embed(new InvalidOperationException($"Unable to deserialize {objectType.FullName}; consider adding a custom converter for this type."), MethodBase.GetCurrentMethod(), Arguments.ToArray(reader, objectType, existingValue, hasExistingValue, serializer)); } - private List ReadPropertyData(JsonReader reader, List properties, JsonSerializer serializer) - { - var propertyData = new List(); - if (reader.TokenType != JsonToken.StartObject) { return propertyData; } + var propertyData = ReadPropertyData(reader, properties, serializer); - var depth = reader.Depth; - while (reader.Read()) - { - switch (reader.TokenType) - { - case JsonToken.PropertyName: - var propertyName = (string)reader.Value; - var matchingProperty = properties.FirstOrDefault(pi => pi.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); - if (matchingProperty != null) - { - reader.Read(); - propertyData.Add(ReadDataPair(reader, matchingProperty, serializer)); - } - break; - } - - if (reader.Depth == depth && reader.TokenType == JsonToken.EndObject) { break; } - } + var result = CreateValueObject(objectType, properties, propertyData); + if (result != null) { return result; } - return propertyData; - } + throw ExceptionInsights.Embed(new InvalidOperationException($"Unable to deserialize {objectType.FullName}; consider adding a custom converter for this type."), MethodBase.GetCurrentMethod(), Arguments.ToArray(reader, objectType, existingValue, hasExistingValue, serializer)); + } + + private List ReadPropertyData(JsonReader reader, List properties, JsonSerializer serializer) + { + var propertyData = new List(); + if (reader.TokenType != JsonToken.StartObject) { return propertyData; } - private DataPair ReadDataPair(JsonReader reader, PropertyInfo matchingProperty, JsonSerializer serializer) + var depth = reader.Depth; + while (reader.Read()) { - if (matchingProperty.PropertyType.HasTypes(typeof(SingleValueObject<>))) + switch (reader.TokenType) { - return new DataPair(matchingProperty.Name, serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + case JsonToken.PropertyName: + var propertyName = (string)reader.Value; + var matchingProperty = properties.FirstOrDefault(pi => pi.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); + if (matchingProperty != null) + { + reader.Read(); + propertyData.Add(ReadDataPair(reader, matchingProperty, serializer)); + } + break; } - return new DataPair(matchingProperty.Name, ParserFactory.FromObject().Parse(reader.Value?.ToString(), matchingProperty.PropertyType, o => o.FormatProvider = _options.FormatProvider) ?? serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + if (reader.Depth == depth && reader.TokenType == JsonToken.EndObject) { break; } } - private ValueObject CreateValueObject(Type objectType, List properties, List propertyData) - { - var ctors = objectType.GetConstructors(_options.Flags).ToList(); - if (ctors.Count == 0) { return null; } + return propertyData; + } - var matchingCtor = ctors.SingleOrDefault(info => MatchesConstructor(info, propertyData)); - if (matchingCtor != null) - { - return matchingCtor.Invoke(propertyData.Select(pair => pair.Value).ToArray()) as ValueObject; - } + private DataPair ReadDataPair(JsonReader reader, PropertyInfo matchingProperty, JsonSerializer serializer) + { + if (matchingProperty.PropertyType.HasTypes(typeof(SingleValueObject<>))) + { + return new DataPair(matchingProperty.Name, serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + } - var defaultCtor = ctors.SingleOrDefault(ci => ci.GetParameters().Length == 0); - if (defaultCtor == null) { return null; } + return new DataPair(matchingProperty.Name, ParserFactory.FromObject().Parse(reader.Value?.ToString(), matchingProperty.PropertyType, o => o.FormatProvider = _options.FormatProvider) ?? serializer.Deserialize(reader, matchingProperty.PropertyType), matchingProperty.PropertyType); + } - return PopulateDefaultConstructed(defaultCtor, properties, propertyData); - } + private ValueObject CreateValueObject(Type objectType, List properties, List propertyData) + { + var ctors = objectType.GetConstructors(_options.Flags).ToList(); + if (ctors.Count == 0) { return null; } - private static bool MatchesConstructor(ConstructorInfo info, List propertyData) + var matchingCtor = ctors.SingleOrDefault(info => MatchesConstructor(info, propertyData)); + if (matchingCtor != null) { - var paramters = info.GetParameters().ToList(); - return paramters.Count == propertyData.Count && paramters.Select(pi => pi.ParameterType).SequenceEqual(propertyData.Select(pair => pair.Type)); + return matchingCtor.Invoke(propertyData.Select(pair => pair.Value).ToArray()) as ValueObject; } - private static ValueObject PopulateDefaultConstructed(ConstructorInfo defaultCtor, List properties, List propertyData) + var defaultCtor = ctors.SingleOrDefault(ci => ci.GetParameters().Length == 0); + if (defaultCtor == null) { return null; } + + return PopulateDefaultConstructed(defaultCtor, properties, propertyData); + } + + private static bool MatchesConstructor(ConstructorInfo info, List propertyData) + { + var paramters = info.GetParameters().ToList(); + return paramters.Count == propertyData.Count && paramters.Select(pi => pi.ParameterType).SequenceEqual(propertyData.Select(pair => pair.Type)); + } + + private static ValueObject PopulateDefaultConstructed(ConstructorInfo defaultCtor, List properties, List propertyData) + { + var vo = defaultCtor.Invoke(Array.Empty()) as ValueObject; + foreach (var property in properties) { - var vo = defaultCtor.Invoke(Array.Empty()) as ValueObject; - foreach (var property in properties) + if (property.CanWrite) { - if (property.CanWrite) - { - property.SetValue(vo, propertyData.SingleOrDefault(pair => pair.Name.Equals(property.Name, StringComparison.OrdinalIgnoreCase))?.Value); - } + property.SetValue(vo, propertyData.SingleOrDefault(pair => pair.Name.Equals(property.Name, StringComparison.OrdinalIgnoreCase))?.Value); } - - return vo; } + + return vo; } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs b/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs index 4c071e5e..4a2668ec 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs @@ -9,112 +9,111 @@ using Savvyio.Messaging; using Savvyio.Messaging.Cryptography; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +/// +/// Extension methods for the class. +/// +public static class JsonConverterExtensions { /// - /// Extension methods for the class. + /// Adds a converter to the collection. /// - public static class JsonConverterExtensions + /// The collection to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddValueObjectConverter(this ICollection converters, Action setup = null) { - /// - /// Adds a converter to the collection. - /// - /// The collection to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddValueObjectConverter(this ICollection converters, Action setup = null) - { - Validator.ThrowIfNull(converters); - converters.Add(new ValueObjectConverter(setup)); - return converters; - } + Validator.ThrowIfNull(converters); + converters.Add(new ValueObjectConverter(setup)); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection to extend. - /// The which may be configured. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddAggregateRootConverter(this ICollection converters, Action setup = null) - { - Validator.ThrowIfNull(converters); - converters.Add(new AggregateRootConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection to extend. + /// The which may be configured. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddAggregateRootConverter(this ICollection converters, Action setup = null) + { + Validator.ThrowIfNull(converters); + converters.Add(new AggregateRootConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddMetadataDictionaryConverter(this ICollection converters) + /// + /// Adds a converter to the collection. + /// + /// The collection to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddMetadataDictionaryConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(JsonConverterFactory.Create(null, (reader, _, _, _) => { - Validator.ThrowIfNull(converters); - converters.Add(JsonConverterFactory.Create(null, (reader, _, _, _) => + var md = new MetadataDictionary(); + var result = JData.ReadAll(reader); + foreach (var entry in result) { - var md = new MetadataDictionary(); - var result = JData.ReadAll(reader); - foreach (var entry in result) - { - md.Add(entry.PropertyName, entry.Value); - } - return md; - })); - return converters; - } + md.Add(entry.PropertyName, entry.Value); + } + return md; + })); + return converters; + } - /// - /// Adds an converter to the collection. - /// - /// The collection to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddRequestConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new RequestConverter()); - return converters; - } + /// + /// Adds an converter to the collection. + /// + /// The collection to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddRequestConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new RequestConverter()); + return converters; + } - /// - /// Adds an / converter to the collection. - /// - /// The collection to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddMessageConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new MessageConverter()); - return converters; - } + /// + /// Adds an / converter to the collection. + /// + /// The collection to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddMessageConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new MessageConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddSingleValueObjectConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new SingleValueObjectConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddSingleValueObjectConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new SingleValueObjectConverter()); + return converters; } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs b/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs index aa6cfde9..e904981b 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs @@ -1,35 +1,34 @@ using Codebelt.Extensions.Newtonsoft.Json.Serialization; using Newtonsoft.Json; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +/// +/// Provides extension methods for the class. +/// +public static class JsonSerializerExtensions { /// - /// Provides extension methods for the class. + /// Resolves the property key by convention using the specified . /// - public static class JsonSerializerExtensions + /// The to use for resolving the property key. + /// The name of the property to resolve. + /// The resolved property key. + public static string ResolvePropertyKeyByConvention(this JsonSerializer serializer, string name) { - /// - /// Resolves the property key by convention using the specified . - /// - /// The to use for resolving the property key. - /// The name of the property to resolve. - /// The resolved property key. - public static string ResolvePropertyKeyByConvention(this JsonSerializer serializer, string name) - { - var ns = serializer.ContractResolver.ResolveNamingStrategyOrDefault(); - return ns.GetPropertyName(name, false); - } + var ns = serializer.ContractResolver.ResolveNamingStrategyOrDefault(); + return ns.GetPropertyName(name, false); + } - /// - /// Resolves the dictionary key by convention using the specified . - /// - /// The to use for resolving the dictionary key. - /// The name of the dictionary key to resolve. - /// The resolved dictionary key. - public static string ResolveDictionaryKeyByConvention(this JsonSerializer serializer, string name) - { - var ns = serializer.ContractResolver.ResolveNamingStrategyOrDefault(); - return ns.GetDictionaryKey(name); - } + /// + /// Resolves the dictionary key by convention using the specified . + /// + /// The to use for resolving the dictionary key. + /// The name of the dictionary key to resolve. + /// The resolved dictionary key. + public static string ResolveDictionaryKeyByConvention(this JsonSerializer serializer, string name) + { + var ns = serializer.ContractResolver.ResolveNamingStrategyOrDefault(); + return ns.GetDictionaryKey(name); } } diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs b/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs index ba4db167..360eb89e 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs @@ -3,65 +3,64 @@ using Codebelt.Extensions.Newtonsoft.Json.Formatters; using Newtonsoft.Json; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +/// +/// Provides a class for marshalling data using the Newtonsoft JSON library. +/// +/// +public class NewtonsoftJsonMarshaller : IMarshaller { + private readonly Action _setup; + /// - /// Provides a class for marshalling data using the Newtonsoft JSON library. + /// Provides a default instance of the class optimized for messaging. /// - /// - public class NewtonsoftJsonMarshaller : IMarshaller - { - private readonly Action _setup; + /// The default instance of the class optimized for messaging. + public static NewtonsoftJsonMarshaller Default { get; } = new(o => o.Settings.Formatting = Formatting.None); - /// - /// Provides a default instance of the class optimized for messaging. - /// - /// The default instance of the class optimized for messaging. - public static NewtonsoftJsonMarshaller Default { get; } = new(o => o.Settings.Formatting = Formatting.None); - - /// - /// Creates a new instance of the class. - /// - /// The which may be configured. - /// JsonMarshaller. - public static NewtonsoftJsonMarshaller Create(Action setup = null) => new(setup); + /// + /// Creates a new instance of the class. + /// + /// The which may be configured. + /// JsonMarshaller. + public static NewtonsoftJsonMarshaller Create(Action setup = null) => new(setup); - static NewtonsoftJsonMarshaller() - { - Bootstrapper.Initialize(); - } + static NewtonsoftJsonMarshaller() + { + Bootstrapper.Initialize(); + } - /// - /// Initializes a new instance of the class. - /// - /// The which need to be configured. - public NewtonsoftJsonMarshaller(Action setup = null) - { - _setup = setup; - } + /// + /// Initializes a new instance of the class. + /// + /// The which need to be configured. + public NewtonsoftJsonMarshaller(Action setup = null) + { + _setup = setup; + } - /// - public Stream Serialize(TValue value) - { - return NewtonsoftJsonFormatter.SerializeObject(value, _setup); - } + /// + public Stream Serialize(TValue value) + { + return NewtonsoftJsonFormatter.SerializeObject(value, _setup); + } - /// - public Stream Serialize(object value, Type inputType) - { - return NewtonsoftJsonFormatter.SerializeObject(value, inputType, _setup); - } + /// + public Stream Serialize(object value, Type inputType) + { + return NewtonsoftJsonFormatter.SerializeObject(value, inputType, _setup); + } - /// - public TValue Deserialize(Stream data) - { - return NewtonsoftJsonFormatter.DeserializeObject(data, _setup); - } + /// + public TValue Deserialize(Stream data) + { + return NewtonsoftJsonFormatter.DeserializeObject(data, _setup); + } - /// - public object Deserialize(Stream data, Type returnType) - { - return NewtonsoftJsonFormatter.DeserializeObject(data, returnType, _setup); - } + /// + public object Deserialize(Stream data, Type returnType) + { + return NewtonsoftJsonFormatter.DeserializeObject(data, returnType, _setup); } } diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs index 4e35b5d8..6e573b3f 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs @@ -11,232 +11,231 @@ using Cuemon.Threading; using Savvyio.Messaging; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +/// +/// Represents the base class from which all implementations of Azure Storage Queue should derive. +/// +/// The type of the request. +public abstract class AzureQueue where TRequest : IRequest { - /// - /// Represents the base class from which all implementations of Azure Storage Queue should derive. - /// - /// The type of the request. - public abstract class AzureQueue where TRequest : IRequest + private readonly IMarshaller _marshaller; + private readonly AzureQueueOptions _options; + private readonly QueueServiceClient _serviceClient; + private readonly QueueClient _client; + + private readonly Func, IMarshaller, string> _sendMessageFormatter = (message, marshaller) => { - private readonly IMarshaller _marshaller; - private readonly AzureQueueOptions _options; - private readonly QueueServiceClient _serviceClient; - private readonly QueueClient _client; + var base64Type = message.GetType() + .ToFullNameIncludingAssemblyName() + .ToByteArray() + .ToBase64String(); - private readonly Func, IMarshaller, string> _sendMessageFormatter = (message, marshaller) => - { - var base64Type = message.GetType() - .ToFullNameIncludingAssemblyName() - .ToByteArray() - .ToBase64String(); + var base64Message = marshaller.Serialize(message) + .ToByteArray() + .ToBase64String(); - var base64Message = marshaller.Serialize(message) - .ToByteArray() - .ToBase64String(); + return $"{base64Type}.{base64Message}"; + }; - return $"{base64Type}.{base64Message}"; - }; + private readonly Func> _receiveMessageFormatter = (rawMessage, marshaller) => + { + var base64Components = rawMessage.MessageText.Split('.'); + var type = Type.GetType(base64Components[0].FromBase64().ToEncodedString()); + return marshaller.Deserialize(base64Components[1].FromBase64().ToStream(), type) as IMessage; + }; - private readonly Func> _receiveMessageFormatter = (rawMessage, marshaller) => - { - var base64Components = rawMessage.MessageText.Split('.'); - var type = Type.GetType(base64Components[0].FromBase64().ToEncodedString()); - return marshaller.Deserialize(base64Components[1].FromBase64().ToStream(), type) as IMessage; - }; - - /// - /// Initializes a new instance of the class with testable Azure Storage Queue clients. - /// - /// The marshaller used for serializing and deserializing messages. - /// The used to configure this instance. - /// The queue service client to use. - /// The queue client to use. - /// The function delegate to format messages for sending. If null, a default formatter is used. - /// The function delegate to format messages for receiving. If null, a default formatter is used. - /// - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - protected AzureQueue(IMarshaller marshaller, AzureQueueOptions options, QueueServiceClient serviceClient, QueueClient client, Func, IMarshaller, string> sendMessageFormatter = null, Func> receiveMessageFormatter = null) - { - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidOptions(options); - Validator.ThrowIfNull(serviceClient); - Validator.ThrowIfNull(client); - - _marshaller = marshaller; - _options = options; - _serviceClient = serviceClient; - _client = client; - _sendMessageFormatter = sendMessageFormatter ?? _sendMessageFormatter; - _receiveMessageFormatter = receiveMessageFormatter ?? _receiveMessageFormatter; - - options.SetConfiguredClient(_client); - } + /// + /// Initializes a new instance of the class with testable Azure Storage Queue clients. + /// + /// The marshaller used for serializing and deserializing messages. + /// The used to configure this instance. + /// The queue service client to use. + /// The queue client to use. + /// The function delegate to format messages for sending. If null, a default formatter is used. + /// The function delegate to format messages for receiving. If null, a default formatter is used. + /// + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected AzureQueue(IMarshaller marshaller, AzureQueueOptions options, QueueServiceClient serviceClient, QueueClient client, Func, IMarshaller, string> sendMessageFormatter = null, Func> receiveMessageFormatter = null) + { + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidOptions(options); + Validator.ThrowIfNull(serviceClient); + Validator.ThrowIfNull(client); + + _marshaller = marshaller; + _options = options; + _serviceClient = serviceClient; + _client = client; + _sendMessageFormatter = sendMessageFormatter ?? _sendMessageFormatter; + _receiveMessageFormatter = receiveMessageFormatter ?? _receiveMessageFormatter; + + options.SetConfiguredClient(_client); + } - /// - /// Initializes a new instance of the class. - /// - /// The marshaller used for serializing and deserializing messages. - /// The used to configure this instance. - /// The function delegate to format messages for sending. If null, a default formatter is used. - /// The function delegate to format messages for receiving. If null, a default formatter is used. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - /// - /// The following table shows the initial field values for an instance of . - /// - /// - /// Field - /// Initial Value - /// - /// - /// - /// - /// (message, marshaller) => - /// { - /// var base64Type = message.GetType() - /// .ToFullNameIncludingAssemblyName() - /// .ToByteArray() - /// .ToBase64String(); - /// var base64Message = marshaller.Serialize(message) - /// .ToByteArray() - /// .ToBase64String(); - /// return $"{base64Type}.{base64Message}"; - /// }; - /// - /// - /// - /// - /// - /// (rawMessage, marshaller) => - /// { - /// var base64Components = rawMessage.MessageText.Split('.'); - /// var type = Type.GetType(base64Components[0].FromBase64().ToEncodedString()); - /// return marshaller.Deserialize(base64Components[1].FromBase64().ToStream(), type) as IMessage<TRequest>; - /// }; - /// - /// - /// - /// - protected AzureQueue(IMarshaller marshaller, AzureQueueOptions options, Func, IMarshaller, string> sendMessageFormatter = null, Func> receiveMessageFormatter = null) - { - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidOptions(options); + /// + /// Initializes a new instance of the class. + /// + /// The marshaller used for serializing and deserializing messages. + /// The used to configure this instance. + /// The function delegate to format messages for sending. If null, a default formatter is used. + /// The function delegate to format messages for receiving. If null, a default formatter is used. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + /// + /// The following table shows the initial field values for an instance of . + /// + /// + /// Field + /// Initial Value + /// + /// + /// + /// + /// (message, marshaller) => + /// { + /// var base64Type = message.GetType() + /// .ToFullNameIncludingAssemblyName() + /// .ToByteArray() + /// .ToBase64String(); + /// var base64Message = marshaller.Serialize(message) + /// .ToByteArray() + /// .ToBase64String(); + /// return $"{base64Type}.{base64Message}"; + /// }; + /// + /// + /// + /// + /// + /// (rawMessage, marshaller) => + /// { + /// var base64Components = rawMessage.MessageText.Split('.'); + /// var type = Type.GetType(base64Components[0].FromBase64().ToEncodedString()); + /// return marshaller.Deserialize(base64Components[1].FromBase64().ToStream(), type) as IMessage<TRequest>; + /// }; + /// + /// + /// + /// + protected AzureQueue(IMarshaller marshaller, AzureQueueOptions options, Func, IMarshaller, string> sendMessageFormatter = null, Func> receiveMessageFormatter = null) + { + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidOptions(options); - _marshaller = marshaller; - _options = options; - _sendMessageFormatter = sendMessageFormatter ?? _sendMessageFormatter; - _receiveMessageFormatter = receiveMessageFormatter ?? _receiveMessageFormatter; + _marshaller = marshaller; + _options = options; + _sendMessageFormatter = sendMessageFormatter ?? _sendMessageFormatter; + _receiveMessageFormatter = receiveMessageFormatter ?? _receiveMessageFormatter; - if (string.IsNullOrWhiteSpace(options.ConnectionString)) + if (string.IsNullOrWhiteSpace(options.ConnectionString)) + { + var queueUri = $"https://{options.StorageAccountName}.queue.core.windows.net/{options.QueueName}".ToUri(); + if (options.Credential != null) + { + _serviceClient = new QueueServiceClient(queueUri, options.Credential, options.Settings); + } + else if (options.SasCredential != null) { - var queueUri = $"https://{options.StorageAccountName}.queue.core.windows.net/{options.QueueName}".ToUri(); - if (options.Credential != null) - { - _serviceClient = new QueueServiceClient(queueUri, options.Credential, options.Settings); - } - else if (options.SasCredential != null) - { - _serviceClient = new QueueServiceClient(queueUri, options.SasCredential, options.Settings); - } - else if (options.StorageKeyCredential != null) - { - _serviceClient = new QueueServiceClient(queueUri, options.StorageKeyCredential, options.Settings); - } + _serviceClient = new QueueServiceClient(queueUri, options.SasCredential, options.Settings); } - else + else if (options.StorageKeyCredential != null) { - _serviceClient = new QueueServiceClient(options.ConnectionString, options.Settings); + _serviceClient = new QueueServiceClient(queueUri, options.StorageKeyCredential, options.Settings); } + } + else + { + _serviceClient = new QueueServiceClient(options.ConnectionString, options.Settings); + } - _client = _serviceClient!.GetQueueClient(options.QueueName); + _client = _serviceClient!.GetQueueClient(options.QueueName); - options.SetConfiguredClient(_client); - } + options.SetConfiguredClient(_client); + } - /// - /// Sends the specified messages to the Azure Storage Queue. - /// - /// The messages to send. - /// The which may be configured. - /// A task that represents the asynchronous operation. - /// - /// cannot be null. - /// - protected async Task SendMessageAsync(IEnumerable> messages, Action setup = null) - { - Validator.ThrowIfNull(messages); - Validator.ThrowIfInvalidConfigurator(setup, out var options); + /// + /// Sends the specified messages to the Azure Storage Queue. + /// + /// The messages to send. + /// The which may be configured. + /// A task that represents the asynchronous operation. + /// + /// cannot be null. + /// + protected async Task SendMessageAsync(IEnumerable> messages, Action setup = null) + { + Validator.ThrowIfNull(messages); + Validator.ThrowIfInvalidConfigurator(setup, out var options); - foreach (var message in messages) - { - await _client.SendMessageAsync(_sendMessageFormatter(message, _marshaller), - _options.SendContext.VisibilityTimeout, - _options.SendContext.TimeToLive, - options.CancellationToken).ConfigureAwait(false); - } + foreach (var message in messages) + { + await _client.SendMessageAsync(_sendMessageFormatter(message, _marshaller), + _options.SendContext.VisibilityTimeout, + _options.SendContext.TimeToLive, + options.CancellationToken).ConfigureAwait(false); } + } - /// - /// Receives messages from the Azure Storage Queue. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - protected async IAsyncEnumerable> ReceiveMessagesAsync(Action setup = null) - { - Validator.ThrowIfInvalidConfigurator(setup, out var options); + /// + /// Receives messages from the Azure Storage Queue. + /// + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + protected async IAsyncEnumerable> ReceiveMessagesAsync(Action setup = null) + { + Validator.ThrowIfInvalidConfigurator(setup, out var options); - var rawMessages = await _client.ReceiveMessagesAsync(_options.ReceiveContext.NumberOfMessagesToTakePerRequest, - _options.ReceiveContext.VisibilityTimeout, - options.CancellationToken).ConfigureAwait(false); + var rawMessages = await _client.ReceiveMessagesAsync(_options.ReceiveContext.NumberOfMessagesToTakePerRequest, + _options.ReceiveContext.VisibilityTimeout, + options.CancellationToken).ConfigureAwait(false); - if (rawMessages.HasValue && rawMessages.Value.Length > 0) + if (rawMessages.HasValue && rawMessages.Value.Length > 0) + { + foreach (var rawMessage in rawMessages.Value) { - foreach (var rawMessage in rawMessages.Value) - { - options.CancellationToken.ThrowIfCancellationRequested(); - - var message = _receiveMessageFormatter(rawMessage, _marshaller); - message!.Properties.Add(nameof(QueueMessage.MessageId), rawMessage.MessageId); - message.Properties.Add(nameof(QueueMessage.PopReceipt), rawMessage.PopReceipt); - message.Properties.Add(nameof(CancellationToken), options.CancellationToken); - message.Acknowledged += OnAcknowledgedAsync; - yield return message; - } + options.CancellationToken.ThrowIfCancellationRequested(); + + var message = _receiveMessageFormatter(rawMessage, _marshaller); + message!.Properties.Add(nameof(QueueMessage.MessageId), rawMessage.MessageId); + message.Properties.Add(nameof(QueueMessage.PopReceipt), rawMessage.PopReceipt); + message.Properties.Add(nameof(CancellationToken), options.CancellationToken); + message.Acknowledged += OnAcknowledgedAsync; + yield return message; } } + } - /// - /// Handles the acknowledgment of a message by deleting it from the queue. - /// - /// The message that was acknowledged. - /// The event arguments containing properties of the acknowledged message. - private async Task OnAcknowledgedAsync(object sender, AcknowledgedEventArgs args) - { - var messageId = (string)args.Properties[nameof(QueueMessage.MessageId)]; - var popReceipt = (string)args.Properties[nameof(QueueMessage.PopReceipt)]; - var cancellationToken = (CancellationToken)args.Properties[nameof(CancellationToken)]; + /// + /// Handles the acknowledgment of a message by deleting it from the queue. + /// + /// The message that was acknowledged. + /// The event arguments containing properties of the acknowledged message. + private async Task OnAcknowledgedAsync(object sender, AcknowledgedEventArgs args) + { + var messageId = (string)args.Properties[nameof(QueueMessage.MessageId)]; + var popReceipt = (string)args.Properties[nameof(QueueMessage.PopReceipt)]; + var cancellationToken = (CancellationToken)args.Properties[nameof(CancellationToken)]; - await _client.DeleteMessageAsync(messageId, popReceipt, cancellationToken).ConfigureAwait(false); + await _client.DeleteMessageAsync(messageId, popReceipt, cancellationToken).ConfigureAwait(false); - if (sender is IAcknowledgeable message) { message.Acknowledged -= OnAcknowledgedAsync; } - } + if (sender is IAcknowledgeable message) { message.Acknowledged -= OnAcknowledgedAsync; } + } - internal QueueServiceClient GetQueueServiceClient() - { - return _serviceClient; - } + internal QueueServiceClient GetQueueServiceClient() + { + return _serviceClient; } } diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs index c84027e9..8c7f813c 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs @@ -7,192 +7,191 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +/// +/// Configuration options for . +/// +public class AzureQueueOptions : IValidatableParameterObject { /// - /// Configuration options for . + /// The maximum number of messages that Azure Queue Storage supports when retrieving. + /// + public const int MaxNumberOfMessages = 32; + + /// + /// The maximum visibility timeout for messages in Azure Queue Storage. /// - public class AzureQueueOptions : IValidatableParameterObject + public static readonly TimeSpan MaxVisibilityTimeout = TimeSpan.FromDays(7); + + private Action _clientCallback; + private StorageSharedKeyCredential _storageKeyCredential; + private AzureSasCredential _sasCredential; + private TokenCredential _credential; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// new DefaultAzureCredential() + /// + /// + /// + /// null + /// + /// + /// + /// new QueueClientOptions() + /// + /// + /// + /// new AzureQueueReceiveOptions() + /// + /// + /// + /// new AzureQueueSendOptions() + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + public AzureQueueOptions() { - /// - /// The maximum number of messages that Azure Queue Storage supports when retrieving. - /// - public const int MaxNumberOfMessages = 32; - - /// - /// The maximum visibility timeout for messages in Azure Queue Storage. - /// - public static readonly TimeSpan MaxVisibilityTimeout = TimeSpan.FromDays(7); - - private Action _clientCallback; - private StorageSharedKeyCredential _storageKeyCredential; - private AzureSasCredential _sasCredential; - private TokenCredential _credential; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// new DefaultAzureCredential() - /// - /// - /// - /// null - /// - /// - /// - /// new QueueClientOptions() - /// - /// - /// - /// new AzureQueueReceiveOptions() - /// - /// - /// - /// new AzureQueueSendOptions() - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - public AzureQueueOptions() - { - Credential = new DefaultAzureCredential(); - Settings = new QueueClientOptions(); - ReceiveContext = new AzureQueueReceiveOptions(); - SendContext = new AzureQueueSendOptions(); - } + Credential = new DefaultAzureCredential(); + Settings = new QueueClientOptions(); + ReceiveContext = new AzureQueueReceiveOptions(); + SendContext = new AzureQueueSendOptions(); + } - /// - /// Gets the options for receiving messages from the queue. - /// - public AzureQueueReceiveOptions ReceiveContext { get; } - - /// - /// Gets the options for sending messages to the queue. - /// - public AzureQueueSendOptions SendContext { get; } - - /// - /// Gets or sets the name of the storage account. - /// - public string StorageAccountName { get; set; } - - /// - /// Gets or sets the name of the queue. - /// - public string QueueName { get; set; } - - /// - /// Gets or sets the credential used to authenticate with Azure. - /// - /// Setting this property will nullify and as they are mutually exclusive. - public TokenCredential Credential - { - get => _credential; - set - { - _credential = value; - _sasCredential = null; - _storageKeyCredential = null; - } - } + /// + /// Gets the options for receiving messages from the queue. + /// + public AzureQueueReceiveOptions ReceiveContext { get; } - /// - /// Gets or sets the SAS credential used to authenticate with Azure. - /// - /// Setting this property will nullify and as they are mutually exclusive. - public AzureSasCredential SasCredential - { - get => _sasCredential; - set - { - _sasCredential = value; - _credential = null; - _storageKeyCredential = null; - } - } + /// + /// Gets the options for sending messages to the queue. + /// + public AzureQueueSendOptions SendContext { get; } + + /// + /// Gets or sets the name of the storage account. + /// + public string StorageAccountName { get; set; } - /// - /// Gets or sets the storage key credential used to authenticate with Azure. - /// - /// Setting this property will nullify and as they are mutually exclusive. - public StorageSharedKeyCredential StorageKeyCredential + /// + /// Gets or sets the name of the queue. + /// + public string QueueName { get; set; } + + /// + /// Gets or sets the credential used to authenticate with Azure. + /// + /// Setting this property will nullify and as they are mutually exclusive. + public TokenCredential Credential + { + get => _credential; + set { - get => _storageKeyCredential; - set - { - _storageKeyCredential = value; - _credential = null; - _sasCredential = null; - } + _credential = value; + _sasCredential = null; + _storageKeyCredential = null; } + } - /// - /// Gets or sets the connection string used to connect to the Azure storage account. - /// - public string ConnectionString { get; set; } - - /// - /// Gets the settings for the >. - /// - public QueueClientOptions Settings { get; } - - /// - /// Provides a way to post-configure the client after it has been created. - /// - /// The delegate to post-configure the client. - /// A reference to this instance. - /// This was added to support invoking methods of interest: https://learn.microsoft.com/en-us/dotnet/api/azure.storage.queues.queueclient?view=azure-dotnet#methods - public AzureQueueOptions PostConfigureClient(Action factory) + /// + /// Gets or sets the SAS credential used to authenticate with Azure. + /// + /// Setting this property will nullify and as they are mutually exclusive. + public AzureSasCredential SasCredential + { + get => _sasCredential; + set { - _clientCallback = factory; - return this; + _sasCredential = value; + _credential = null; + _storageKeyCredential = null; } + } - internal void SetConfiguredClient(QueueClient client) + /// + /// Gets or sets the storage key credential used to authenticate with Azure. + /// + /// Setting this property will nullify and as they are mutually exclusive. + public StorageSharedKeyCredential StorageKeyCredential + { + get => _storageKeyCredential; + set { - _clientCallback?.Invoke(client); + _storageKeyCredential = value; + _credential = null; + _sasCredential = null; } + } - /// - /// Validates the options to ensure they are in a valid state. - /// - /// - /// cannot be null, empty, or consists only of white-space characters when was specified -or- - /// and and cannot be null -or- - /// and cannot be null, empty, or consists only of white-space characters. - /// - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(!string.IsNullOrWhiteSpace(ConnectionString) && string.IsNullOrWhiteSpace(QueueName), $"{nameof(QueueName)} cannot be null, empty, or consists only of white-space when a {nameof(ConnectionString)} has been specified."); + /// + /// Gets or sets the connection string used to connect to the Azure storage account. + /// + public string ConnectionString { get; set; } + + /// + /// Gets the settings for the >. + /// + public QueueClientOptions Settings { get; } + + /// + /// Provides a way to post-configure the client after it has been created. + /// + /// The delegate to post-configure the client. + /// A reference to this instance. + /// This was added to support invoking methods of interest: https://learn.microsoft.com/en-us/dotnet/api/azure.storage.queues.queueclient?view=azure-dotnet#methods + public AzureQueueOptions PostConfigureClient(Action factory) + { + _clientCallback = factory; + return this; + } - Validator.ThrowIfInvalidState(Credential == null && SasCredential == null && StorageKeyCredential == null, "A credential type has to be specified for Azure authentication."); + internal void SetConfiguredClient(QueueClient client) + { + _clientCallback?.Invoke(client); + } - Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(StorageAccountName) && string.IsNullOrWhiteSpace(QueueName), $"{nameof(StorageAccountName)} and {nameof(QueueName)} cannot be null, empty, or consists only of white-space characters."); + /// + /// Validates the options to ensure they are in a valid state. + /// + /// + /// cannot be null, empty, or consists only of white-space characters when was specified -or- + /// and and cannot be null -or- + /// and cannot be null, empty, or consists only of white-space characters. + /// + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(!string.IsNullOrWhiteSpace(ConnectionString) && string.IsNullOrWhiteSpace(QueueName), $"{nameof(QueueName)} cannot be null, empty, or consists only of white-space when a {nameof(ConnectionString)} has been specified."); + + Validator.ThrowIfInvalidState(Credential == null && SasCredential == null && StorageKeyCredential == null, "A credential type has to be specified for Azure authentication."); + + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(StorageAccountName) && string.IsNullOrWhiteSpace(QueueName), $"{nameof(StorageAccountName)} and {nameof(QueueName)} cannot be null, empty, or consists only of white-space characters."); - } } } diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs index 1baa0610..751b9bbd 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs @@ -1,54 +1,53 @@ using System; using Cuemon.Configuration; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +/// +/// Configuration options that is related to receiving messages from an Azure Storage Queue. +/// +public class AzureQueueReceiveOptions : IParameterObject { + private int _numberOfMessagesToTakePerRequest; + private TimeSpan _visibilityTimeout; + /// - /// Configuration options that is related to receiving messages from an Azure Storage Queue. + /// Initializes a new instance of the class. /// - public class AzureQueueReceiveOptions : IParameterObject + internal AzureQueueReceiveOptions() { - private int _numberOfMessagesToTakePerRequest; - private TimeSpan _visibilityTimeout; - - /// - /// Initializes a new instance of the class. - /// - internal AzureQueueReceiveOptions() - { - NumberOfMessagesToTakePerRequest = 10; - VisibilityTimeout = TimeSpan.FromSeconds(30); - } + NumberOfMessagesToTakePerRequest = 10; + VisibilityTimeout = TimeSpan.FromSeconds(30); + } - /// - /// Gets or sets the number of messages to return per request. Default is 10. - /// - /// The number of messages to return per request. - /// Max. allowed value is limited to . - public int NumberOfMessagesToTakePerRequest - { - get => _numberOfMessagesToTakePerRequest; - set => _numberOfMessagesToTakePerRequest = Math.Clamp(value, 1, AzureQueueOptions.MaxNumberOfMessages); - } + /// + /// Gets or sets the number of messages to return per request. Default is 10. + /// + /// The number of messages to return per request. + /// Max. allowed value is limited to . + public int NumberOfMessagesToTakePerRequest + { + get => _numberOfMessagesToTakePerRequest; + set => _numberOfMessagesToTakePerRequest = Math.Clamp(value, 1, AzureQueueOptions.MaxNumberOfMessages); + } - /// - /// Gets or sets the visibility timeout for the messages. Default is 30 seconds. - /// - /// The visibility timeout for the messages. - /// - /// The minimum allowed value is 1 second, and the maximum allowed value is limited to . - ///
- /// Reference: https://learn.microsoft.com/en-us/rest/api/storageservices/get-messages#uri-parameters - ///
- public TimeSpan VisibilityTimeout + /// + /// Gets or sets the visibility timeout for the messages. Default is 30 seconds. + /// + /// The visibility timeout for the messages. + /// + /// The minimum allowed value is 1 second, and the maximum allowed value is limited to . + ///
+ /// Reference: https://learn.microsoft.com/en-us/rest/api/storageservices/get-messages#uri-parameters + ///
+ public TimeSpan VisibilityTimeout + { + get => _visibilityTimeout; + set { - get => _visibilityTimeout; - set - { - if (value < TimeSpan.FromSeconds(1)) { value = TimeSpan.FromSeconds(1); } - if (value > AzureQueueOptions.MaxVisibilityTimeout) { value = AzureQueueOptions.MaxVisibilityTimeout; } - _visibilityTimeout = value; - } + if (value < TimeSpan.FromSeconds(1)) { value = TimeSpan.FromSeconds(1); } + if (value > AzureQueueOptions.MaxVisibilityTimeout) { value = AzureQueueOptions.MaxVisibilityTimeout; } + _visibilityTimeout = value; } } } diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs index 7468bc87..f16b7e45 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs @@ -1,48 +1,47 @@ using System; using Cuemon.Configuration; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +/// +/// Configuration options that is related to sending messages from an Azure Storage Queue. +/// +public class AzureQueueSendOptions : IParameterObject { + private TimeSpan _visibilityTimeout; + /// - /// Configuration options that is related to sending messages from an Azure Storage Queue. + /// Initializes a new instance of the class. /// - public class AzureQueueSendOptions : IParameterObject + internal AzureQueueSendOptions() { - private TimeSpan _visibilityTimeout; - - /// - /// Initializes a new instance of the class. - /// - internal AzureQueueSendOptions() - { - VisibilityTimeout = TimeSpan.Zero; - TimeToLive = TimeSpan.FromDays(7); - } + VisibilityTimeout = TimeSpan.Zero; + TimeToLive = TimeSpan.FromDays(7); + } - /// - /// Gets or sets the time-to-live for the messages. Default is 7 days. - /// - /// The time-to-live for the messages. - public TimeSpan TimeToLive { get; set; } + /// + /// Gets or sets the time-to-live for the messages. Default is 7 days. + /// + /// The time-to-live for the messages. + public TimeSpan TimeToLive { get; set; } - /// - /// Gets or sets the visibility timeout for the messages. Default is . - /// - /// The visibility timeout for the messages. - /// - /// The minimum allowed value is , and the maximum allowed value is limited to . - ///
- /// Reference: https://learn.microsoft.com/en-us/rest/api/storageservices/put-message#uri-parameters - ///
- public TimeSpan VisibilityTimeout + /// + /// Gets or sets the visibility timeout for the messages. Default is . + /// + /// The visibility timeout for the messages. + /// + /// The minimum allowed value is , and the maximum allowed value is limited to . + ///
+ /// Reference: https://learn.microsoft.com/en-us/rest/api/storageservices/put-message#uri-parameters + ///
+ public TimeSpan VisibilityTimeout + { + get => _visibilityTimeout; + set { - get => _visibilityTimeout; - set - { - if (value < TimeSpan.Zero) { value = TimeSpan.Zero; } - if (value > AzureQueueOptions.MaxVisibilityTimeout) { value = AzureQueueOptions.MaxVisibilityTimeout; } - _visibilityTimeout = value; - } + if (value < TimeSpan.Zero) { value = TimeSpan.Zero; } + if (value > AzureQueueOptions.MaxVisibilityTimeout) { value = AzureQueueOptions.MaxVisibilityTimeout; } + _visibilityTimeout = value; } } } diff --git a/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs b/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs index 885570d9..842432b2 100644 --- a/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs +++ b/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs @@ -7,60 +7,59 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Savvyio.Extensions.QueueStorage.Commands +namespace Savvyio.Extensions.QueueStorage.Commands; + +/// +/// Provides an Azure Storage Queue implementation of the . +/// +public class AzureCommandQueue : AzureQueue, IPointToPointChannel, IHealthCheckProvider { /// - /// Provides an Azure Storage Queue implementation of the . + /// Initializes a new instance of the class. /// - public class AzureCommandQueue : AzureQueue, IPointToPointChannel, IHealthCheckProvider + /// 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 AzureCommandQueue(IMarshaller marshaller, AzureQueueOptions options) : base(marshaller, 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 AzureCommandQueue(IMarshaller marshaller, AzureQueueOptions options) : base(marshaller, options) - { - } + } - /// - /// Sends the specified messages to the Azure Storage Queue. - /// - /// The messages to send. - /// The which may be configured. - /// A task that represents the asynchronous operation. - /// - /// cannot be null. - /// - public Task SendAsync(IEnumerable> messages, Action setup = null) - { - return SendMessageAsync(messages, setup); - } + /// + /// Sends the specified messages to the Azure Storage Queue. + /// + /// The messages to send. + /// The which may be configured. + /// A task that represents the asynchronous operation. + /// + /// cannot be null. + /// + public Task SendAsync(IEnumerable> messages, Action setup = null) + { + return SendMessageAsync(messages, setup); + } - /// - /// Receives messages from the Azure Storage Queue. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - public IAsyncEnumerable> ReceiveAsync(Action setup = null) - { - return ReceiveMessagesAsync(setup); - } + /// + /// Receives messages from the Azure Storage Queue. + /// + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + public IAsyncEnumerable> ReceiveAsync(Action setup = null) + { + return ReceiveMessagesAsync(setup); + } - /// - /// Gets the instance used for probing the health status of the Azure Storage Queue service. - /// - /// The instance representing the client connection to the Azure Storage Queue service. - public QueueServiceClient GetHealthCheckTarget() - { - return GetQueueServiceClient(); // fetch from base class - } + /// + /// Gets the instance used for probing the health status of the Azure Storage Queue service. + /// + /// The instance representing the client connection to the Azure Storage Queue service. + public QueueServiceClient GetHealthCheckTarget() + { + return GetQueueServiceClient(); // fetch from base class } } diff --git a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs index 7c4a5aea..49592f95 100644 --- a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs +++ b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs @@ -15,148 +15,147 @@ using Savvyio.Messaging; using Savvyio.Messaging.Cryptography; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +/// +/// Provides a combined Azure Event Grid/Azure Storage Queue implementation of the . +/// +public class AzureEventBus : AzureQueue, IPublishSubscribeChannel, IHealthCheckProvider { + private readonly EventGridPublisherClient _client; + private readonly IMarshaller _marshaller; + private readonly AzureEventBusOptions _options; + /// - /// Provides a combined Azure Event Grid/Azure Storage Queue implementation of the . + /// The attribute name for the CloudEvent type extension. /// - public class AzureEventBus : AzureQueue, IPublishSubscribeChannel, IHealthCheckProvider - { - private readonly EventGridPublisherClient _client; - private readonly IMarshaller _marshaller; - private readonly AzureEventBusOptions _options; - - /// - /// The attribute name for the CloudEvent type extension. - /// - public const string CloudEventTypeExtensionAttribute = "typeext"; - - /// - /// Initializes a new instance of the class. - /// - /// The to use for serializing and deserializing implementations to messages. - /// The for configuring . - /// The used to configure this instance. - public AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions) : base(marshaller, azureQueueOptions, receiveMessageFormatter: FormatCloudEventQueueMessage) - { - Validator.ThrowIfInvalidOptions(azureEventBusOptions); + public const string CloudEventTypeExtensionAttribute = "typeext"; - _marshaller = marshaller; + /// + /// Initializes a new instance of the class. + /// + /// The to use for serializing and deserializing implementations to messages. + /// The for configuring . + /// The used to configure this instance. + public AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions) : base(marshaller, azureQueueOptions, receiveMessageFormatter: FormatCloudEventQueueMessage) + { + Validator.ThrowIfInvalidOptions(azureEventBusOptions); - if (azureEventBusOptions.Credential != null) - { - _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.Credential, azureEventBusOptions.Settings); - } - else if (azureEventBusOptions.SasCredential != null) - { - _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.SasCredential, azureEventBusOptions.Settings); - } - else if (azureEventBusOptions.KeyCredential != null) - { - _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.KeyCredential, azureEventBusOptions.Settings); - } + _marshaller = marshaller; - _options = azureEventBusOptions; + if (azureEventBusOptions.Credential != null) + { + _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.Credential, azureEventBusOptions.Settings); } - - /// - /// Initializes a new instance of the class with testable Azure clients. - /// - /// The to use for serializing and deserializing implementations to messages. - /// The for configuring . - /// The used to configure this instance. - /// The queue service client to use. - /// The queue client to use. - /// The event grid publisher client to use. - protected AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions, QueueServiceClient queueServiceClient, QueueClient queueClient, EventGridPublisherClient eventGridClient) : base(marshaller, azureQueueOptions, queueServiceClient, queueClient, receiveMessageFormatter: FormatCloudEventQueueMessage) + else if (azureEventBusOptions.SasCredential != null) { - Validator.ThrowIfInvalidOptions(azureEventBusOptions); - - _marshaller = marshaller; - _client = eventGridClient; - _options = azureEventBusOptions; + _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.SasCredential, azureEventBusOptions.Settings); } - - /// - /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The message to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - /// - /// cannot be null. - /// - public async Task PublishAsync(IMessage message, Action setup = null) + else if (azureEventBusOptions.KeyCredential != null) { - Validator.ThrowIfNull(message); - Validator.ThrowIfInvalidConfigurator(setup, out var options); + _client = new EventGridPublisherClient(azureEventBusOptions.TopicEndpoint, azureEventBusOptions.KeyCredential, azureEventBusOptions.Settings); + } - var ce = message.ToCloudEvent(); + _options = azureEventBusOptions; + } - if (message is ISignedMessage signedMessage) { ce.Add(nameof(ISignedMessage.Signature), signedMessage.Signature); } + /// + /// Initializes a new instance of the class with testable Azure clients. + /// + /// The to use for serializing and deserializing implementations to messages. + /// The for configuring . + /// The used to configure this instance. + /// The queue service client to use. + /// The queue client to use. + /// The event grid publisher client to use. + protected AzureEventBus(IMarshaller marshaller, AzureQueueOptions azureQueueOptions, AzureEventBusOptions azureEventBusOptions, QueueServiceClient queueServiceClient, QueueClient queueClient, EventGridPublisherClient eventGridClient) : base(marshaller, azureQueueOptions, queueServiceClient, queueClient, receiveMessageFormatter: FormatCloudEventQueueMessage) + { + Validator.ThrowIfInvalidOptions(azureEventBusOptions); - ce.Add(CloudEventTypeExtensionAttribute, message.GetType().ToFullNameIncludingAssemblyName()); + _marshaller = marshaller; + _client = eventGridClient; + _options = azureEventBusOptions; + } - var json = _marshaller.Serialize(ce).ToEncodedString(); - await _client.SendEventAsync(Azure.Messaging.CloudEvent.Parse(new BinaryData(json)), options.CancellationToken).ConfigureAwait(false); - } + /// + /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The message to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + /// + /// cannot be null. + /// + public async Task PublishAsync(IMessage message, Action setup = null) + { + Validator.ThrowIfNull(message); + Validator.ThrowIfInvalidConfigurator(setup, out var options); - /// - /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The function delegate that will handle received messages. - /// The which may be configured. - /// A that represents the asynchronous operation. - /// - /// cannot be null. - /// - public async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) - { - Validator.ThrowIfNull(asyncHandler); - Validator.ThrowIfInvalidConfigurator(setup, out var options); + var ce = message.ToCloudEvent(); - await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => InvokeHandlerAsync(asyncHandler, options.CancellationToken), async () => - { - try - { - await InvokeHandlerAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) - { - // ThrowIfCancellationWasRequested was set to false (default) - } - }).ConfigureAwait(false); - } + if (message is ISignedMessage signedMessage) { ce.Add(nameof(ISignedMessage.Signature), signedMessage.Signature); } + + ce.Add(CloudEventTypeExtensionAttribute, message.GetType().ToFullNameIncludingAssemblyName()); - private async Task InvokeHandlerAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken cancellationToken) + var json = _marshaller.Serialize(ce).ToEncodedString(); + await _client.SendEventAsync(Azure.Messaging.CloudEvent.Parse(new BinaryData(json)), options.CancellationToken).ConfigureAwait(false); + } + + /// + /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The function delegate that will handle received messages. + /// The which may be configured. + /// A that represents the asynchronous operation. + /// + /// cannot be null. + /// + public async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + { + Validator.ThrowIfNull(asyncHandler); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + + await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => InvokeHandlerAsync(asyncHandler, options.CancellationToken), async () => { - var hasMessages = true; - while (hasMessages) + try { - hasMessages = false; - await foreach (var message in ReceiveMessagesAsync(o => o.CancellationToken = cancellationToken).ConfigureAwait(false)) - { - hasMessages = true; - await asyncHandler.Invoke(message, cancellationToken).ConfigureAwait(false); - } + await InvokeHandlerAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); } - } - - /// - /// Gets the representing the health check endpoint for the configured Azure Event Grid topic. - /// - /// A instance pointing to the health check endpoint of the Azure Event Grid topic. - public Uri GetHealthCheckTarget() - { - return new Uri(_options.TopicEndpoint, "/api/health"); - } + catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) + { + // ThrowIfCancellationWasRequested was set to false (default) + } + }).ConfigureAwait(false); + } - private static IMessage FormatCloudEventQueueMessage(Azure.Storage.Queues.Models.QueueMessage rawMessage, IMarshaller serializer) + private async Task InvokeHandlerAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken cancellationToken) + { + var hasMessages = true; + while (hasMessages) { - var json = rawMessage.MessageText; - var jsonStream = json.FromBase64().ToStream(); - var type = JsonNode.Parse(jsonStream.ToEncodedString(o => o.LeaveOpen = true))!.Root[CloudEventTypeExtensionAttribute]!.GetValue(); - return serializer.Deserialize(jsonStream, Type.GetType(type)!) as IMessage; + hasMessages = false; + await foreach (var message in ReceiveMessagesAsync(o => o.CancellationToken = cancellationToken).ConfigureAwait(false)) + { + hasMessages = true; + await asyncHandler.Invoke(message, cancellationToken).ConfigureAwait(false); + } } } + + /// + /// Gets the representing the health check endpoint for the configured Azure Event Grid topic. + /// + /// A instance pointing to the health check endpoint of the Azure Event Grid topic. + public Uri GetHealthCheckTarget() + { + return new Uri(_options.TopicEndpoint, "/api/health"); + } + + private static IMessage FormatCloudEventQueueMessage(Azure.Storage.Queues.Models.QueueMessage rawMessage, IMarshaller serializer) + { + var json = rawMessage.MessageText; + var jsonStream = json.FromBase64().ToStream(); + var type = JsonNode.Parse(jsonStream.ToEncodedString(o => o.LeaveOpen = true))!.Root[CloudEventTypeExtensionAttribute]!.GetValue(); + return serializer.Deserialize(jsonStream, Type.GetType(type)!) as IMessage; + } } diff --git a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs index 6e891c9b..90f76323 100644 --- a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs @@ -6,120 +6,119 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +/// +/// Configuration options for . +/// +public class AzureEventBusOptions : IValidatableParameterObject { - /// - /// Configuration options for . - /// - public class AzureEventBusOptions : IValidatableParameterObject - { - private TokenCredential _credential; - private AzureKeyCredential _keyCredential; - private AzureSasCredential _sasCredential; + private TokenCredential _credential; + private AzureKeyCredential _keyCredential; + private AzureSasCredential _sasCredential; - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// new DefaultAzureCredential() - /// - /// - /// - /// new QueueClientOptions() - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - public AzureEventBusOptions() - { - Credential = new DefaultAzureCredential(); - Settings = new EventGridPublisherClientOptions(); - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// new DefaultAzureCredential() + /// + /// + /// + /// new QueueClientOptions() + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + public AzureEventBusOptions() + { + Credential = new DefaultAzureCredential(); + Settings = new EventGridPublisherClientOptions(); + } - /// - /// Gets or sets the topic endpoint URI. - /// - /// The topic endpoint URI. - public Uri TopicEndpoint { get; set; } + /// + /// Gets or sets the topic endpoint URI. + /// + /// The topic endpoint URI. + public Uri TopicEndpoint { get; set; } - /// - /// Gets or sets the token credential for Azure authentication. - /// - /// The token credential. - /// Setting this property will nullify and as they are mutually exclusive. - public TokenCredential Credential + /// + /// Gets or sets the token credential for Azure authentication. + /// + /// The token credential. + /// Setting this property will nullify and as they are mutually exclusive. + public TokenCredential Credential + { + get => _credential; + set { - get => _credential; - set - { - _credential = value; - _sasCredential = null; - _keyCredential = null; - } + _credential = value; + _sasCredential = null; + _keyCredential = null; } + } - /// - /// Gets or sets the key credential for Azure authentication. - /// - /// The key credential. - /// Setting this property will nullify and as they are mutually exclusive. - public AzureKeyCredential KeyCredential + /// + /// Gets or sets the key credential for Azure authentication. + /// + /// The key credential. + /// Setting this property will nullify and as they are mutually exclusive. + public AzureKeyCredential KeyCredential + { + get => _keyCredential; + set { - get => _keyCredential; - set - { - _keyCredential = value; - _credential = null; - _sasCredential = null; - } + _keyCredential = value; + _credential = null; + _sasCredential = null; } + } - /// - /// Gets or sets the SAS credential for Azure authentication. - /// - /// The SAS credential. - /// Setting this property will nullify and as they are mutually exclusive. - public AzureSasCredential SasCredential + /// + /// Gets or sets the SAS credential for Azure authentication. + /// + /// The SAS credential. + /// Setting this property will nullify and as they are mutually exclusive. + public AzureSasCredential SasCredential + { + get => _sasCredential; + set { - get => _sasCredential; - set - { - _sasCredential = value; - _credential = null; - _keyCredential = null; - } + _sasCredential = value; + _credential = null; + _keyCredential = null; } + } - /// - /// Gets the settings for the Event Grid publisher client. - /// - /// The Event Grid publisher client options. - public EventGridPublisherClientOptions Settings { get; } + /// + /// Gets the settings for the Event Grid publisher client. + /// + /// The Event Grid publisher client options. + public EventGridPublisherClientOptions Settings { get; } - /// - /// Validates the options to ensure they are in a valid state. - /// - /// Thrown when the options are in an invalid state. - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(TopicEndpoint == null, $"A {nameof(TopicEndpoint)} is required."); + /// + /// Validates the options to ensure they are in a valid state. + /// + /// Thrown when the options are in an invalid state. + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(TopicEndpoint == null, $"A {nameof(TopicEndpoint)} is required."); - Validator.ThrowIfInvalidState(Credential == null && SasCredential == null && KeyCredential == null, "A credential type has to be specified for Azure authentication."); - } + Validator.ThrowIfInvalidState(Credential == null && SasCredential == null && KeyCredential == null, "A credential type has to be specified for Azure authentication."); } } diff --git a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs index 806351ea..cec0e203 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs @@ -13,112 +13,111 @@ using System.Threading.Channels; using System.Threading.Tasks; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +/// +/// Provides a default implementation of the class for messages holding an implementation. +/// +/// +/// +public class RabbitMqCommandQueue : RabbitMqMessage, IPointToPointChannel { + private readonly RabbitMqCommandQueueOptions _options; + /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class RabbitMqCommandQueue : RabbitMqMessage, IPointToPointChannel + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the RabbitMQ command queue. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public RabbitMqCommandQueue(IMarshaller marshaller, RabbitMqCommandQueueOptions options) : base(marshaller, options) { - private readonly RabbitMqCommandQueueOptions _options; - - /// - /// Initializes a new instance of the class. - /// - /// The marshaller used for serializing and deserializing messages. - /// The options used to configure the RabbitMQ command queue. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public RabbitMqCommandQueue(IMarshaller marshaller, RabbitMqCommandQueueOptions options) : base(marshaller, options) - { - Validator.ThrowIfInvalidOptions(options); - _options = options; - } + Validator.ThrowIfInvalidOptions(options); + _options = options; + } - /// - /// Sends the specified command messages asynchronously to the configured RabbitMQ queue. - /// - /// The messages to send. - /// The which may be configured. - /// A that represents the asynchronous operation. - public async Task SendAsync(IEnumerable> messages, Action setup = null) - { - Validator.ThrowIfInvalidConfigurator(setup, out var options); + /// + /// Sends the specified command messages asynchronously to the configured RabbitMQ queue. + /// + /// The messages to send. + /// The which may be configured. + /// A that represents the asynchronous operation. + public async Task SendAsync(IEnumerable> messages, Action setup = null) + { + Validator.ThrowIfInvalidConfigurator(setup, out var options); - await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); + await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); - await RabbitMqChannel.QueueDeclareAsync(_options.QueueName, _options.Durable, _options.Exclusive, _options.AutoDelete, cancellationToken: options.CancellationToken).ConfigureAwait(false); + await RabbitMqChannel.QueueDeclareAsync(_options.QueueName, _options.Durable, _options.Exclusive, _options.AutoDelete, cancellationToken: options.CancellationToken).ConfigureAwait(false); - foreach (var message in messages) + foreach (var message in messages) + { + await RabbitMqChannel.BasicPublishAsync("", _options.QueueName, true, basicProperties: new BasicProperties() { - await RabbitMqChannel.BasicPublishAsync("", _options.QueueName, true, basicProperties: new BasicProperties() + Persistent = _options.Persistent, + Headers = new Dictionary() { - Persistent = _options.Persistent, - Headers = new Dictionary() - { - { MessageType, message.GetType().ToFullNameIncludingAssemblyName() } - } - }, body: await Marshaller.Serialize(message).ToByteArrayAsync(o => o.CancellationToken = options.CancellationToken).ConfigureAwait(false), options.CancellationToken).ConfigureAwait(false); - } + { MessageType, message.GetType().ToFullNameIncludingAssemblyName() } + } + }, body: await Marshaller.Serialize(message).ToByteArrayAsync(o => o.CancellationToken = options.CancellationToken).ConfigureAwait(false), options.CancellationToken).ConfigureAwait(false); } + } - /// - /// Receives command messages asynchronously from the configured RabbitMQ queue. - /// - /// 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); + /// + /// Receives command messages asynchronously from the configured RabbitMQ queue. + /// + /// 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); - await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); + await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); - await RabbitMqChannel.QueueDeclareAsync(_options.QueueName, _options.Durable, _options.Exclusive, _options.AutoDelete, cancellationToken: options.CancellationToken).ConfigureAwait(false); + await RabbitMqChannel.QueueDeclareAsync(_options.QueueName, _options.Durable, _options.Exclusive, _options.AutoDelete, cancellationToken: options.CancellationToken).ConfigureAwait(false); - var buffer = Channel.CreateUnbounded>(); - var consumer = new AsyncEventingBasicConsumer(RabbitMqChannel); - consumer.ReceivedAsync += async (_, e) => - { - var messageType = Type.GetType((e.BasicProperties.Headers[MessageType] as byte[]).ToEncodedString()); - var deserialized = Marshaller.Deserialize(e.Body.ToArray().ToStream(), messageType) as IMessage; - deserialized!.Properties.Add(nameof(BasicDeliverEventArgs.DeliveryTag), e.DeliveryTag); - deserialized.Properties.Add(nameof(CancellationToken), options.CancellationToken); - deserialized.Properties.Add(nameof(QueueDeclareOk.QueueName), _options.QueueName); - await buffer.Writer.WriteAsync(deserialized, options.CancellationToken).ConfigureAwait(false); - }; + var buffer = Channel.CreateUnbounded>(); + var consumer = new AsyncEventingBasicConsumer(RabbitMqChannel); + consumer.ReceivedAsync += async (_, e) => + { + var messageType = Type.GetType((e.BasicProperties.Headers[MessageType] as byte[]).ToEncodedString()); + var deserialized = Marshaller.Deserialize(e.Body.ToArray().ToStream(), messageType) as IMessage; + deserialized!.Properties.Add(nameof(BasicDeliverEventArgs.DeliveryTag), e.DeliveryTag); + deserialized.Properties.Add(nameof(CancellationToken), options.CancellationToken); + deserialized.Properties.Add(nameof(QueueDeclareOk.QueueName), _options.QueueName); + await buffer.Writer.WriteAsync(deserialized, options.CancellationToken).ConfigureAwait(false); + }; - await RabbitMqChannel.BasicConsumeAsync(_options.QueueName, autoAck: false, consumer: consumer, cancellationToken: options.CancellationToken).ConfigureAwait(false); + await RabbitMqChannel.BasicConsumeAsync(_options.QueueName, autoAck: false, consumer: consumer, cancellationToken: options.CancellationToken).ConfigureAwait(false); - while (await buffer.Reader.WaitToReadAsync(options.CancellationToken).ConfigureAwait(false)) + while (await buffer.Reader.WaitToReadAsync(options.CancellationToken).ConfigureAwait(false)) + { + while (buffer.Reader.TryRead(out var message)) { - while (buffer.Reader.TryRead(out var message)) + message.Acknowledged += OnMessageAcknowledgedAsync; + if (_options.AutoAcknowledge) { - message.Acknowledged += OnMessageAcknowledgedAsync; - if (_options.AutoAcknowledge) - { - await message.AcknowledgeAsync().ConfigureAwait(false); - } - yield return message; + await message.AcknowledgeAsync().ConfigureAwait(false); } + yield return message; } } + } - private async Task OnMessageAcknowledgedAsync(object sender, AcknowledgedEventArgs e) - { - var ct = (CancellationToken)e.Properties[nameof(CancellationToken)]; - 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; } - } + private async Task OnMessageAcknowledgedAsync(object sender, AcknowledgedEventArgs e) + { + var ct = (CancellationToken)e.Properties[nameof(CancellationToken)]; + 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 f9386fd6..f1ba1ecd 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs @@ -1,105 +1,104 @@ using System; using Cuemon; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +/// +/// Configuration options for . +/// +/// +public class RabbitMqCommandQueueOptions : RabbitMqMessageOptions { /// - /// Configuration options for . + /// Initializes a new instance of the class with default values. /// - /// - public class RabbitMqCommandQueueOptions : RabbitMqMessageOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// null + /// + /// + /// + /// false + /// + /// + /// + /// true + /// + /// + /// + /// false + /// + /// + /// + /// false + /// + /// + /// + public RabbitMqCommandQueueOptions() { - /// - /// 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 - /// - /// - /// - /// null - /// - /// - /// - /// false - /// - /// - /// - /// true - /// - /// - /// - /// false - /// - /// - /// - /// false - /// - /// - /// - public RabbitMqCommandQueueOptions() - { - Durable = true; - } + Durable = true; + } - /// - /// Gets or sets the name of the queue. - /// - /// - /// The name of the RabbitMQ queue to be used for command messages. - /// - public string QueueName { get; set; } + /// + /// Gets or sets the name of the queue. + /// + /// + /// The name of the RabbitMQ queue to be used for command messages. + /// + public string QueueName { get; set; } - /// - /// Gets or sets a value indicating whether messages should be automatically acknowledged. - /// - /// - /// true if messages are automatically acknowledged; otherwise, false. - /// - public bool AutoAcknowledge { get; set; } + /// + /// Gets or sets a value indicating whether messages should be automatically acknowledged. + /// + /// + /// true if messages are automatically acknowledged; otherwise, false. + /// + public bool AutoAcknowledge { get; set; } - /// - /// Gets or sets a value indicating whether the queue should be durable. - /// - /// true if the queue should survive broker restarts; otherwise, false. - /// - /// Durable queues remain declared after a RabbitMQ broker restart, but messages in non-persistent queues will be lost. - /// - public bool Durable { get; set; } + /// + /// Gets or sets a value indicating whether the queue should be durable. + /// + /// true if the queue should survive broker restarts; otherwise, false. + /// + /// Durable queues remain declared after a RabbitMQ broker restart, but messages in non-persistent queues will be lost. + /// + public bool Durable { get; set; } - /// - /// Gets or sets a value indicating whether the queue should be exclusive. - /// - /// true if the queue is used by only one connection and deleted when that connection closes; otherwise, false. - /// - /// Exclusive queues are only accessible by the connection that declares them and are deleted when that connection closes. - /// - public bool Exclusive { get; set; } + /// + /// Gets or sets a value indicating whether the queue should be exclusive. + /// + /// true if the queue is used by only one connection and deleted when that connection closes; otherwise, false. + /// + /// Exclusive queues are only accessible by the connection that declares them and are deleted when that connection closes. + /// + public bool Exclusive { get; set; } - /// - /// Gets or sets a value indicating whether the queue should be automatically deleted when no longer in use. - /// - /// true if the queue is automatically deleted when the last consumer unsubscribes; otherwise, false. - /// - /// Auto-delete queues are deleted when the last consumer unsubscribes. If there are no consumers, the queue is not deleted. - /// - public bool AutoDelete { get; set; } + /// + /// Gets or sets a value indicating whether the queue should be automatically deleted when no longer in use. + /// + /// true if the queue is automatically deleted when the last consumer unsubscribes; otherwise, false. + /// + /// Auto-delete queues are deleted when the last consumer unsubscribes. If there are no consumers, the queue is not deleted. + /// + public bool AutoDelete { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null or empty. - /// - public override void ValidateOptions() - { - Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(QueueName)); - base.ValidateOptions(); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null or empty. + /// + public override void ValidateOptions() + { + Validator.ThrowIfInvalidState(string.IsNullOrWhiteSpace(QueueName)); + base.ValidateOptions(); } } diff --git a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs index f8d374a1..712eb692 100644 --- a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs +++ b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs @@ -13,97 +13,96 @@ using System.Threading.Channels; using System.Threading.Tasks; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +/// +/// Provides a default implementation of the class for messages holding an implementation. +/// +/// +/// +public class RabbitMqEventBus : RabbitMqMessage, IPublishSubscribeChannel { + private readonly RabbitMqEventBusOptions _options; + /// - /// Provides a default implementation of the class for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - /// - public class RabbitMqEventBus : RabbitMqMessage, IPublishSubscribeChannel + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the RabbitMQ event bus. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public RabbitMqEventBus(IMarshaller marshaller, RabbitMqEventBusOptions options) : base(marshaller, options) { - private readonly RabbitMqEventBusOptions _options; - - /// - /// Initializes a new instance of the class. - /// - /// The marshaller used for serializing and deserializing messages. - /// The options used to configure the RabbitMQ event bus. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public RabbitMqEventBus(IMarshaller marshaller, RabbitMqEventBusOptions options) : base(marshaller, options) - { - Validator.ThrowIfInvalidOptions(options); - _options = options; - } - - /// - /// Publishes the specified integration event message asynchronously to the configured RabbitMQ exchange. - /// - /// 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); + Validator.ThrowIfInvalidOptions(options); + _options = options; + } - await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); + /// + /// Publishes the specified integration event message asynchronously to the configured RabbitMQ exchange. + /// + /// 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 RabbitMqChannel.ExchangeDeclareAsync(_options.ExchangeName, ExchangeType.Fanout, cancellationToken: options.CancellationToken).ConfigureAwait(false); + await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); - await RabbitMqChannel.BasicPublishAsync(_options.ExchangeName, "", false, basicProperties: new BasicProperties() - { - Persistent = _options.Persistent, - Headers = new Dictionary() - { - { MessageType, message.GetType().ToFullNameIncludingAssemblyName() } - } - }, body: await Marshaller.Serialize(message).ToByteArrayAsync(o => o.CancellationToken = options.CancellationToken).ConfigureAwait(false), options.CancellationToken).ConfigureAwait(false); - } + await RabbitMqChannel.ExchangeDeclareAsync(_options.ExchangeName, ExchangeType.Fanout, cancellationToken: options.CancellationToken).ConfigureAwait(false); - /// - /// Subscribes to integration event messages from the configured RabbitMQ exchange 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) + await RabbitMqChannel.BasicPublishAsync(_options.ExchangeName, "", false, basicProperties: new BasicProperties() { - Validator.ThrowIfInvalidConfigurator(setup, out var options); + Persistent = _options.Persistent, + Headers = new Dictionary() + { + { MessageType, message.GetType().ToFullNameIncludingAssemblyName() } + } + }, body: await Marshaller.Serialize(message).ToByteArrayAsync(o => o.CancellationToken = options.CancellationToken).ConfigureAwait(false), options.CancellationToken).ConfigureAwait(false); + } + + /// + /// Subscribes to integration event messages from the configured RabbitMQ exchange 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 EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); + await EnsureConnectivityAsync(options.CancellationToken).ConfigureAwait(false); - await RabbitMqChannel.ExchangeDeclareAsync(_options.ExchangeName, ExchangeType.Fanout, cancellationToken: options.CancellationToken).ConfigureAwait(false); + await RabbitMqChannel.ExchangeDeclareAsync(_options.ExchangeName, ExchangeType.Fanout, cancellationToken: options.CancellationToken).ConfigureAwait(false); - var queue = await RabbitMqChannel.QueueDeclareAsync(cancellationToken: options.CancellationToken).ConfigureAwait(false); + var queue = await RabbitMqChannel.QueueDeclareAsync(cancellationToken: options.CancellationToken).ConfigureAwait(false); - await RabbitMqChannel.QueueBindAsync(queue.QueueName, _options.ExchangeName, "", cancellationToken: options.CancellationToken).ConfigureAwait(false); + await RabbitMqChannel.QueueBindAsync(queue.QueueName, _options.ExchangeName, "", cancellationToken: options.CancellationToken).ConfigureAwait(false); - var buffer = Channel.CreateUnbounded>(); - var consumer = new AsyncEventingBasicConsumer(RabbitMqChannel); - consumer.ReceivedAsync += async (_, e) => - { - var messageType = Type.GetType((e.BasicProperties.Headers[MessageType] as byte[]).ToEncodedString()); - var deserialized = Marshaller.Deserialize(e.Body.ToArray().ToStream(), messageType) as IMessage; - deserialized!.Properties.Add(nameof(BasicDeliverEventArgs.DeliveryTag), e.DeliveryTag); - deserialized.Properties.Add(nameof(CancellationToken), options.CancellationToken); - deserialized.Properties.Add(nameof(QueueDeclareOk.QueueName), queue.QueueName); - await buffer.Writer.WriteAsync(deserialized, options.CancellationToken).ConfigureAwait(false); - }; - - await RabbitMqChannel.BasicConsumeAsync(queue.QueueName, autoAck: true, consumer: consumer, options.CancellationToken).ConfigureAwait(false); + var buffer = Channel.CreateUnbounded>(); + var consumer = new AsyncEventingBasicConsumer(RabbitMqChannel); + consumer.ReceivedAsync += async (_, e) => + { + var messageType = Type.GetType((e.BasicProperties.Headers[MessageType] as byte[]).ToEncodedString()); + var deserialized = Marshaller.Deserialize(e.Body.ToArray().ToStream(), messageType) as IMessage; + deserialized!.Properties.Add(nameof(BasicDeliverEventArgs.DeliveryTag), e.DeliveryTag); + deserialized.Properties.Add(nameof(CancellationToken), options.CancellationToken); + deserialized.Properties.Add(nameof(QueueDeclareOk.QueueName), queue.QueueName); + await buffer.Writer.WriteAsync(deserialized, options.CancellationToken).ConfigureAwait(false); + }; + + await RabbitMqChannel.BasicConsumeAsync(queue.QueueName, autoAck: true, consumer: consumer, options.CancellationToken).ConfigureAwait(false); - while (await buffer.Reader.WaitToReadAsync(options.CancellationToken).ConfigureAwait(false)) + while (await buffer.Reader.WaitToReadAsync(options.CancellationToken).ConfigureAwait(false)) + { + while (buffer.Reader.TryRead(out var message)) { - while (buffer.Reader.TryRead(out var message)) - { - await asyncHandler(message, options.CancellationToken).ConfigureAwait(false); - } + await asyncHandler(message, options.CancellationToken).ConfigureAwait(false); } } } diff --git a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs index bc0bef17..a42cf8ef 100644 --- a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs @@ -1,51 +1,50 @@ using System; using Cuemon; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +/// +/// Configuration options for . +/// +/// +public class RabbitMqEventBusOptions : RabbitMqMessageOptions { /// - /// Configuration options for . + /// Initializes a new instance of the class. /// - /// - public class RabbitMqEventBusOptions : RabbitMqMessageOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// null + /// + /// + /// + public RabbitMqEventBusOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// null - /// - /// - /// - public RabbitMqEventBusOptions() - { - } + } - /// - /// Gets or sets the name of the exchange. - /// - /// The name of the exchange. - public string ExchangeName { get; set; } + /// + /// Gets or sets the name of the exchange. + /// + /// The name of the exchange. + public string ExchangeName { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null or empty. - /// - public override void ValidateOptions() - { - Validator.ThrowIfInvalidState(string.IsNullOrEmpty(ExchangeName)); - base.ValidateOptions(); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null or empty. + /// + public override void ValidateOptions() + { + Validator.ThrowIfInvalidState(string.IsNullOrEmpty(ExchangeName)); + base.ValidateOptions(); } } diff --git a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs index 08969e46..01fea777 100644 --- a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs +++ b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs @@ -6,118 +6,117 @@ using System.Threading.Tasks; using Savvyio.Diagnostics; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +/// +/// Provides a base class for RabbitMQ message operations, including connection and channel management, marshalling, and resource disposal. Ensures thread-safe initialization of RabbitMQ connectivity. +/// +public abstract class RabbitMqMessage : AsyncDisposable, IAsyncHealthCheckProvider { /// - /// Provides a base class for RabbitMQ message operations, including connection and channel management, marshalling, and resource disposal. Ensures thread-safe initialization of RabbitMQ connectivity. + /// The header key used to indicate the message type in RabbitMQ properties. /// - public abstract class RabbitMqMessage : AsyncDisposable, IAsyncHealthCheckProvider - { - /// - /// The header key used to indicate the message type in RabbitMQ properties. - /// - protected const string MessageType = "type"; + protected const string MessageType = "type"; - private readonly SemaphoreSlim _asyncLock = new(1, 1); - private bool _initialized; + private readonly SemaphoreSlim _asyncLock = new(1, 1); + private bool _initialized; - /// - /// Initializes a new instance of the class with the specified marshaller and options. - /// - /// The marshaller used for serializing and deserializing messages. - /// The options used to configure the RabbitMQ connection. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - protected RabbitMqMessage(IMarshaller marshaller, RabbitMqMessageOptions options) + /// + /// Initializes a new instance of the class with the specified marshaller and options. + /// + /// The marshaller used for serializing and deserializing messages. + /// The options used to configure the RabbitMQ connection. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected RabbitMqMessage(IMarshaller marshaller, RabbitMqMessageOptions options) + { + Validator.ThrowIfInvalidOptions(options); + Validator.ThrowIfNull(marshaller); + Marshaller = marshaller; + RabbitMqFactory = new ConnectionFactory { - Validator.ThrowIfInvalidOptions(options); - Validator.ThrowIfNull(marshaller); - Marshaller = marshaller; - RabbitMqFactory = new ConnectionFactory - { - Uri = options.AmqpUrl - }; - } + Uri = options.AmqpUrl + }; + } - /// - /// Gets the RabbitMQ connection factory used to create connections to the broker. - /// - protected IConnectionFactory RabbitMqFactory { get; private set; } + /// + /// Gets the RabbitMQ connection factory used to create connections to the broker. + /// + protected IConnectionFactory RabbitMqFactory { get; private set; } - /// - /// Ensures that a connection and channel to the RabbitMQ broker are established and initialized. - /// This method is thread-safe and will only initialize the connection and channel once. - /// - /// - /// A that can be used to cancel the asynchronous operation. - /// - /// - /// A representing the asynchronous operation. - /// - /// - /// If the connection and channel are already initialized, this method returns immediately. - /// Otherwise, it acquires an asynchronous lock to ensure only one initialization occurs, - /// then creates the RabbitMQ connection and channel. - /// - protected async Task EnsureConnectivityAsync(CancellationToken ct) + /// + /// Ensures that a connection and channel to the RabbitMQ broker are established and initialized. + /// This method is thread-safe and will only initialize the connection and channel once. + /// + /// + /// A that can be used to cancel the asynchronous operation. + /// + /// + /// A representing the asynchronous operation. + /// + /// + /// If the connection and channel are already initialized, this method returns immediately. + /// Otherwise, it acquires an asynchronous lock to ensure only one initialization occurs, + /// then creates the RabbitMQ connection and channel. + /// + protected async Task EnsureConnectivityAsync(CancellationToken ct) + { + if (_initialized) { return; } + await _asyncLock.WaitAsync(ct).ConfigureAwait(false); + try { - if (_initialized) { return; } - await _asyncLock.WaitAsync(ct).ConfigureAwait(false); - try + if (!_initialized) { - if (!_initialized) - { - RabbitMqConnection = await RabbitMqFactory.CreateConnectionAsync(ct).ConfigureAwait(false); - RabbitMqChannel = await RabbitMqConnection.CreateChannelAsync(cancellationToken: ct).ConfigureAwait(false); - _initialized = true; - } - } - finally - { - _asyncLock.Release(); + RabbitMqConnection = await RabbitMqFactory.CreateConnectionAsync(ct).ConfigureAwait(false); + RabbitMqChannel = await RabbitMqConnection.CreateChannelAsync(cancellationToken: ct).ConfigureAwait(false); + _initialized = true; } } + finally + { + _asyncLock.Release(); + } + } - /// - /// Gets the current RabbitMQ connection instance. - /// - protected IConnection RabbitMqConnection { get; private set; } + /// + /// Gets the current RabbitMQ connection instance. + /// + protected IConnection RabbitMqConnection { get; private set; } - /// - /// Gets the current RabbitMQ channel instance. - /// - protected IChannel RabbitMqChannel { get; private set; } + /// + /// Gets the current RabbitMQ channel instance. + /// + protected IChannel RabbitMqChannel { get; private set; } - /// - /// Gets the by constructor provided serializer context. - /// - /// The by constructor provided serializer context. - protected IMarshaller Marshaller { get; } + /// + /// Gets the by constructor provided serializer context. + /// + /// The by constructor provided serializer context. + protected IMarshaller Marshaller { get; } - /// - /// Called when this object is being disposed by . - /// Disposes the RabbitMQ channel and connection asynchronously if they have been initialized. - /// - /// A representing the asynchronous dispose operation. - protected override async ValueTask OnDisposeManagedResourcesAsync() - { - if (RabbitMqChannel != null) { await RabbitMqChannel.DisposeAsync().ConfigureAwait(false); } - if (RabbitMqConnection != null) { await RabbitMqConnection.DisposeAsync().ConfigureAwait(false); } - } + /// + /// Called when this object is being disposed by . + /// Disposes the RabbitMQ channel and connection asynchronously if they have been initialized. + /// + /// A representing the asynchronous dispose operation. + protected override async ValueTask OnDisposeManagedResourcesAsync() + { + if (RabbitMqChannel != null) { await RabbitMqChannel.DisposeAsync().ConfigureAwait(false); } + if (RabbitMqConnection != null) { await RabbitMqConnection.DisposeAsync().ConfigureAwait(false); } + } - /// - /// Asynchronously returns an instance used for probing the health status of the RabbitMQ broker. - /// - /// A that can be used to cancel the asynchronous operation. - /// A task that represents the asynchronous operation. The task result contains the instance representing the active connection to the RabbitMQ broker, or a newly created connection if not already initialized. - public async Task GetHealthCheckTargetAsync(CancellationToken cancellationToken = default) - { - return RabbitMqConnection ?? await RabbitMqFactory.CreateConnectionAsync(cancellationToken).ConfigureAwait(false); - } + /// + /// Asynchronously returns an instance used for probing the health status of the RabbitMQ broker. + /// + /// A that can be used to cancel the asynchronous operation. + /// A task that represents the asynchronous operation. The task result contains the instance representing the active connection to the RabbitMQ broker, or a newly created connection if not already initialized. + public async Task GetHealthCheckTargetAsync(CancellationToken cancellationToken = default) + { + return RabbitMqConnection ?? await RabbitMqFactory.CreateConnectionAsync(cancellationToken).ConfigureAwait(false); } } diff --git a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs index 84f6b761..878c914e 100644 --- a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs @@ -2,67 +2,66 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +/// +/// Configuration options that is related to RabbitMQ. +/// +/// +public class RabbitMqMessageOptions : IValidatableParameterObject { /// - /// Configuration options that is related to RabbitMQ. + /// Initializes a new instance of the class with default values. /// - /// - public class RabbitMqMessageOptions : IValidatableParameterObject + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// new Uri("amqp://localhost:5672") + /// + /// + /// + /// false + /// + /// + /// + public RabbitMqMessageOptions() { - /// - /// 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("amqp://localhost:5672") - /// - /// - /// - /// false - /// - /// - /// - public RabbitMqMessageOptions() - { - AmqpUrl = new Uri("amqp://localhost:5672"); - } + AmqpUrl = new Uri("amqp://localhost:5672"); + } - /// - /// Gets or sets the AMQP URL used to connect to the RabbitMQ broker. - /// - /// - /// The representing the AMQP endpoint for the RabbitMQ broker. - /// - public Uri AmqpUrl { get; set; } + /// + /// Gets or sets the AMQP URL used to connect to the RabbitMQ broker. + /// + /// + /// The representing the AMQP endpoint for the RabbitMQ broker. + /// + public Uri AmqpUrl { get; set; } - /// - /// Gets or sets a value indicating whether messages should be published as persistent. - /// - /// true if messages are marked as persistent and survive broker restarts; otherwise, false. - /// - /// When set to true, messages are stored to disk by RabbitMQ, ensuring delivery even if the broker restarts. - /// This corresponds to setting the delivery mode to persistent (2) in RabbitMQ. - /// - public bool Persistent { get; set; } + /// + /// Gets or sets a value indicating whether messages should be published as persistent. + /// + /// true if messages are marked as persistent and survive broker restarts; otherwise, false. + /// + /// When set to true, messages are stored to disk by RabbitMQ, ensuring delivery even if the broker restarts. + /// This corresponds to setting the delivery mode to persistent (2) in RabbitMQ. + /// + public bool Persistent { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null. - /// - public virtual void ValidateOptions() - { - Validator.ThrowIfInvalidState(AmqpUrl == null); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null. + /// + public virtual void ValidateOptions() + { + Validator.ThrowIfInvalidState(AmqpUrl == null); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs index 8ba9e237..bd2b0f54 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs @@ -4,46 +4,45 @@ using Cuemon.Threading; using Savvyio.Messaging; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Represents the base class from which all implementations in need of bus capabilities should derive. +/// +/// The type of the model to handle. +/// +/// +public abstract class AmazonBus : AmazonMessage, IPublishSubscribeChannel where TRequest : IRequest { /// - /// Represents the base class from which all implementations in need of bus capabilities should derive. + /// Initializes a new instance of the class. /// - /// The type of the model to handle. - /// - /// - public abstract class AmazonBus : AmazonMessage, IPublishSubscribeChannel where TRequest : IRequest + /// The that is used when converting models to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected AmazonBus(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting models to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - protected AmazonBus(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) - { - } + } - /// - /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The message to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - public abstract Task PublishAsync(IMessage message, Action setup = null); + /// + /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The message to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public abstract Task PublishAsync(IMessage message, Action setup = null); - /// - /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The function delegate that will handle the message. - /// The which may be configured. - /// A that represents the asynchronous operation. - public abstract Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null); - } + /// + /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The function delegate that will handle the message. + /// The which may be configured. + /// A that represents the asynchronous operation. + public abstract Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null); } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs index 7067e71f..03a90ce7 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs @@ -11,179 +11,178 @@ using System.Runtime.CompilerServices; using Cuemon.Extensions.IO; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Represents the base class from which all implementations of AWS SQS should derive. +/// +/// The type of the model to handle. +/// +public abstract class AmazonMessage : IConfigurable where TRequest : IRequest { /// - /// Represents the base class from which all implementations of AWS SQS should derive. + /// The key for the message type attribute. + /// + protected const string MessageTypeAttributeKey = "type"; + + /// + /// Initializes a new instance of the class. /// - /// The type of the model to handle. - /// - public abstract class AmazonMessage : IConfigurable where TRequest : IRequest + /// The that is used when converting models to messages. + /// The used to configure this instance. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected AmazonMessage(IMarshaller marshaller, AmazonMessageOptions options) { - /// - /// The key for the message type attribute. - /// - protected const string MessageTypeAttributeKey = "type"; + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidOptions(options); + Marshaller = marshaller; + Options = options; + UseFirstInFirstOut = options.SourceQueue.OriginalString.Contains(".fifo", StringComparison.OrdinalIgnoreCase); + } - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting models to messages. - /// The used to configure this instance. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - protected AmazonMessage(IMarshaller marshaller, AmazonMessageOptions options) - { - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidOptions(options); - Marshaller = marshaller; - Options = options; - UseFirstInFirstOut = options.SourceQueue.OriginalString.Contains(".fifo", StringComparison.OrdinalIgnoreCase); - } + /// + /// Gets a value indicating whether AWS SQS is configured for FIFO. + /// + /// true if AWS SQS is configured for FIFO; otherwise, false. + protected bool UseFirstInFirstOut { get; } - /// - /// Gets a value indicating whether AWS SQS is configured for FIFO. - /// - /// true if AWS SQS is configured for FIFO; otherwise, false. - protected bool UseFirstInFirstOut { get; } + /// + /// Gets the by constructor provided serializer context. + /// + /// The by constructor provided serializer context. + protected IMarshaller Marshaller { get; } - /// - /// Gets the by constructor provided serializer context. - /// - /// The by constructor provided serializer context. - protected IMarshaller Marshaller { get; } + /// + /// Gets the configured of this instance. + /// + /// The configured of this instance. + public AmazonMessageOptions Options { get; } - /// - /// Gets the configured of this instance. - /// - /// The configured of this instance. - public AmazonMessageOptions Options { get; } + /// + /// Receive one or more message(s) asynchronous from AWS SQS. + /// + /// The cancellation token of an asynchronous operations. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + protected virtual async IAsyncEnumerable> RetrieveMessagesAsync([EnumeratorCancellation] CancellationToken cancellationToken) + { + var sqs = CreateSimpleQueueServiceClient(); - /// - /// Receive one or more message(s) asynchronous from AWS SQS. - /// - /// The cancellation token of an asynchronous operations. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - protected virtual async IAsyncEnumerable> RetrieveMessagesAsync([EnumeratorCancellation] CancellationToken cancellationToken) + if (Options.ReceiveContext.UseApproximateNumberOfMessages) { - var sqs = CreateSimpleQueueServiceClient(); - - if (Options.ReceiveContext.UseApproximateNumberOfMessages) - { - var approximateNumberOfMessages = await FetchApproximateNumberOfMessagesAsync(sqs, cancellationToken).ConfigureAwait(false); // cost 1 request - var currentMessagesCount = approximateNumberOfMessages; - if (approximateNumberOfMessages == 0) { yield break; } - while (approximateNumberOfMessages > 0 && currentMessagesCount > 0) - { - var messagesCount = 0; - await foreach (var message in ReceiveMessagesAsync(sqs, cancellationToken).ConfigureAwait(false)) - { - messagesCount++; - yield return message; - } - currentMessagesCount = messagesCount; - approximateNumberOfMessages -= currentMessagesCount; - } - } - else + var approximateNumberOfMessages = await FetchApproximateNumberOfMessagesAsync(sqs, cancellationToken).ConfigureAwait(false); // cost 1 request + var currentMessagesCount = approximateNumberOfMessages; + if (approximateNumberOfMessages == 0) { yield break; } + while (approximateNumberOfMessages > 0 && currentMessagesCount > 0) { + var messagesCount = 0; await foreach (var message in ReceiveMessagesAsync(sqs, cancellationToken).ConfigureAwait(false)) { + messagesCount++; yield return message; } + currentMessagesCount = messagesCount; + approximateNumberOfMessages -= currentMessagesCount; } } - - private async Task FetchApproximateNumberOfMessagesAsync(IAmazonSQS sqs, CancellationToken cancellationToken) + else { - var attributes = await sqs.GetQueueAttributesAsync(new GetQueueAttributesRequest + await foreach (var message in ReceiveMessagesAsync(sqs, cancellationToken).ConfigureAwait(false)) { - QueueUrl = Options.SourceQueue.OriginalString, - AttributeNames = new List() - { - "ApproximateNumberOfMessages" - } - }, cancellationToken).ConfigureAwait(false); - return attributes.ApproximateNumberOfMessages; + yield return message; + } } + } - private async IAsyncEnumerable> ReceiveMessagesAsync(IAmazonSQS sqs, [EnumeratorCancellation] CancellationToken cancellationToken) + private async Task FetchApproximateNumberOfMessagesAsync(IAmazonSQS sqs, CancellationToken cancellationToken) + { + var attributes = await sqs.GetQueueAttributesAsync(new GetQueueAttributesRequest { - var request = new ReceiveMessageRequest + QueueUrl = Options.SourceQueue.OriginalString, + AttributeNames = new List() { - MaxNumberOfMessages = Options.ReceiveContext.NumberOfMessagesToTakePerRequest, - WaitTimeSeconds = (int)Options.ReceiveContext.PollingTimeout.TotalSeconds, - QueueUrl = Options.SourceQueue.OriginalString, - MessageAttributeNames = new List() - { - MessageTypeAttributeKey - }, - VisibilityTimeout = (int)Options.ReceiveContext.VisibilityTimeout.TotalSeconds - }; + "ApproximateNumberOfMessages" + } + }, cancellationToken).ConfigureAwait(false); + return attributes.ApproximateNumberOfMessages; + } - var response = await sqs.ReceiveMessageAsync(request, cancellationToken).ConfigureAwait(false); // cost 1 request with fetching of up to 10 messages - if (response.Messages == null || response.Messages.Count == 0) { yield break; } // v4 requirement as per https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html#net-dg-v4-collections - var deserializedMessages = new List>(); - foreach (var message in response.Messages) + private async IAsyncEnumerable> ReceiveMessagesAsync(IAmazonSQS sqs, [EnumeratorCancellation] CancellationToken cancellationToken) + { + var request = new ReceiveMessageRequest + { + MaxNumberOfMessages = Options.ReceiveContext.NumberOfMessagesToTakePerRequest, + WaitTimeSeconds = (int)Options.ReceiveContext.PollingTimeout.TotalSeconds, + QueueUrl = Options.SourceQueue.OriginalString, + MessageAttributeNames = new List() { - cancellationToken.ThrowIfCancellationRequested(); - var messageType = Type.GetType(message.MessageAttributes[MessageTypeAttributeKey].StringValue); - var deserialized = Marshaller.Deserialize(message.Body.ToStream(), messageType) as IMessage; - deserialized!.Properties.Add(nameof(DeleteMessageBatchRequestEntry.Id), message.MessageId); - deserialized.Properties.Add(nameof(DeleteMessageBatchRequestEntry.ReceiptHandle), message.ReceiptHandle); - deserializedMessages.Add(deserialized); - } + MessageTypeAttributeKey + }, + VisibilityTimeout = (int)Options.ReceiveContext.VisibilityTimeout.TotalSeconds + }; + + var response = await sqs.ReceiveMessageAsync(request, cancellationToken).ConfigureAwait(false); // cost 1 request with fetching of up to 10 messages + if (response.Messages == null || response.Messages.Count == 0) { yield break; } // v4 requirement as per https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html#net-dg-v4-collections + var deserializedMessages = new List>(); + foreach (var message in response.Messages) + { + cancellationToken.ThrowIfCancellationRequested(); + var messageType = Type.GetType(message.MessageAttributes[MessageTypeAttributeKey].StringValue); + var deserialized = Marshaller.Deserialize(message.Body.ToStream(), messageType) as IMessage; + deserialized!.Properties.Add(nameof(DeleteMessageBatchRequestEntry.Id), message.MessageId); + deserialized.Properties.Add(nameof(DeleteMessageBatchRequestEntry.ReceiptHandle), message.ReceiptHandle); + deserializedMessages.Add(deserialized); + } - await foreach (var message in new MessageAsyncEnumerable(deserializedMessages, o => + await foreach (var message in new MessageAsyncEnumerable(deserializedMessages, o => + { + o.MessageCallback = async message => { - o.MessageCallback = async message => + if (Options.ReceiveContext.AssumeMessageProcessed) { - if (Options.ReceiveContext.AssumeMessageProcessed) - { - await message.AcknowledgeAsync().ConfigureAwait(false); - } - }; - o.AcknowledgedPropertiesCallback = async properties => + await message.AcknowledgeAsync().ConfigureAwait(false); + } + }; + o.AcknowledgedPropertiesCallback = async properties => + { + if (Options.ReceiveContext.RemoveProcessedMessages) { - if (Options.ReceiveContext.RemoveProcessedMessages) - { - await RemoveProcessedMessagesAsync(sqs, properties, cancellationToken).ConfigureAwait(false); - } - }; - }).ConfigureAwait(false)) - { - yield return message; - } + await RemoveProcessedMessagesAsync(sqs, properties, cancellationToken).ConfigureAwait(false); + } + }; + }).ConfigureAwait(false)) + { + yield return message; } + } - private async Task RemoveProcessedMessagesAsync(IAmazonSQS sqs, IEnumerable> properties, CancellationToken cancellationToken) + private async Task RemoveProcessedMessagesAsync(IAmazonSQS sqs, IEnumerable> properties, CancellationToken cancellationToken) + { + var batchRequest = new DeleteMessageBatchRequest { - var batchRequest = new DeleteMessageBatchRequest + QueueUrl = Options.SourceQueue.OriginalString, + Entries = new(properties.Select(property => new DeleteMessageBatchRequestEntry { - QueueUrl = Options.SourceQueue.OriginalString, - Entries = new(properties.Select(property => new DeleteMessageBatchRequestEntry - { - Id = (string)property[nameof(DeleteMessageBatchRequestEntry.Id)], - ReceiptHandle = (string)property[nameof(DeleteMessageBatchRequestEntry.ReceiptHandle)] - })) - }; - await sqs.DeleteMessageBatchAsync(batchRequest, cancellationToken).ConfigureAwait(false); // cost 1 request with deletion of up to 10 messages - } + Id = (string)property[nameof(DeleteMessageBatchRequestEntry.Id)], + ReceiptHandle = (string)property[nameof(DeleteMessageBatchRequestEntry.ReceiptHandle)] + })) + }; + await sqs.DeleteMessageBatchAsync(batchRequest, cancellationToken).ConfigureAwait(false); // cost 1 request with deletion of up to 10 messages + } - /// - /// Creates the AWS SQS client used by send and receive operations. - /// - /// An client configured from . - protected virtual IAmazonSQS CreateSimpleQueueServiceClient() - { - return Options.ClientConfigurations.IsValid() - ? new AmazonSQSClient(Options.Credentials, Options.ClientConfigurations.SimpleQueueService()) - : new AmazonSQSClient(Options.Credentials, Options.Endpoint); - } + /// + /// Creates the AWS SQS client used by send and receive operations. + /// + /// An client configured from . + protected virtual IAmazonSQS CreateSimpleQueueServiceClient() + { + return Options.ClientConfigurations.IsValid() + ? new AmazonSQSClient(Options.Credentials, Options.ClientConfigurations.SimpleQueueService()) + : new AmazonSQSClient(Options.Credentials, Options.Endpoint); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs index 48aebafa..61d67818 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs @@ -7,136 +7,135 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Configuration options that is related to AWS SQS and AWS SNS. +/// +/// +public class AmazonMessageOptions : IValidatableParameterObject { /// - /// Configuration options that is related to AWS SQS and AWS SNS. + /// The maximum number of messages that AWS SQS supports when sending or retrieving. /// - /// - public class AmazonMessageOptions : IValidatableParameterObject - { - /// - /// The maximum number of messages that AWS SQS supports when sending or retrieving. - /// - public const int MaxNumberOfMessages = 10; + public const int MaxNumberOfMessages = 10; - /// - /// The maximum amount of seconds that a call waits for a message to arrive in AWS SQS. - /// - public const int MaxPollingWaitTimeInSeconds = 20; + /// + /// The maximum amount of seconds that a call waits for a message to arrive in AWS SQS. + /// + public const int MaxPollingWaitTimeInSeconds = 20; - /// - /// The maximum amount of seconds that a message can be hidden from other consumers in AWS SQS after it has been received. - /// - public const int MaxVisibilityTimeoutInSeconds = 12 * 60 * 60; + /// + /// The maximum amount of seconds that a message can be hidden from other consumers in AWS SQS after it has been received. + /// + public const int MaxVisibilityTimeoutInSeconds = 12 * 60 * 60; - /// - /// The default amount of seconds that a message can be hidden from other consumers in AWS SQS after it has been received. - /// - public const int DefaultVisibilityTimeoutInSeconds = 30; + /// + /// The default amount of seconds that a message can be hidden from other consumers in AWS SQS after it has been received. + /// + public const int DefaultVisibilityTimeoutInSeconds = 30; - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - /// Enumerable.Empty<ClientConfig>().ToArray(); - /// - /// - /// - public AmazonMessageOptions() - { - ReceiveContext = new AmazonMessageReceiveOptions(); - ClientConfigurations = Enumerable.Empty().ToArray(); - } + /// + /// Initializes a new instance of the class. + /// + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + /// Enumerable.Empty<ClientConfig>().ToArray(); + /// + /// + /// + public AmazonMessageOptions() + { + ReceiveContext = new AmazonMessageReceiveOptions(); + ClientConfigurations = Enumerable.Empty().ToArray(); + } - /// - /// Gets or sets the credentials required to connect to AWS SQS/SNS. - /// - /// The credentials required to connect to AWS SQS/SNS. - public AWSCredentials Credentials { get; set; } + /// + /// Gets or sets the credentials required to connect to AWS SQS/SNS. + /// + /// The credentials required to connect to AWS SQS/SNS. + public AWSCredentials Credentials { get; set; } - /// - /// Gets or sets the endpoint required to connect to AWS SQS/SNS. - /// - /// The endpoint required to connect to AWS SQS/SNS. - public RegionEndpoint Endpoint { get; set; } + /// + /// Gets or sets the endpoint required to connect to AWS SQS/SNS. + /// + /// The endpoint required to connect to AWS SQS/SNS. + public RegionEndpoint Endpoint { get; set; } - /// - /// Gets the client configuration for AWS SQS/SNS provided by . - /// - /// The configuration of the AWS SQS/SNS. - /// When this property is set, it will take precedence over the property. Useful for testing with a local SQS/SNS instance such as LocalStack or require full configuration flexibility. - public ClientConfig[] ClientConfigurations { get; private set; } + /// + /// Gets the client configuration for AWS SQS/SNS provided by . + /// + /// The configuration of the AWS SQS/SNS. + /// When this property is set, it will take precedence over the property. Useful for testing with a local SQS/SNS instance such as LocalStack or require full configuration flexibility. + public ClientConfig[] ClientConfigurations { get; private set; } - /// - /// Provides a flexible way to configure client configurations for both AWS SQS/SNS in a single call. - /// - /// The setup. - /// - /// cannot be null. - /// - /// When this method is invoked, it will set the property that take precedence over the property. Useful for testing with a local SQS/SNS instance such as LocalStack or require full configuration flexibility. - public AmazonMessageOptions ConfigureClient(Action setup) - { - Validator.ThrowIfNull(setup); - var sqsConfig = new AmazonSQSConfig(); - var snsConfig = new AmazonSimpleNotificationServiceConfig(); - setup(sqsConfig); - setup(snsConfig); - ClientConfigurations = new ClientConfig[] { sqsConfig, snsConfig }; - return this; - } + /// + /// Provides a flexible way to configure client configurations for both AWS SQS/SNS in a single call. + /// + /// The setup. + /// + /// cannot be null. + /// + /// When this method is invoked, it will set the property that take precedence over the property. Useful for testing with a local SQS/SNS instance such as LocalStack or require full configuration flexibility. + public AmazonMessageOptions ConfigureClient(Action setup) + { + Validator.ThrowIfNull(setup); + var sqsConfig = new AmazonSQSConfig(); + var snsConfig = new AmazonSimpleNotificationServiceConfig(); + setup(sqsConfig); + setup(snsConfig); + ClientConfigurations = new ClientConfig[] { sqsConfig, snsConfig }; + return this; + } - /// - /// Gets or sets the URI that represents an AWS SQS/SNS endpoint. - /// - /// The URI that represents an AWS SQS/SNS endpoint. - public Uri SourceQueue { get; set; } + /// + /// Gets or sets the URI that represents an AWS SQS/SNS endpoint. + /// + /// The URI that represents an AWS SQS/SNS endpoint. + public Uri SourceQueue { get; set; } - /// - /// Gets the options related to receive operations on AWS SQS. - /// - /// The options related to receive operations on AWS SQS. - public AmazonMessageReceiveOptions ReceiveContext { get; } + /// + /// Gets the options related to receive operations on AWS SQS. + /// + /// The options related to receive operations on AWS SQS. + public AmazonMessageReceiveOptions ReceiveContext { get; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null -or- - /// is initialized but does not have a length of 2 or the expected elements of type or . - /// - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(Credentials == null); - Validator.ThrowIfInvalidState(Endpoint == null); - Validator.ThrowIfInvalidState(SourceQueue == null); - Validator.ThrowIfInvalidState(ReceiveContext == null); - Validator.ThrowIfInvalidState(ClientConfigurations.Length > 0 && (ClientConfigurations.Length != 2 || !(ClientConfigurations[0] is AmazonSQSConfig && ClientConfigurations[1] is AmazonSimpleNotificationServiceConfig))); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null -or- + /// is initialized but does not have a length of 2 or the expected elements of type or . + /// + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(Credentials == null); + Validator.ThrowIfInvalidState(Endpoint == null); + Validator.ThrowIfInvalidState(SourceQueue == null); + Validator.ThrowIfInvalidState(ReceiveContext == null); + Validator.ThrowIfInvalidState(ClientConfigurations.Length > 0 && (ClientConfigurations.Length != 2 || !(ClientConfigurations[0] is AmazonSQSConfig && ClientConfigurations[1] is AmazonSimpleNotificationServiceConfig))); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs index f1227214..fa582bfc 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs @@ -1,107 +1,106 @@ using System; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Configuration options that is related to receive operations on AWS SQS. +/// +public class AmazonMessageReceiveOptions { + private TimeSpan _pollingTimeout; + private TimeSpan _visibilityTimeout; + private int _numberOfMessagesToTakePerRequest; + /// - /// Configuration options that is related to receive operations on AWS SQS. + /// Initializes a new instance of the class. /// - public class AmazonMessageReceiveOptions + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// 10 + /// + /// + /// + /// 20 seconds + /// + /// + /// + /// true + /// + /// + /// + /// true + /// + /// + /// + /// false + /// + /// + /// + public AmazonMessageReceiveOptions() { - private TimeSpan _pollingTimeout; - private TimeSpan _visibilityTimeout; - private int _numberOfMessagesToTakePerRequest; - - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// 10 - /// - /// - /// - /// 20 seconds - /// - /// - /// - /// true - /// - /// - /// - /// true - /// - /// - /// - /// false - /// - /// - /// - public AmazonMessageReceiveOptions() - { - NumberOfMessagesToTakePerRequest = AmazonMessageOptions.MaxNumberOfMessages; - PollingTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds); - VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.DefaultVisibilityTimeoutInSeconds); - AssumeMessageProcessed = true; - RemoveProcessedMessages = true; - UseApproximateNumberOfMessages = false; - } + NumberOfMessagesToTakePerRequest = AmazonMessageOptions.MaxNumberOfMessages; + PollingTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds); + VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.DefaultVisibilityTimeoutInSeconds); + AssumeMessageProcessed = true; + RemoveProcessedMessages = true; + UseApproximateNumberOfMessages = false; + } - /// - /// Gets or sets the number of messages to return per request. Default is 10. - /// - /// The number of messages to return per request. - /// Max. allowed value is limited to . - public int NumberOfMessagesToTakePerRequest - { - get => _numberOfMessagesToTakePerRequest; - set => _numberOfMessagesToTakePerRequest = Math.Clamp(value, 1, AmazonMessageOptions.MaxNumberOfMessages); - } + /// + /// Gets or sets the number of messages to return per request. Default is 10. + /// + /// The number of messages to return per request. + /// Max. allowed value is limited to . + public int NumberOfMessagesToTakePerRequest + { + get => _numberOfMessagesToTakePerRequest; + set => _numberOfMessagesToTakePerRequest = Math.Clamp(value, 1, AmazonMessageOptions.MaxNumberOfMessages); + } - /// - /// Gets or sets the polling timeout per request. Default is 20 seconds. - /// - /// The polling timeout per request. - /// Max. allowed value is limited to . - public TimeSpan PollingTimeout - { - get => _pollingTimeout; - set => _pollingTimeout = TimeSpan.FromSeconds(Math.Clamp(value.TotalSeconds, 0, AmazonMessageOptions.MaxPollingWaitTimeInSeconds)); - } + /// + /// Gets or sets the polling timeout per request. Default is 20 seconds. + /// + /// The polling timeout per request. + /// Max. allowed value is limited to . + public TimeSpan PollingTimeout + { + get => _pollingTimeout; + set => _pollingTimeout = TimeSpan.FromSeconds(Math.Clamp(value.TotalSeconds, 0, AmazonMessageOptions.MaxPollingWaitTimeInSeconds)); + } - /// - /// Gets or sets the visibility timeout per request. Default is 30 seconds. - /// - /// The visibility timeout per request. - /// Max. allowed value is limited to . - public TimeSpan VisibilityTimeout - { - get => _visibilityTimeout; - set => _visibilityTimeout = TimeSpan.FromSeconds(Math.Clamp(value.TotalSeconds, 0, AmazonMessageOptions.MaxVisibilityTimeoutInSeconds)); - } + /// + /// Gets or sets the visibility timeout per request. Default is 30 seconds. + /// + /// The visibility timeout per request. + /// Max. allowed value is limited to . + public TimeSpan VisibilityTimeout + { + get => _visibilityTimeout; + set => _visibilityTimeout = TimeSpan.FromSeconds(Math.Clamp(value.TotalSeconds, 0, AmazonMessageOptions.MaxVisibilityTimeoutInSeconds)); + } - /// - /// Gets or sets a value indicating whether each message should be automatically assumed processed. Default is true. - /// - /// true if each message should be assumed automatically processed; otherwise, false. - public bool AssumeMessageProcessed { get; set; } + /// + /// Gets or sets a value indicating whether each message should be automatically assumed processed. Default is true. + /// + /// true if each message should be assumed automatically processed; otherwise, false. + public bool AssumeMessageProcessed { get; set; } - /// - /// Gets or sets a value indicating whether processed messages should be removed after processing. Default is true. - /// - /// true if processed messages should be removed after processing; otherwise, false. - public bool RemoveProcessedMessages { get; set; } + /// + /// Gets or sets a value indicating whether processed messages should be removed after processing. Default is true. + /// + /// true if processed messages should be removed after processing; otherwise, false. + public bool RemoveProcessedMessages { get; set; } - /// - /// Gets or sets a value indicating whether to retrieve the approximate number of messages for the queue in question. Default is false. - /// - /// true to retrieve the approximate number of messages for the queue in question; otherwise, false. - public bool UseApproximateNumberOfMessages { get; set; } - } + /// + /// Gets or sets a value indicating whether to retrieve the approximate number of messages for the queue in question. Default is false. + /// + /// true to retrieve the approximate number of messages for the queue in question; otherwise, false. + public bool UseApproximateNumberOfMessages { get; set; } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs index 8b672370..a21cd791 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs @@ -4,45 +4,44 @@ using Cuemon.Threading; using Savvyio.Messaging; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Represents the base class from which all implementations in need of queue capabilities should derive. +/// +/// The type of the model to handle. +/// +/// +public abstract class AmazonQueue : AmazonMessage, IPointToPointChannel where TRequest : IRequest { /// - /// Represents the base class from which all implementations in need of queue capabilities should derive. + /// Initializes a new instance of the class. /// - /// The type of the model to handle. - /// - /// - public abstract class AmazonQueue : AmazonMessage, IPointToPointChannel where TRequest : IRequest + /// The that is used when converting models to messages. + /// The configured . + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + protected AmazonQueue(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting models to messages. - /// The configured . - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - protected AmazonQueue(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) - { - } + } - /// - /// Sends the specified asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The messages to send. - /// The which may be configured. - /// A task that represents the asynchronous operation. - public abstract Task SendAsync(IEnumerable> messages, Action setup = null); + /// + /// Sends the specified asynchronous using Point-to-Point Channel/P2P MEP. + /// + /// The messages to send. + /// The which may be configured. + /// A task that represents the asynchronous operation. + public abstract Task SendAsync(IEnumerable> messages, Action setup = null); - /// - /// Receive one or more message(s) asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - public abstract IAsyncEnumerable> ReceiveAsync(Action setup = null); - } + /// + /// Receive one or more message(s) asynchronous using Point-to-Point Channel/P2P MEP. + /// + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + public abstract IAsyncEnumerable> ReceiveAsync(Action setup = null); } diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs index 087ce66e..eb946d63 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs @@ -5,75 +5,74 @@ using Cuemon.Configuration; using Cuemon.Extensions; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Configuration options that is related to Amazon Resource Name (ARN). +/// +/// https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html +public class AmazonResourceNameOptions : IValidatableParameterObject { /// - /// Configuration options that is related to Amazon Resource Name (ARN). + /// Gets or sets the default partition in which the resource is located to embed in the ARN. Default is "aws". /// - /// https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html - public class AmazonResourceNameOptions : IValidatableParameterObject - { - /// - /// Gets or sets the default partition in which the resource is located to embed in the ARN. Default is "aws". - /// - /// The default partition in which the resource is located to embed in the ARN. - public static string DefaultPartition { get; set; } = RegionEndpoint.EUWest1.PartitionName; + /// The default partition in which the resource is located to embed in the ARN. + public static string DefaultPartition { get; set; } = RegionEndpoint.EUWest1.PartitionName; - /// - /// Gets or sets the default region code to embed in the ARN. Default is "eu-west-1". - /// - /// The default region code to embed in the ARN. - public static string DefaultRegion { get; set; } = RegionEndpoint.EUWest1.SystemName; + /// + /// Gets or sets the default region code to embed in the ARN. Default is "eu-west-1". + /// + /// The default region code to embed in the ARN. + public static string DefaultRegion { get; set; } = RegionEndpoint.EUWest1.SystemName; - /// - /// Gets or sets the default ID of the AWS account that owns the resource (without the hyphens) to embed in the ARN. Default is "000000000000". - /// - /// The default ID of the AWS account that owns the resource to embed in the ARN. - /// For example, 123456789012. - public static string DefaultAccountId { get; set; } = "000000000000"; + /// + /// Gets or sets the default ID of the AWS account that owns the resource (without the hyphens) to embed in the ARN. Default is "000000000000". + /// + /// The default ID of the AWS account that owns the resource to embed in the ARN. + /// For example, 123456789012. + public static string DefaultAccountId { get; set; } = "000000000000"; - /// - /// Initializes a new instance of the class. - /// - public AmazonResourceNameOptions() - { - Partition = DefaultPartition; - Region = DefaultRegion; - AccountId = DefaultAccountId; - } + /// + /// Initializes a new instance of the class. + /// + public AmazonResourceNameOptions() + { + Partition = DefaultPartition; + Region = DefaultRegion; + AccountId = DefaultAccountId; + } - /// - /// Gets or sets the partition in which the resource is located to embed in the ARN. - /// - /// The partition to embed in the ARN. - public string Partition { get; set; } + /// + /// Gets or sets the partition in which the resource is located to embed in the ARN. + /// + /// The partition to embed in the ARN. + public string Partition { get; set; } - /// - /// Gets or sets the default region code to embed in the ARN. - /// - /// The region code to embed in the ARN. - public string Region { get; set; } + /// + /// Gets or sets the default region code to embed in the ARN. + /// + /// The region code to embed in the ARN. + public string Region { get; set; } - /// - /// Gets or sets the default ID of the AWS account that owns the resource (without the hyphens) to embed in the ARN. - /// - /// The ID of the AWS account that owns the resource to embed in the ARN. - public string AccountId { get; set; } + /// + /// Gets or sets the default ID of the AWS account that owns the resource (without the hyphens) to embed in the ARN. + /// + /// The ID of the AWS account that owns the resource to embed in the ARN. + public string AccountId { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null, empty or consist only of white-space characters - or - - /// cannot be null, empty or consist only of white-space characters - or - - /// cannot be null, have a length different from 12 or not be parseable to a numeric value. - /// - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(Partition.IsNullOrWhiteSpace()); - Validator.ThrowIfInvalidState(Region.IsNullOrWhiteSpace()); - Validator.ThrowIfInvalidState(AccountId.IsNullOrWhiteSpace() || AccountId.Length != 12 || !AccountId.IsNumeric(NumberStyles.Integer, CultureInfo.InvariantCulture)); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null, empty or consist only of white-space characters - or - + /// cannot be null, empty or consist only of white-space characters - or - + /// cannot be null, have a length different from 12 or not be parseable to a numeric value. + /// + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(Partition.IsNullOrWhiteSpace()); + Validator.ThrowIfInvalidState(Region.IsNullOrWhiteSpace()); + Validator.ThrowIfInvalidState(AccountId.IsNullOrWhiteSpace() || AccountId.Length != 12 || !AccountId.IsNumeric(NumberStyles.Integer, CultureInfo.InvariantCulture)); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs b/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs index daee311c..f9292875 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs @@ -3,43 +3,42 @@ using Amazon.SimpleNotificationService; using Amazon.SQS; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +/// +/// Extension methods for the base class. +/// +public static class ClientConfigExtensions { /// - /// Extension methods for the base class. + /// Evaluates whether the specified > is valid, e.g. if it has a length of 2 and each element is of type or . /// - public static class ClientConfigExtensions + /// The array of to extend. + /// true if the specified configurations is valid; otherwise, false. + public static bool IsValid(this ClientConfig[] configurations) { - /// - /// Evaluates whether the specified > is valid, e.g. if it has a length of 2 and each element is of type or . - /// - /// The array of to extend. - /// true if the specified configurations is valid; otherwise, false. - public static bool IsValid(this ClientConfig[] configurations) - { - return configurations != null && - configurations.Length == 2 && - configurations.All(config => config is AmazonSQSConfig || config is AmazonSimpleNotificationServiceConfig); - } + return configurations != null && + configurations.Length == 2 && + configurations.All(config => config is AmazonSQSConfig || config is AmazonSimpleNotificationServiceConfig); + } - /// - /// Resolves an instance of from the specified . - /// - /// The array of to extend. - /// A configured instance of . - public static AmazonSQSConfig SimpleQueueService(this ClientConfig[] configurations) - { - return configurations.SingleOrDefault(config => config.GetType() == typeof(AmazonSQSConfig)) as AmazonSQSConfig; - } + /// + /// Resolves an instance of from the specified . + /// + /// The array of to extend. + /// A configured instance of . + public static AmazonSQSConfig SimpleQueueService(this ClientConfig[] configurations) + { + return configurations.SingleOrDefault(config => config.GetType() == typeof(AmazonSQSConfig)) as AmazonSQSConfig; + } - /// - /// Resolves an instance of from the specified . - /// - /// The array of to extend. - /// A configured instance of . - public static AmazonSimpleNotificationServiceConfig SimpleNotificationService(this ClientConfig[] configurations) - { - return configurations.SingleOrDefault(config => config.GetType() == typeof(AmazonSimpleNotificationServiceConfig)) as AmazonSimpleNotificationServiceConfig; - } + /// + /// Resolves an instance of from the specified . + /// + /// The array of to extend. + /// A configured instance of . + public static AmazonSimpleNotificationServiceConfig SimpleNotificationService(this ClientConfig[] configurations) + { + return configurations.SingleOrDefault(config => config.GetType() == typeof(AmazonSimpleNotificationServiceConfig)) as AmazonSimpleNotificationServiceConfig; } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs index 52d1d7c0..70775d4b 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs @@ -14,93 +14,92 @@ using Savvyio.Diagnostics; using Savvyio.Messaging; -namespace Savvyio.Extensions.SimpleQueueService.Commands +namespace Savvyio.Extensions.SimpleQueueService.Commands; + +/// +/// Provides a default implementation of the class tailored for messages holding an implementation. +/// +/// +public class AmazonCommandQueue : AmazonQueue, IHealthCheckProvider { /// - /// Provides a default implementation of the class tailored for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - public class AmazonCommandQueue : AmazonQueue, IHealthCheckProvider + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options) : base(marshaller, options) - { - } + } - /// - /// Sends the specified whose generic type argument is asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The enclosed messages to send. - /// The which may be configured. - /// A task that represents the asynchronous operation. - /// - /// cannot be null. - /// - public override async Task SendAsync(IEnumerable> messages, Action setup = null) + /// + /// Sends the specified whose generic type argument is asynchronous using Point-to-Point Channel/P2P MEP. + /// + /// The enclosed messages to send. + /// The which may be configured. + /// A task that represents the asynchronous operation. + /// + /// cannot be null. + /// + public override async Task SendAsync(IEnumerable> messages, Action setup = null) + { + Validator.ThrowIfNull(messages); + var options = setup.Configure(); + var batches = messages.ToPartitioner(AmazonMessageOptions.MaxNumberOfMessages); + var tasks = new List(); + while (batches.HasPartitions) { - Validator.ThrowIfNull(messages); - var options = setup.Configure(); - var batches = messages.ToPartitioner(AmazonMessageOptions.MaxNumberOfMessages); - var tasks = new List(); - while (batches.HasPartitions) - { - var sqs = CreateSimpleQueueServiceClient(); + var sqs = CreateSimpleQueueServiceClient(); - var batchRequest = new SendMessageBatchRequest + var batchRequest = new SendMessageBatchRequest + { + QueueUrl = Options.SourceQueue.OriginalString, + Entries = new List(batches.Select(message => new SendMessageBatchRequestEntry { - QueueUrl = Options.SourceQueue.OriginalString, - Entries = new List(batches.Select(message => new SendMessageBatchRequestEntry - { - Id = message.Id, - MessageGroupId = UseFirstInFirstOut ? message.Source : null, - MessageDeduplicationId = UseFirstInFirstOut ? message.Id : null, - MessageBody = Marshaller.Serialize(message).ToEncodedString(), - MessageAttributes = new Dictionary + Id = message.Id, + MessageGroupId = UseFirstInFirstOut ? message.Source : null, + MessageDeduplicationId = UseFirstInFirstOut ? message.Id : null, + MessageBody = Marshaller.Serialize(message).ToEncodedString(), + MessageAttributes = new Dictionary + { { + MessageTypeAttributeKey, new MessageAttributeValue { - MessageTypeAttributeKey, new MessageAttributeValue - { - DataType = "String", - StringValue = message.GetType().ToFullNameIncludingAssemblyName() - } + DataType = "String", + StringValue = message.GetType().ToFullNameIncludingAssemblyName() } } - })) - }; - tasks.Add(sqs.SendMessageBatchAsync(batchRequest, options.CancellationToken)); - } - await Task.WhenAll(tasks).ConfigureAwait(false); + } + })) + }; + tasks.Add(sqs.SendMessageBatchAsync(batchRequest, options.CancellationToken)); } + await Task.WhenAll(tasks).ConfigureAwait(false); + } - /// - /// Receive one or more command(s) asynchronous using Point-to-Point Channel/P2P MEP. - /// - /// The which may be configured. - /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . - public override IAsyncEnumerable> ReceiveAsync(Action setup = null) - { - var options = setup.Configure(); - return RetrieveMessagesAsync(options.CancellationToken); - } + /// + /// Receive one or more command(s) asynchronous using Point-to-Point Channel/P2P MEP. + /// + /// The which may be configured. + /// A task that represents the asynchronous operation. The task result contains a sequence of whose generic type argument is . + public override IAsyncEnumerable> ReceiveAsync(Action setup = null) + { + var options = setup.Configure(); + return RetrieveMessagesAsync(options.CancellationToken); + } - /// - /// Returns a new client instance configured for health probing of the underlying Amazon SQS service. - /// - /// An client instance used to probe the health status of the queue service. - public IAmazonSQS GetHealthCheckTarget() - { - return CreateSimpleQueueServiceClient(); - } + /// + /// Returns a new client instance configured for health probing of the underlying Amazon SQS service. + /// + /// An client instance used to probe the health status of the queue service. + public IAmazonSQS GetHealthCheckTarget() + { + return CreateSimpleQueueServiceClient(); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs index 8382f166..15d4202e 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Extensions.SimpleQueueService.Commands +namespace Savvyio.Extensions.SimpleQueueService.Commands; + +/// +/// Configuration options for . +/// +/// +public class AmazonCommandQueueOptions : AmazonMessageOptions { - /// - /// Configuration options for . - /// - /// - public class AmazonCommandQueueOptions : AmazonMessageOptions - { - } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs index a1bb1263..b69ac958 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs @@ -13,114 +13,113 @@ using Savvyio.EventDriven; using Savvyio.Messaging; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +/// +/// Provides a default implementation of the class tailored for messages holding an implementation. +/// +/// +public class AmazonEventBus : AmazonBus, IHealthCheckProvider { /// - /// Provides a default implementation of the class tailored for messages holding an implementation. + /// Initializes a new instance of the class. /// - /// - public class AmazonEventBus : AmazonBus, IHealthCheckProvider + /// The that is used when converting implementations to messages. + /// The used to configure this instance. + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// are not in a valid state. + /// + public AmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options) : base(marshaller, options) { - /// - /// Initializes a new instance of the class. - /// - /// The that is used when converting implementations to messages. - /// The used to configure this instance. - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public AmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options) : base(marshaller, options) - { - } + } - /// - /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The event to publish. - /// The which may be configured. - /// A that represents the asynchronous operation. - public override async Task PublishAsync(IMessage @event, Action setup = null) + /// + /// Publishes the specified asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The event to publish. + /// The which may be configured. + /// A that represents the asynchronous operation. + public override async Task PublishAsync(IMessage @event, Action setup = null) + { + var options = setup.Configure(); + var sns = CreateSimpleNotificationServiceClient(); + var request = new PublishRequest { - var options = setup.Configure(); - var sns = CreateSimpleNotificationServiceClient(); - var request = new PublishRequest + TopicArn = @event.Source, + Message = await Marshaller.Serialize(@event).ToEncodedStringAsync().ConfigureAwait(false), + MessageGroupId = UseFirstInFirstOut ? @event.Source : null, + MessageDeduplicationId = UseFirstInFirstOut ? @event.Id : null, + MessageAttributes = new Dictionary { - TopicArn = @event.Source, - Message = await Marshaller.Serialize(@event).ToEncodedStringAsync().ConfigureAwait(false), - MessageGroupId = UseFirstInFirstOut ? @event.Source : null, - MessageDeduplicationId = UseFirstInFirstOut ? @event.Id : null, - MessageAttributes = new Dictionary { + MessageTypeAttributeKey, new MessageAttributeValue { - MessageTypeAttributeKey, new MessageAttributeValue - { - DataType = "String", - StringValue = @event.GetType().ToFullNameIncludingAssemblyName() - } + DataType = "String", + StringValue = @event.GetType().ToFullNameIncludingAssemblyName() } } - }; - await sns.PublishAsync(request, options.CancellationToken).ConfigureAwait(false); - } + } + }; + await sns.PublishAsync(request, options.CancellationToken).ConfigureAwait(false); + } - /// - /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. - /// - /// The function delegate that will handle the message. - /// The which may be configured. - /// A that represents the asynchronous operation. - public override async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + /// + /// Subscribe to one or more message(s) asynchronous using Publish-Subscribe Channel/Pub-Sub MEP. + /// + /// The function delegate that will handle the message. + /// The which may be configured. + /// A that represents the asynchronous operation. + public override async Task SubscribeAsync(Func, CancellationToken, Task> asyncHandler, Action setup = null) + { + var options = setup.Configure(); + await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => InvokeHandlerAsync(asyncHandler, options.CancellationToken), async () => { - var options = setup.Configure(); - await Condition.FlipFlopAsync(options.ThrowIfCancellationWasRequested, () => InvokeHandlerAsync(asyncHandler, options.CancellationToken), async () => + try { - try - { - await InvokeHandlerAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) - { - // ThrowIfCancellationWasRequested was set to false (default) - } - }).ConfigureAwait(false); - } + await InvokeHandlerAsync(asyncHandler, options.CancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) when (options.CancellationToken.IsCancellationRequested) + { + // ThrowIfCancellationWasRequested was set to false (default) + } + }).ConfigureAwait(false); + } - private async Task InvokeHandlerAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken cancellationToken) + private async Task InvokeHandlerAsync(Func, CancellationToken, Task> asyncHandler, CancellationToken cancellationToken) + { + var hasMessages = true; + while (hasMessages) { - var hasMessages = true; - while (hasMessages) + hasMessages = false; + await foreach (var message in RetrieveMessagesAsync(cancellationToken).ConfigureAwait(false)) { - hasMessages = false; - await foreach (var message in RetrieveMessagesAsync(cancellationToken).ConfigureAwait(false)) - { - hasMessages = true; - await asyncHandler.Invoke(message, cancellationToken).ConfigureAwait(false); - } + hasMessages = true; + await asyncHandler.Invoke(message, cancellationToken).ConfigureAwait(false); } } + } - /// - /// Returns a new client instance configured for health probing of the underlying Amazon SNS service. - /// - /// An client instance used to probe the health status of the notification service. - public IAmazonSimpleNotificationService GetHealthCheckTarget() - { - return CreateSimpleNotificationServiceClient(); - } + /// + /// Returns a new client instance configured for health probing of the underlying Amazon SNS service. + /// + /// An client instance used to probe the health status of the notification service. + public IAmazonSimpleNotificationService GetHealthCheckTarget() + { + return CreateSimpleNotificationServiceClient(); + } - /// - /// Creates the AWS SNS client used by publish operations. - /// - /// An client configured from . - protected virtual IAmazonSimpleNotificationService CreateSimpleNotificationServiceClient() - { - return Options.ClientConfigurations.IsValid() - ? new AmazonSimpleNotificationServiceClient(Options.Credentials, Options.ClientConfigurations.SimpleNotificationService()) - : new AmazonSimpleNotificationServiceClient(Options.Credentials, Options.Endpoint); - } + /// + /// Creates the AWS SNS client used by publish operations. + /// + /// An client configured from . + protected virtual IAmazonSimpleNotificationService CreateSimpleNotificationServiceClient() + { + return Options.ClientConfigurations.IsValid() + ? new AmazonSimpleNotificationServiceClient(Options.Credentials, Options.ClientConfigurations.SimpleNotificationService()) + : new AmazonSimpleNotificationServiceClient(Options.Credentials, Options.Endpoint); } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs index 3582e78a..52641f87 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +/// +/// Configuration options for . +/// +/// +public class AmazonEventBusOptions : AmazonMessageOptions { - /// - /// Configuration options for . - /// - /// - public class AmazonEventBusOptions : AmazonMessageOptions - { - } } diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs index 512b912e..a0d30b37 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs @@ -2,25 +2,24 @@ using Cuemon; using Cuemon.Extensions; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +/// +/// Extension methods for the class. +/// +public static class StringExtensions { /// - /// Extension methods for the class. + /// Converts the specified to its equivalent AWS ARN representation. /// - public static class StringExtensions + /// The to extend. + /// The which may be configured. + /// A that corresponds to and . + /// + public static Uri ToSnsUri(this string source, Action setup = null) { - /// - /// Converts the specified to its equivalent AWS ARN representation. - /// - /// The to extend. - /// The which may be configured. - /// A that corresponds to and . - /// - public static Uri ToSnsUri(this string source, Action setup = null) - { - Validator.ThrowIfInvalidConfigurator(setup, out var options); - var arn = $"arn:{options.Partition}:sns:{options.Region}:{options.AccountId}:{source}"; - return arn.ToUri(); - } + Validator.ThrowIfInvalidConfigurator(setup, out var options); + var arn = $"arn:{options.Partition}:sns:{options.Region}:{options.AccountId}:{source}"; + return arn.ToUri(); } } diff --git a/src/Savvyio.Extensions.Text.Json/Bootstrapper.cs b/src/Savvyio.Extensions.Text.Json/Bootstrapper.cs index 732a75db..b803def8 100644 --- a/src/Savvyio.Extensions.Text.Json/Bootstrapper.cs +++ b/src/Savvyio.Extensions.Text.Json/Bootstrapper.cs @@ -1,32 +1,31 @@ using Cuemon.Extensions.Text.Json.Formatters; using System.Threading; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +internal static class Bootstrapper { - internal static class Bootstrapper - { - private static readonly Lock PadLock = new(); - private static bool _initialized; + private static readonly Lock PadLock = new(); + private static bool _initialized; - internal static void Initialize() + internal static void Initialize() + { + if (!_initialized) { - if (!_initialized) + lock (PadLock) { - lock (PadLock) + if (!_initialized) { - if (!_initialized) + _initialized = true; + JsonFormatterOptions.DefaultConverters += list => { - _initialized = true; - JsonFormatterOptions.DefaultConverters += list => - { - list.AddRequestConverter(); - list.AddMetadataDictionaryConverter(); - list.AddMessageConverter(); - list.AddSingleValueObjectConverter(); - list.AddDateTimeConverter(); - list.AddDateTimeOffsetConverter(); - }; - } + list.AddRequestConverter(); + list.AddMetadataDictionaryConverter(); + list.AddMessageConverter(); + list.AddSingleValueObjectConverter(); + list.AddDateTimeConverter(); + list.AddDateTimeOffsetConverter(); + }; } } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs index f07082de..06493c49 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs @@ -2,44 +2,43 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts a to or from JSON using ISO8601. +/// +public class DateTimeConverter : JsonConverter { /// - /// Converts a to or from JSON using ISO8601. + /// Determines whether the specified type can be converted. /// - public class DateTimeConverter : JsonConverter + /// The type to compare against. + /// if the type can be converted; otherwise, . + public override bool CanConvert(Type typeToConvert) { - /// - /// Determines whether the specified type can be converted. - /// - /// The type to compare against. - /// if the type can be converted; otherwise, . - public override bool CanConvert(Type typeToConvert) - { - return typeToConvert == typeof(DateTime); - } + return typeToConvert == typeof(DateTime); + } - /// - /// Reads and converts the JSON to . - /// - /// The reader. - /// The type to convert. - /// An object that specifies serialization options to use. - /// The converted value. - public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return reader.GetDateTime(); - } + /// + /// Reads and converts the JSON to . + /// + /// The reader. + /// The type to convert. + /// An object that specifies serialization options to use. + /// The converted value. + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetDateTime(); + } - /// - /// Writes a specified as JSON. - /// - /// The writer to write to. - /// The value to convert to JSON. - /// An object that specifies serialization options to use. - public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString("O")); - } + /// + /// Writes a specified as JSON. + /// + /// The writer to write to. + /// The value to convert to JSON. + /// An object that specifies serialization options to use. + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("O")); } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs index 0cdebda0..19c384b0 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs @@ -2,47 +2,46 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts a to or from JSON using ISO8601. +/// +public class DateTimeOffsetConverter : JsonConverter { + /// - /// Converts a to or from JSON using ISO8601. + /// Determines whether the specified type can be converted. /// - public class DateTimeOffsetConverter : JsonConverter + /// The type to compare against. + /// if the type can be converted; otherwise, . + public override bool CanConvert(Type typeToConvert) { - - /// - /// Determines whether the specified type can be converted. - /// - /// The type to compare against. - /// if the type can be converted; otherwise, . - public override bool CanConvert(Type typeToConvert) - { - return typeToConvert == typeof(DateTime); - } + return typeToConvert == typeof(DateTime); + } - /// - /// Reads and converts the JSON to . - /// - /// The reader. - /// The type to convert. - /// An object that specifies serialization options to use. - /// The converted value. - public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return reader.GetDateTimeOffset(); - } + /// + /// Reads and converts the JSON to . + /// + /// The reader. + /// The type to convert. + /// An object that specifies serialization options to use. + /// The converted value. + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetDateTimeOffset(); + } - /// - /// Writes a specified as JSON. - /// - /// The writer to write to. - /// The value to convert to JSON. - /// An object that specifies serialization options to use. - public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString("O")); - } + /// + /// Writes a specified as JSON. + /// + /// The writer to write to. + /// The value to convert to JSON. + /// An object that specifies serialization options to use. + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("O")); } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs index 06dbfae5..138da9b1 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs @@ -14,179 +14,178 @@ using Savvyio.Messaging.Cryptography; using Savvyio.Reflection; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts an (or derived) to or from JSON. +/// +/// +public class MessageConverter : JsonConverterFactory { + internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && + ti is { IsAbstract: false, IsInterface: false })).ToList()); + /// - /// Converts an (or derived) to or from JSON. + /// Initializes a new instance of the class. /// - /// - public class MessageConverter : JsonConverterFactory + public MessageConverter() { - internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && - ti is { IsAbstract: false, IsInterface: false })).ToList()); - - /// - /// Initializes a new instance of the class. - /// - public MessageConverter() - { - } + } - /// - /// When overridden in a derived class, determines whether the converter instance can convert the specified object type. - /// - /// The type of the object to check whether it can be converted by this converter instance. - /// if the instance can convert the specified object type; otherwise, . + /// + /// When overridden in a derived class, determines whether the converter instance can convert the specified object type. + /// + /// The type of the object to check whether it can be converted by this converter instance. + /// if the instance can convert the specified object type; otherwise, . public override bool CanConvert(Type typeToConvert) - { - return (typeToConvert.IsGenericType && - typeToConvert.GetGenericTypeDefinition().HasInterfaces(typeof(IMessage<>))); - } + { + return (typeToConvert.IsGenericType && + typeToConvert.GetGenericTypeDefinition().HasInterfaces(typeof(IMessage<>))); + } - /// - /// Creates a converter for a specified type. - /// - /// The type handled by the converter. - /// The serialization options to use. - /// A converter that is compatible with . - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var requestType = typeToConvert.GetGenericArguments()[0]; - return (JsonConverter)Activator.CreateInstance( - typeof(MessageConverter<>).MakeGenericType(requestType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - } + /// + /// Creates a converter for a specified type. + /// + /// The type handled by the converter. + /// The serialization options to use. + /// A converter that is compatible with . + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var requestType = typeToConvert.GetGenericArguments()[0]; + return (JsonConverter)Activator.CreateInstance( + typeof(MessageConverter<>).MakeGenericType(requestType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; } +} - internal sealed class MessageConverter : JsonConverter> where T : IRequest +internal sealed class MessageConverter : JsonConverter> where T : IRequest +{ + public MessageConverter() { - public MessageConverter() - { - } + } - public override IMessage Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override IMessage Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using (var document = JsonDocument.ParseValue(ref reader)) { - using (var document = JsonDocument.ParseValue(ref reader)) + var idKey = options.PropertyNamingPolicy!.ConvertName(nameof(IMessage.Id)); + var sourceKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Source)); + var timeKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Time)); + var typeKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Type)); + var dataKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Data)); + var metadataKey = options.PropertyNamingPolicy.ConvertName(nameof(IMetadata.Metadata)); + var signatureKey = options.PropertyNamingPolicy.ConvertName(nameof(ISignedMessage.Signature)); + + var id = document.RootElement.GetProperty(idKey).GetString(); + var source = document.RootElement.GetProperty(sourceKey).GetString().ToUri(); + var type = document.RootElement.GetProperty(typeKey).GetString(); + var memberType = typeToConvert.GenericTypeArguments[0]; + var time = document.RootElement.GetProperty(timeKey).GetDateTimeOffset().UtcDateTime; + var data = (T)document.RootElement.GetProperty(dataKey).Deserialize(memberType!, options); + + ApplyMetadata(data, memberType, document.RootElement.GetProperty(dataKey), metadataKey, options); + + var message = new Message(id, source, type, data, time); + + if (typeToConvert.HasInterfaces(typeof(ICloudEvent<>))) { - var idKey = options.PropertyNamingPolicy!.ConvertName(nameof(IMessage.Id)); - var sourceKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Source)); - var timeKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Time)); - var typeKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Type)); - var dataKey = options.PropertyNamingPolicy.ConvertName(nameof(IMessage.Data)); - var metadataKey = options.PropertyNamingPolicy.ConvertName(nameof(IMetadata.Metadata)); - var signatureKey = options.PropertyNamingPolicy.ConvertName(nameof(ISignedMessage.Signature)); - - var id = document.RootElement.GetProperty(idKey).GetString(); - var source = document.RootElement.GetProperty(sourceKey).GetString().ToUri(); - var type = document.RootElement.GetProperty(typeKey).GetString(); - var memberType = typeToConvert.GenericTypeArguments[0]; - var time = document.RootElement.GetProperty(timeKey).GetDateTimeOffset().UtcDateTime; - var data = (T)document.RootElement.GetProperty(dataKey).Deserialize(memberType!, options); - - ApplyMetadata(data, memberType, document.RootElement.GetProperty(dataKey), metadataKey, options); - - var message = new Message(id, source, type, data, time); - - if (typeToConvert.HasInterfaces(typeof(ICloudEvent<>))) - { - var reservedKeys = new[] { idKey, sourceKey, timeKey, typeKey, dataKey, metadataKey, signatureKey }; - return CreateCloudEvent(typeToConvert, message, document.RootElement, signatureKey, reservedKeys, options); - } - - if (typeToConvert.HasInterfaces(typeof(ISignedMessage<>))) - { - var signature = document.RootElement.GetProperty(signatureKey).GetString(); - return new SignedMessage(message, signature); - } - - return message; + var reservedKeys = new[] { idKey, sourceKey, timeKey, typeKey, dataKey, metadataKey, signatureKey }; + return CreateCloudEvent(typeToConvert, message, document.RootElement, signatureKey, reservedKeys, options); } - } - // for unknown reasons, Microsoft does not use the custom converter for IMetadataDictionary here; have to fiddle extra around as seen below .. for the record; this just works with Newtonsoft! - private static void ApplyMetadata(T data, Type memberType, JsonElement dataElement, string metadataKey, JsonSerializerOptions options) - { - if (data is not IMetadata) { return; } - - var md = dataElement.GetProperty(metadataKey).Deserialize(options); - var property = memberType.GetAllProperties().SingleOrDefault(pi => pi.Name == nameof(IMetadata.Metadata)); - if (property == null) { return; } - - if (property.CanWrite) + if (typeToConvert.HasInterfaces(typeof(ISignedMessage<>))) { - property.SetValue(data, md); - } - else - { - memberType.GetAllFields().SingleOrDefault(fi => fi.Name.Contains(nameof(IMetadata.Metadata)))?.SetValue(data, md); + var signature = document.RootElement.GetProperty(signatureKey).GetString(); + return new SignedMessage(message, signature); } + + return message; } + } - private static IMessage CreateCloudEvent(Type typeToConvert, Message message, JsonElement root, string signatureKey, string[] reservedKeys, JsonSerializerOptions options) + // for unknown reasons, Microsoft does not use the custom converter for IMetadataDictionary here; have to fiddle extra around as seen below .. for the record; this just works with Newtonsoft! + private static void ApplyMetadata(T data, Type memberType, JsonElement dataElement, string metadataKey, JsonSerializerOptions options) + { + if (data is not IMetadata) { return; } + + var md = dataElement.GetProperty(metadataKey).Deserialize(options); + var property = memberType.GetAllProperties().SingleOrDefault(pi => pi.Name == nameof(IMetadata.Metadata)); + if (property == null) { return; } + + if (property.CanWrite) + { + property.SetValue(data, md); + } + else { - var specVersionKey = options.PropertyNamingPolicy!.ConvertName(nameof(ICloudEvent.Specversion)); - var requestType = typeToConvert.GetGenericArguments()[0]; - var cloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.CloudEvent", StringComparison.Ordinal)); - var specVersion = root.GetProperty(specVersionKey).GetString(); - var cloudEvent = Activator.CreateInstance(cloudEventType.MakeGenericType(requestType), [message, specVersion]) as IMessage; + memberType.GetAllFields().SingleOrDefault(fi => fi.Name.Contains(nameof(IMetadata.Metadata)))?.SetValue(data, md); + } + } - if (typeToConvert.HasInterfaces(typeof(ISignedCloudEvent<>))) - { - var signedCloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.Cryptography.SignedCloudEvent", StringComparison.Ordinal)); - var signature = root.GetProperty(signatureKey).GetString(); + private static IMessage CreateCloudEvent(Type typeToConvert, Message message, JsonElement root, string signatureKey, string[] reservedKeys, JsonSerializerOptions options) + { + var specVersionKey = options.PropertyNamingPolicy!.ConvertName(nameof(ICloudEvent.Specversion)); + var requestType = typeToConvert.GetGenericArguments()[0]; + var cloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.CloudEvent", StringComparison.Ordinal)); + var specVersion = root.GetProperty(specVersionKey).GetString(); + var cloudEvent = Activator.CreateInstance(cloudEventType.MakeGenericType(requestType), [message, specVersion]) as IMessage; - return Activator.CreateInstance(signedCloudEventType.MakeGenericType(requestType), [cloudEvent, signature]) as IMessage; - } + if (typeToConvert.HasInterfaces(typeof(ISignedCloudEvent<>))) + { + var signedCloudEventType = MessageConverter.CloudEventTypes.Value.Single(ti => ti.FullName!.StartsWith("Savvyio.EventDriven.Messaging.CloudEvents.Cryptography.SignedCloudEvent", StringComparison.Ordinal)); + var signature = root.GetProperty(signatureKey).GetString(); - AddExtensionAttributes(cloudEvent, root, [.. reservedKeys, specVersionKey], options); - return cloudEvent; + return Activator.CreateInstance(signedCloudEventType.MakeGenericType(requestType), [cloudEvent, signature]) as IMessage; } - private static void AddExtensionAttributes(IMessage cloudEvent, JsonElement root, string[] reservedKeys, JsonSerializerOptions options) - { - if (cloudEvent is not IDictionary dictionary) { return; } + AddExtensionAttributes(cloudEvent, root, [.. reservedKeys, specVersionKey], options); + return cloudEvent; + } - foreach (var property in root.EnumerateObject().Where(jp => !reservedKeys.Contains(jp.Name))) - { - dictionary.Add(property.Name, property.Value.Deserialize(property.Value.GetType(), options)); - } + private static void AddExtensionAttributes(IMessage cloudEvent, JsonElement root, string[] reservedKeys, JsonSerializerOptions options) + { + if (cloudEvent is not IDictionary dictionary) { return; } + + foreach (var property in root.EnumerateObject().Where(jp => !reservedKeys.Contains(jp.Name))) + { + dictionary.Add(property.Name, property.Value.Deserialize(property.Value.GetType(), options)); } + } - public override void Write(Utf8JsonWriter writer, IMessage value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, IMessage value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Id)), value.Id); + writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Source)), value.Source); + writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Type)), value.Type); + writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Time))); + writer.WriteObject(value.Time, options); + writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Data))); + writer.WriteObject(value.Data, options); + + if (value.GetType().HasInterfaces(typeof(ICloudEvent<>))) { - writer.WriteStartObject(); - writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Id)), value.Id); - writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Source)), value.Source); - writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Type)), value.Type); - writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Time))); - writer.WriteObject(value.Time, options); - writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(value.Data))); - writer.WriteObject(value.Data, options); - - if (value.GetType().HasInterfaces(typeof(ICloudEvent<>))) - { - dynamic ce = value; - writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(ICloudEvent.Specversion)), ce.Specversion); - } + dynamic ce = value; + writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(ICloudEvent.Specversion)), ce.Specversion); + } - if (value is ISignedMessage sm) - { - writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(sm.Signature)), sm.Signature); - } + if (value is ISignedMessage sm) + { + writer.WriteString(options.PropertyNamingPolicy.DefaultOrConvertName(nameof(sm.Signature)), sm.Signature); + } - if (value is IDictionary dictionary) + if (value is IDictionary dictionary) + { + foreach (var kvp in dictionary) { - foreach (var kvp in dictionary) - { - writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(kvp.Key)); - writer.WriteObject(kvp.Value, options); - } + writer.WritePropertyName(options.PropertyNamingPolicy.DefaultOrConvertName(kvp.Key)); + writer.WriteObject(kvp.Value, options); } - - writer.WriteEndObject(); } + + writer.WriteEndObject(); } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs index 3f3bfa4e..16e2c752 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs @@ -3,90 +3,89 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts an to or from JSON. +/// +/// +/// Inspiration taken from this article: https://josef.codes/custom-dictionary-string-object-jsonconverter-for-system-text-json/ +public class MetadataDictionaryConverter : JsonConverter { /// - /// Converts an to or from JSON. + /// Determines whether the specified type can be converted. /// - /// - /// Inspiration taken from this article: https://josef.codes/custom-dictionary-string-object-jsonconverter-for-system-text-json/ - public class MetadataDictionaryConverter : JsonConverter + /// The type to compare against. + /// if the type can be converted; otherwise, . + public override bool CanConvert(Type typeToConvert) { - /// - /// Determines whether the specified type can be converted. - /// - /// The type to compare against. - /// if the type can be converted; otherwise, . - public override bool CanConvert(Type typeToConvert) - { - return typeof(IMetadataDictionary).IsAssignableFrom(typeToConvert); - } + return typeof(IMetadataDictionary).IsAssignableFrom(typeToConvert); + } - /// - /// Reads and converts the JSON to . - /// - /// The reader. - /// The type to convert. - /// An object that specifies serialization options to use. - /// The converted value. - public override IMetadataDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + /// + /// Reads and converts the JSON to . + /// + /// The reader. + /// The type to convert. + /// An object that specifies serialization options to use. + /// The converted value. + public override IMetadataDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var md = new MetadataDictionary(); + while (reader.Read()) { - var md = new MetadataDictionary(); - while (reader.Read()) - { - if (reader.TokenType == JsonTokenType.EndObject) { return md; } - var propertyName = reader.GetString(); - reader.Read(); - md.Add(propertyName!, ExtractValue(ref reader, options)); - } - return md; + if (reader.TokenType == JsonTokenType.EndObject) { return md; } + var propertyName = reader.GetString(); + reader.Read(); + md.Add(propertyName!, ExtractValue(ref reader, options)); } + return md; + } - /// - /// Writes a specified as JSON. - /// - /// The writer to write to. - /// The value to convert to JSON. - /// An object that specifies serialization options to use. - public override void Write(Utf8JsonWriter writer, IMetadataDictionary value, JsonSerializerOptions options) - { - JsonSerializer.Serialize(writer, value, options.Clone(jso => jso.Converters.RemoveAllOf())); // prevent stackoverflow in case this method gets called - } + /// + /// Writes a specified as JSON. + /// + /// The writer to write to. + /// The value to convert to JSON. + /// An object that specifies serialization options to use. + public override void Write(Utf8JsonWriter writer, IMetadataDictionary value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value, options.Clone(jso => jso.Converters.RemoveAllOf())); // prevent stackoverflow in case this method gets called + } - private object ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions options) + private object ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions options) + { + switch (reader.TokenType) { - switch (reader.TokenType) - { - case JsonTokenType.String: - if (reader.TryGetDateTime(out var date)) - { - return date; - } - return reader.GetString(); - case JsonTokenType.False: - return false; - case JsonTokenType.True: - return true; - case JsonTokenType.Null: - return null; - case JsonTokenType.Number: - if (reader.TryGetInt64(out var result)) - { - return result; - } - return reader.GetDecimal(); - case JsonTokenType.StartObject: - return Read(ref reader, null!, options); - case JsonTokenType.StartArray: - var list = new List(); - while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) - { - list.Add(ExtractValue(ref reader, options)); - } - return list; - default: - throw new JsonException($"'{reader.TokenType}' is not supported."); - } + case JsonTokenType.String: + if (reader.TryGetDateTime(out var date)) + { + return date; + } + return reader.GetString(); + case JsonTokenType.False: + return false; + case JsonTokenType.True: + return true; + case JsonTokenType.Null: + return null; + case JsonTokenType.Number: + if (reader.TryGetInt64(out var result)) + { + return result; + } + return reader.GetDecimal(); + case JsonTokenType.StartObject: + return Read(ref reader, null!, options); + case JsonTokenType.StartArray: + var list = new List(); + while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) + { + list.Add(ExtractValue(ref reader, options)); + } + return list; + default: + throw new JsonException($"'{reader.TokenType}' is not supported."); } } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs index 0b5f67bb..367e1dbe 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs @@ -6,82 +6,81 @@ using System.Text.Json.Serialization; using Cuemon.Extensions.Reflection; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts an to or from JSON. +/// +/// +public class RequestConverter : JsonConverter { /// - /// Converts an to or from JSON. + /// Determines whether the specified type can be converted. /// - /// - public class RequestConverter : JsonConverter + /// The type to compare against. + /// if the type can be converted; otherwise, . + public override bool CanConvert(Type typeToConvert) { - /// - /// Determines whether the specified type can be converted. - /// - /// The type to compare against. - /// if the type can be converted; otherwise, . - public override bool CanConvert(Type typeToConvert) - { - return typeof(IRequest).IsAssignableFrom(typeToConvert); - } + return typeof(IRequest).IsAssignableFrom(typeToConvert); + } - /// - /// Reads and converts the JSON to . - /// - /// The reader. - /// The type to convert. - /// An object that specifies serialization options to use. - /// The converted value. - /// - /// This deserializer only supports rehydration of implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent. - /// - public override IRequest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + /// + /// Reads and converts the JSON to . + /// + /// The reader. + /// The type to convert. + /// An object that specifies serialization options to use. + /// The converted value. + /// + /// This deserializer only supports rehydration of implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent. + /// + public override IRequest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using (var document = JsonDocument.ParseValue(ref reader)) { - using (var document = JsonDocument.ParseValue(ref reader)) + var instance = RuntimeHelpers.GetUninitializedObject(typeToConvert); + var properties = typeToConvert.GetAllProperties(); + var jProperties = document.RootElement.EnumerateObject(); + foreach (var property in properties.Where(pi => jProperties.Any(jp => jp.Name.Equals(options.PropertyNamingPolicy!.ConvertName(pi.Name), StringComparison.OrdinalIgnoreCase)))) { - var instance = RuntimeHelpers.GetUninitializedObject(typeToConvert); - var properties = typeToConvert.GetAllProperties(); - var jProperties = document.RootElement.EnumerateObject(); - foreach (var property in properties.Where(pi => jProperties.Any(jp => jp.Name.Equals(options.PropertyNamingPolicy!.ConvertName(pi.Name), StringComparison.OrdinalIgnoreCase)))) + var jProperty = jProperties.Single(jp => jp.Name.Equals(options.PropertyNamingPolicy!.ConvertName(property.Name), StringComparison.OrdinalIgnoreCase)); + if (document.RootElement.TryGetProperty(jProperty.Name, out var element)) { - var jProperty = jProperties.Single(jp => jp.Name.Equals(options.PropertyNamingPolicy!.ConvertName(property.Name), StringComparison.OrdinalIgnoreCase)); - if (document.RootElement.TryGetProperty(jProperty.Name, out var element)) - { - var value = element.Deserialize(property.PropertyType, options); - SetPropertyOrField(instance, typeToConvert, property, value); - } + var value = element.Deserialize(property.PropertyType, options); + SetPropertyOrField(instance, typeToConvert, property, value); } - return instance as IRequest; } + return instance as IRequest; } + } - private static void SetPropertyOrField(object instance, Type typeToConvert, PropertyInfo property, object value) + private static void SetPropertyOrField(object instance, Type typeToConvert, PropertyInfo property, object value) + { + if (property.CanWrite) { - if (property.CanWrite) - { - property.SetValue(instance, value); - return; - } - - var field = property.IsAutoProperty() - ? typeToConvert.GetAllFields().SingleOrDefault(fi => fi.Name.StartsWith($"<{property.Name}>", StringComparison.Ordinal)) - : typeToConvert.GetAllFields().SingleOrDefault(fi => fi.Name.Equals($"_{property.Name}>", StringComparison.OrdinalIgnoreCase)); - if (field == null) - { - throw new NotSupportedException($"This deserializer only supports rehydration of {nameof(IRequest)} implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent."); - } - - field.SetValue(instance, value); + property.SetValue(instance, value); + return; } - /// - /// Writes a specified as JSON. - /// - /// The writer to write to. - /// The value to convert to JSON. - /// An object that specifies serialization options to use. - public override void Write(Utf8JsonWriter writer, IRequest value, JsonSerializerOptions options) + var field = property.IsAutoProperty() + ? typeToConvert.GetAllFields().SingleOrDefault(fi => fi.Name.StartsWith($"<{property.Name}>", StringComparison.Ordinal)) + : typeToConvert.GetAllFields().SingleOrDefault(fi => fi.Name.Equals($"_{property.Name}>", StringComparison.OrdinalIgnoreCase)); + if (field == null) { - JsonSerializer.Serialize(writer, (object)value, options.Clone(jso => jso.Converters.RemoveAllOf())); // prevent stackoverflow in case this method gets called + throw new NotSupportedException($"This deserializer only supports rehydration of {nameof(IRequest)} implementations that either use auto-properties or have a naming convention that makes it possible to tie non-writable properties with the backing field equivalent."); } + + field.SetValue(instance, value); + } + + /// + /// Writes a specified as JSON. + /// + /// The writer to write to. + /// The value to convert to JSON. + /// An object that specifies serialization options to use. + public override void Write(Utf8JsonWriter writer, IRequest value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, (object)value, options.Clone(jso => jso.Converters.RemoveAllOf())); // prevent stackoverflow in case this method gets called } } diff --git a/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs index b75e20ff..d0e1fb65 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs @@ -8,69 +8,68 @@ using Cuemon.Extensions.Text.Json; using Savvyio.Domain; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +/// +/// Converts a to or from JSON. +/// +/// +public class SingleValueObjectConverter : JsonConverterFactory { /// - /// Converts a to or from JSON. + /// Initializes a new instance of the class. /// - /// - public class SingleValueObjectConverter : JsonConverterFactory + public SingleValueObjectConverter() { - /// - /// Initializes a new instance of the class. - /// - public SingleValueObjectConverter() - { - } + } - /// - /// When overridden in a derived class, determines whether the converter instance can convert the specified object type. - /// - /// The type of the object to check whether it can be converted by this converter instance. - /// if the instance can convert the specified object type; otherwise, . - public override bool CanConvert(Type typeToConvert) - { - return typeToConvert.HasTypes(typeof(SingleValueObject<>)); - } + /// + /// When overridden in a derived class, determines whether the converter instance can convert the specified object type. + /// + /// The type of the object to check whether it can be converted by this converter instance. + /// if the instance can convert the specified object type; otherwise, . + public override bool CanConvert(Type typeToConvert) + { + return typeToConvert.HasTypes(typeof(SingleValueObject<>)); + } - /// - /// Creates a converter for a specified type. - /// - /// The type handled by the converter. - /// The serialization options to use. - /// A converter that is compatible with . - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var valueType = typeToConvert.GetInheritedTypes().Single(type => type.IsGenericType - && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; - return (JsonConverter)Activator.CreateInstance( - typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), - BindingFlags.Instance | BindingFlags.Public, - binder: null, - args: null, - culture: null)!; - } + /// + /// Creates a converter for a specified type. + /// + /// The type handled by the converter. + /// The serialization options to use. + /// A converter that is compatible with . + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var valueType = typeToConvert.GetInheritedTypes().Single(type => type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(SingleValueObject<>)).GetGenericArguments()[0]; + return (JsonConverter)Activator.CreateInstance( + typeof(SingleValueObjectConverter<>).MakeGenericType(valueType), + BindingFlags.Instance | BindingFlags.Public, + binder: null, + args: null, + culture: null)!; } +} - internal sealed class SingleValueObjectConverter : JsonConverter> +internal sealed class SingleValueObjectConverter : JsonConverter> +{ + public SingleValueObjectConverter() { - public SingleValueObjectConverter() - { - } + } - public override SingleValueObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override SingleValueObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using (var document = JsonDocument.ParseValue(ref reader)) { - using (var document = JsonDocument.ParseValue(ref reader)) - { - var valueType = typeof(T); - return Activator.CreateInstance(typeToConvert, document.RootElement.Deserialize(valueType)) as SingleValueObject; - } + var valueType = typeof(T); + return Activator.CreateInstance(typeToConvert, document.RootElement.Deserialize(valueType)) as SingleValueObject; } + } - public override void Write(Utf8JsonWriter writer, SingleValueObject value, JsonSerializerOptions options) - { - writer.WriteObject(value.Value, options); - } + public override void Write(Utf8JsonWriter writer, SingleValueObject value, JsonSerializerOptions options) + { + writer.WriteObject(value.Value, options); } } diff --git a/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs b/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs index 2f4d9857..07f68977 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs @@ -7,136 +7,135 @@ using Savvyio.Extensions.Text.Json.Converters; using Savvyio.Messaging; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +/// +/// Extension methods for the class. +/// +public static class JsonConverterExtensions { /// - /// Extension methods for the class. + /// Removes one or more implementations where evaluates true in the collection of . /// - public static class JsonConverterExtensions + /// The type of object or value handled by the . + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection RemoveAllOf(this ICollection converters) { - /// - /// Removes one or more implementations where evaluates true in the collection of . - /// - /// The type of object or value handled by the . - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection RemoveAllOf(this ICollection converters) - { - return RemoveAllOf(converters, typeof(T)); - } + return RemoveAllOf(converters, typeof(T)); + } - /// - /// Removes one or more implementations where evaluates true in the collection of . - /// - /// The collection of to extend. - /// The type of objects or values handled by a sequence of . - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection RemoveAllOf(this ICollection converters, params Type[] types) + /// + /// Removes one or more implementations where evaluates true in the collection of . + /// + /// The collection of to extend. + /// The type of objects or values handled by a sequence of . + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection RemoveAllOf(this ICollection converters, params Type[] types) + { + Validator.ThrowIfNull(converters); + Validator.ThrowIfNull(types); + var rejects = types.SelectMany(type => converters.Where(jc => jc.CanConvert(type))).ToList(); + foreach (var reject in rejects) { - Validator.ThrowIfNull(converters); - Validator.ThrowIfNull(types); - var rejects = types.SelectMany(type => converters.Where(jc => jc.CanConvert(type))).ToList(); - foreach (var reject in rejects) - { - converters.Remove(reject); - } - return converters; + converters.Remove(reject); } + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddMetadataDictionaryConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new MetadataDictionaryConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddMetadataDictionaryConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new MetadataDictionaryConverter()); + return converters; + } - /// - /// Adds an converter (or derived) to the collection. - /// - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddMessageConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new MessageConverter()); - return converters; - } + /// + /// Adds an converter (or derived) to the collection. + /// + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddMessageConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new MessageConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddRequestConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new RequestConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddRequestConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new RequestConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddDateTimeConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new DateTimeConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddDateTimeConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new DateTimeConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection of to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddDateTimeOffsetConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new DateTimeOffsetConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection of to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddDateTimeOffsetConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new DateTimeOffsetConverter()); + return converters; + } - /// - /// Adds a converter to the collection. - /// - /// The collection to extend. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null. - /// - public static ICollection AddSingleValueObjectConverter(this ICollection converters) - { - Validator.ThrowIfNull(converters); - converters.Add(new SingleValueObjectConverter()); - return converters; - } + /// + /// Adds a converter to the collection. + /// + /// The collection to extend. + /// A reference to so that additional calls can be chained. + /// + /// cannot be null. + /// + public static ICollection AddSingleValueObjectConverter(this ICollection converters) + { + Validator.ThrowIfNull(converters); + converters.Add(new SingleValueObjectConverter()); + return converters; } } diff --git a/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs b/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs index 0629a627..6c5fb8d1 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs @@ -2,65 +2,64 @@ using System.IO; using Cuemon.Extensions.Text.Json.Formatters; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +/// +/// Provides a class for marshalling data using native JSON support in .NET. +/// +/// +public class JsonMarshaller : IMarshaller { + private readonly Action _setup; + /// - /// Provides a class for marshalling data using native JSON support in .NET. + /// Provides a default instance of the class optimized for messaging. /// - /// - public class JsonMarshaller : IMarshaller - { - private readonly Action _setup; + /// The default instance of the class optimized for messaging. + public static JsonMarshaller Default { get; } = new(o => o.Settings.WriteIndented = false); - /// - /// Provides a default instance of the class optimized for messaging. - /// - /// The default instance of the class optimized for messaging. - public static JsonMarshaller Default { get; } = new(o => o.Settings.WriteIndented = false); - - /// - /// Creates a new instance of the class. - /// - /// The which may be configured. - /// JsonMarshaller. - public static JsonMarshaller Create(Action setup = null) => new(setup); + /// + /// Creates a new instance of the class. + /// + /// The which may be configured. + /// JsonMarshaller. + public static JsonMarshaller Create(Action setup = null) => new(setup); - static JsonMarshaller() - { - Bootstrapper.Initialize(); - } + static JsonMarshaller() + { + Bootstrapper.Initialize(); + } - /// - /// Initializes a new instance of the class. - /// - /// The which may be configured. - public JsonMarshaller(Action setup = null) - { - _setup = setup; - } + /// + /// Initializes a new instance of the class. + /// + /// The which may be configured. + public JsonMarshaller(Action setup = null) + { + _setup = setup; + } - /// - public Stream Serialize(TValue value) - { - return JsonFormatter.SerializeObject(value, _setup); - } + /// + public Stream Serialize(TValue value) + { + return JsonFormatter.SerializeObject(value, _setup); + } - /// - public Stream Serialize(object value, Type inputType) - { - return JsonFormatter.SerializeObject(value, inputType, _setup); - } + /// + public Stream Serialize(object value, Type inputType) + { + return JsonFormatter.SerializeObject(value, inputType, _setup); + } - /// - public TValue Deserialize(Stream data) - { - return JsonFormatter.DeserializeObject(data, _setup); - } + /// + public TValue Deserialize(Stream data) + { + return JsonFormatter.DeserializeObject(data, _setup); + } - /// - public object Deserialize(Stream data, Type returnType) - { - return JsonFormatter.DeserializeObject(data, returnType, _setup); - } + /// + public object Deserialize(Stream data, Type returnType) + { + return JsonFormatter.DeserializeObject(data, returnType, _setup); } } diff --git a/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs b/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs index abd39b27..2870f95a 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs @@ -2,28 +2,27 @@ using System.Text.Json; using Cuemon; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +/// +/// Extension methods for the class. +/// +public static class JsonSerializerOptionsExtensions { /// - /// Extension methods for the class. + /// Copies the options from a instance to a new instance. /// - public static class JsonSerializerOptionsExtensions + /// The to extend. + /// The which may be configured. + /// A new cloned instance of with optional altering as specified by the delegate. + /// + /// cannot be null. + /// + public static JsonSerializerOptions Clone(this JsonSerializerOptions options, Action setup = null) { - /// - /// Copies the options from a instance to a new instance. - /// - /// The to extend. - /// The which may be configured. - /// A new cloned instance of with optional altering as specified by the delegate. - /// - /// cannot be null. - /// - public static JsonSerializerOptions Clone(this JsonSerializerOptions options, Action setup = null) - { - Validator.ThrowIfNull(options); - options = new JsonSerializerOptions(options); - setup?.Invoke(options); - return options; - } + Validator.ThrowIfNull(options); + options = new JsonSerializerOptions(options); + setup?.Invoke(options); + return options; } } diff --git a/src/Savvyio.Messaging/Acknowledgeable.cs b/src/Savvyio.Messaging/Acknowledgeable.cs index 44fed49c..1fe527b0 100644 --- a/src/Savvyio.Messaging/Acknowledgeable.cs +++ b/src/Savvyio.Messaging/Acknowledgeable.cs @@ -1,41 +1,40 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Provides a default implementation of the interface. +/// +public abstract record Acknowledgeable : IAcknowledgeable { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - public abstract record Acknowledgeable : IAcknowledgeable + protected Acknowledgeable() { - /// - /// Initializes a new instance of the class. - /// - protected Acknowledgeable() - { - Properties = new Dictionary(); - } + Properties = new Dictionary(); + } - /// - public event AsyncEventHandler Acknowledged; + /// + public event AsyncEventHandler Acknowledged; - /// - public IDictionary Properties { get; } + /// + public IDictionary Properties { get; } - /// - public async Task AcknowledgeAsync() - { - await OnAcknowledgedAsync(new AcknowledgedEventArgs(Properties)).ConfigureAwait(false); - } + /// + public async Task AcknowledgeAsync() + { + await OnAcknowledgedAsync(new AcknowledgedEventArgs(Properties)).ConfigureAwait(false); + } - /// - /// Raises the event. - /// - /// The instance containing the event data. - protected virtual async Task OnAcknowledgedAsync(AcknowledgedEventArgs e) - { - var handler = Acknowledged; - if (handler != null) { await handler(this, e).ConfigureAwait(false); } - } + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual async Task OnAcknowledgedAsync(AcknowledgedEventArgs e) + { + var handler = Acknowledged; + if (handler != null) { await handler(this, e).ConfigureAwait(false); } } } diff --git a/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs b/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs index 4bdb84dd..1549fc99 100644 --- a/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs +++ b/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs @@ -2,36 +2,35 @@ using Cuemon; using Cuemon.Security.Cryptography; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +/// +/// Extension methods for the interface. +/// +public static class MessageExtensions { /// - /// Extension methods for the interface. + /// Converts the specified to an equivalent using the provided configurator. /// - public static class MessageExtensions + /// The type of the payload constraint to the interface. + /// The message to cryptographically sign. + /// The that is used when converting the into an . + /// The that must be configured. + /// An implementation of the interface having a constraint to the interface. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + public static ISignedMessage Sign(this IMessage message, IMarshaller marshaller, Action setup) where T : IRequest { - /// - /// Converts the specified to an equivalent using the provided configurator. - /// - /// The type of the payload constraint to the interface. - /// The message to cryptographically sign. - /// The that is used when converting the into an . - /// The that must be configured. - /// An implementation of the interface having a constraint to the interface. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - public static ISignedMessage Sign(this IMessage message, IMarshaller marshaller, Action setup) where T : IRequest - { - Validator.ThrowIfNull(message); - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - var data = marshaller.Serialize(message); - var signature = KeyedHashFactory.CreateHmacCrypto(options.SignatureSecret, options.SignatureAlgorithm).ComputeHash(data).ToHexadecimalString(); - return new SignedMessage(message, signature); - } + Validator.ThrowIfNull(message); + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + var data = marshaller.Serialize(message); + var signature = KeyedHashFactory.CreateHmacCrypto(options.SignatureSecret, options.SignatureAlgorithm).ComputeHash(data).ToHexadecimalString(); + return new SignedMessage(message, signature); } } diff --git a/src/Savvyio.Messaging/Cryptography/SignedMessage.cs b/src/Savvyio.Messaging/Cryptography/SignedMessage.cs index fd084361..28eb3018 100644 --- a/src/Savvyio.Messaging/Cryptography/SignedMessage.cs +++ b/src/Savvyio.Messaging/Cryptography/SignedMessage.cs @@ -1,58 +1,57 @@ using System; using Cuemon; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +/// +/// Provides a default implementation of the interface. +/// +/// The type of the payload constraint to the interface. +/// + public record SignedMessage : Acknowledgeable, ISignedMessage where T : IRequest { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// The type of the payload constraint to the interface. - /// - public record SignedMessage : Acknowledgeable, ISignedMessage where T : IRequest + /// The message to cryptographically sign. + /// The cryptographic signature of the . + /// + /// cannot be null - or - + /// cannot be null. + /// + /// + /// cannot be empty or consist only of white-space characters. + /// + public SignedMessage(IMessage message, string signature) { - /// - /// Initializes a new instance of the class. - /// - /// The message to cryptographically sign. - /// The cryptographic signature of the . - /// - /// cannot be null - or - - /// cannot be null. - /// - /// - /// cannot be empty or consist only of white-space characters. - /// - public SignedMessage(IMessage message, string signature) - { - Validator.ThrowIfNull(message); - Validator.ThrowIfNullOrWhitespace(signature); - Id = message.Id; - Source = message.Source; - Type = message.Type; - Time = message.Time; - Data = message.Data; - Signature = signature; - } - - /// - public string Id { get; } - - /// - public string Source { get; } - - /// - public string Type { get; } - - /// - public DateTime? Time { get; } - - /// - public T Data { get; } - - /// - /// Gets the cryptographic signature of the message. - /// - /// The cryptographic signature of the message. - public string Signature { get; } + Validator.ThrowIfNull(message); + Validator.ThrowIfNullOrWhitespace(signature); + Id = message.Id; + Source = message.Source; + Type = message.Type; + Time = message.Time; + Data = message.Data; + Signature = signature; } + + /// + public string Id { get; } + + /// + public string Source { get; } + + /// + public string Type { get; } + + /// + public DateTime? Time { get; } + + /// + public T Data { get; } + + /// + /// Gets the cryptographic signature of the message. + /// + /// The cryptographic signature of the message. + public string Signature { get; } } diff --git a/src/Savvyio.Messaging/Cryptography/SignedMessageExtensions.cs b/src/Savvyio.Messaging/Cryptography/SignedMessageExtensions.cs index 6d9768c4..dc421776 100644 --- a/src/Savvyio.Messaging/Cryptography/SignedMessageExtensions.cs +++ b/src/Savvyio.Messaging/Cryptography/SignedMessageExtensions.cs @@ -1,41 +1,40 @@ using System; using Cuemon; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +/// +/// Extension methods for the interface. +/// +public static class SignedMessageExtensions { /// - /// Extension methods for the interface. + /// Verifies the digital signature of the message. /// - public static class SignedMessageExtensions + /// The type of the payload constraint to the interface. + /// The message to cryptographically verify. + /// The that is used when converting the into an . + /// The that must be configured. + /// + /// cannot be null -or- + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + /// + /// signature did not match the cryptographically calculated value. + /// + /// This method throws an if the verification of the digital signature fails. + public static void CheckSignature(this ISignedMessage message, IMarshaller marshaller, Action setup) where T : IRequest { - /// - /// Verifies the digital signature of the message. - /// - /// The type of the payload constraint to the interface. - /// The message to cryptographically verify. - /// The that is used when converting the into an . - /// The that must be configured. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - /// - /// signature did not match the cryptographically calculated value. - /// - /// This method throws an if the verification of the digital signature fails. - public static void CheckSignature(this ISignedMessage message, IMarshaller marshaller, Action setup) where T : IRequest + Validator.ThrowIfNull(message); + Validator.ThrowIfNull(marshaller); + Validator.ThrowIfInvalidConfigurator(setup, out _); + var baseMessage = message.Clone().Sign(marshaller, setup); + if (!message.Signature.Equals(baseMessage.Signature, StringComparison.Ordinal)) { - Validator.ThrowIfNull(message); - Validator.ThrowIfNull(marshaller); - Validator.ThrowIfInvalidConfigurator(setup, out _); - var baseMessage = message.Clone().Sign(marshaller, setup); - if (!message.Signature.Equals(baseMessage.Signature, StringComparison.Ordinal)) - { - throw new ArgumentOutOfRangeException(nameof(message), message.Signature, "The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with."); - } + throw new ArgumentOutOfRangeException(nameof(message), message.Signature, "The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with."); } } } diff --git a/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs b/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs index be327b73..e4290817 100644 --- a/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs +++ b/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs @@ -3,59 +3,58 @@ using Cuemon.Configuration; using Cuemon.Security.Cryptography; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +/// +/// Configuration options that is related to wrapping an implementation inside a cryptographically signed message. +/// +/// + public class SignedMessageOptions : IValidatableParameterObject { /// - /// Configuration options that is related to wrapping an implementation inside a cryptographically signed message. + /// Initializes a new instance of the class. /// - /// - public class SignedMessageOptions : IValidatableParameterObject + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// + /// + /// + /// + public SignedMessageOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// - /// - /// - /// - public SignedMessageOptions() - { - SignatureAlgorithm = KeyedCryptoAlgorithm.HmacSha256; - SignatureSecret = null; - } + SignatureAlgorithm = KeyedCryptoAlgorithm.HmacSha256; + SignatureSecret = null; + } - /// - /// Gets or sets the cryptographical algorithm used when signing the serialized . - /// - /// The cryptographical algorithm used when signing the serialized . - public KeyedCryptoAlgorithm SignatureAlgorithm { get; set; } + /// + /// Gets or sets the cryptographical algorithm used when signing the serialized . + /// + /// The cryptographical algorithm used when signing the serialized . + public KeyedCryptoAlgorithm SignatureAlgorithm { get; set; } - /// - /// Gets or sets the secret key used when signing the serialized . - /// - /// The secret key used when signing the serialized . - public byte[] SignatureSecret { get; set; } + /// + /// Gets or sets the secret key used when signing the serialized . + /// + /// The secret key used when signing the serialized . + public byte[] SignatureSecret { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null - or - - /// cannot have a length of zero. - /// + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null - or - + /// cannot have a length of zero. + /// public void ValidateOptions() - { - Validator.ThrowIfInvalidState(SignatureSecret == null || SignatureSecret.Length == 0); - } + { + Validator.ThrowIfInvalidState(SignatureSecret == null || SignatureSecret.Length == 0); } } diff --git a/src/Savvyio.Messaging/Message.cs b/src/Savvyio.Messaging/Message.cs index e2654fa1..4ad7b1f8 100644 --- a/src/Savvyio.Messaging/Message.cs +++ b/src/Savvyio.Messaging/Message.cs @@ -1,65 +1,64 @@ using System; using Cuemon; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Provides a default implementation of the interface. +/// +/// The type of the payload constraint to the interface. +/// +public record Message : Acknowledgeable, IMessage where T : IRequest { /// - /// Provides a default implementation of the interface. + /// Initializes a new instance of the class. /// - /// The type of the payload constraint to the interface. - /// - public record Message : Acknowledgeable, IMessage where T : IRequest + /// The identifier of the message. + /// The context that describes the origin of the message. + /// The payload of the message. + /// The type that describes the type of event related to the originating occurrence. + /// The time at which this message was generated. + /// + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null - or - + /// cannot be null. + /// + /// + /// cannot be empty or consist only of white-space characters - or - + /// cannot be empty or consist only of white-space characters - or - + /// was not expressed as the Coordinated Universal Time (UTC). + /// + public Message(string id, Uri source, string type, T data, DateTime? time = null) { - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the message. - /// The context that describes the origin of the message. - /// The payload of the message. - /// The type that describes the type of event related to the originating occurrence. - /// The time at which this message was generated. - /// - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null - or - - /// cannot be null. - /// - /// - /// cannot be empty or consist only of white-space characters - or - - /// cannot be empty or consist only of white-space characters - or - - /// was not expressed as the Coordinated Universal Time (UTC). - /// - public Message(string id, Uri source, string type, T data, DateTime? time = null) - { - Validator.ThrowIfNullOrWhitespace(id); - Validator.ThrowIfNull(source); - Validator.ThrowIfNullOrWhitespace(type); - Validator.ThrowIfNull(data); - Validator.ThrowIfTrue(() => time.HasValue && time.Value.Kind != DateTimeKind.Utc, nameof(time), "Time must be expressed as the Coordinated Universal Time (UTC)."); - Id = id; - Source = source.OriginalString; - Type = type; - Data = data; - Time = (time ?? DateTime.UtcNow); - } + Validator.ThrowIfNullOrWhitespace(id); + Validator.ThrowIfNull(source); + Validator.ThrowIfNullOrWhitespace(type); + Validator.ThrowIfNull(data); + Validator.ThrowIfTrue(() => time.HasValue && time.Value.Kind != DateTimeKind.Utc, nameof(time), "Time must be expressed as the Coordinated Universal Time (UTC)."); + Id = id; + Source = source.OriginalString; + Type = type; + Data = data; + Time = (time ?? DateTime.UtcNow); + } - internal Message() - { - } + internal Message() + { + } - /// - public string Id { get; internal set; } + /// + public string Id { get; internal set; } - /// - public string Source { get; internal set; } + /// + public string Source { get; internal set; } - /// - public string Type { get; internal set; } + /// + public string Type { get; internal set; } - /// - public DateTime? Time { get; internal set; } + /// + public DateTime? Time { get; internal set; } - /// - public T Data { get; internal set; } - } + /// + public T Data { get; internal set; } } diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerable.cs b/src/Savvyio.Messaging/MessageAsyncEnumerable.cs index d40c7d1a..bb3f3f58 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerable.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerable.cs @@ -4,55 +4,54 @@ using System.Threading; using Cuemon; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Exposes an enumerator that provides asynchronous iteration over values of a specified type. +/// +/// The type of the elements in the collection. +/// +public class MessageAsyncEnumerable : IAsyncEnumerable> where T : IRequest { + private readonly IAsyncEnumerable> _source; + private readonly MessageAsyncEnumerableOptions _options; + + /// - /// Exposes an enumerator that provides asynchronous iteration over values of a specified type. + /// Initializes a new instance of the class. /// - /// The type of the elements in the collection. - /// - public class MessageAsyncEnumerable : IAsyncEnumerable> where T : IRequest + /// The sequence to iterate. + /// The which may be configured. + public MessageAsyncEnumerable(IEnumerable> source, Action> setup = null) : this(source?.ToAsyncEnumerable(), setup) { - private readonly IAsyncEnumerable> _source; - private readonly MessageAsyncEnumerableOptions _options; - - - /// - /// Initializes a new instance of the class. - /// - /// The sequence to iterate. - /// The which may be configured. - public MessageAsyncEnumerable(IEnumerable> source, Action> setup = null) : this(source?.ToAsyncEnumerable(), setup) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The sequence to iterate. - /// The which may be configured. - /// - /// cannot be null. - /// - /// - /// failed to configure an instance of in a valid state. - /// - public MessageAsyncEnumerable(IAsyncEnumerable> source, Action> setup = null) - { - Validator.ThrowIfNull(source); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - _source = source; - _options = options; - } + /// + /// Initializes a new instance of the class. + /// + /// The sequence to iterate. + /// The which may be configured. + /// + /// cannot be null. + /// + /// + /// failed to configure an instance of in a valid state. + /// + public MessageAsyncEnumerable(IAsyncEnumerable> source, Action> setup = null) + { + Validator.ThrowIfNull(source); + Validator.ThrowIfInvalidConfigurator(setup, out var options); + _source = source; + _options = options; + } - /// - /// Returns an enumerator that iterates asynchronously through the collection. - /// - /// A that may be used to cancel the asynchronous iteration. - /// An enumerator that can be used to iterate asynchronously through the collection. - public virtual IAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) - { - return new MessageAsyncEnumerator(_source.GetAsyncEnumerator(cancellationToken), _options); - } + /// + /// Returns an enumerator that iterates asynchronously through the collection. + /// + /// A that may be used to cancel the asynchronous iteration. + /// An enumerator that can be used to iterate asynchronously through the collection. + public virtual IAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new MessageAsyncEnumerator(_source.GetAsyncEnumerator(cancellationToken), _options); } } diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs b/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs index 156f9366..1ebe5b51 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs @@ -5,66 +5,65 @@ using Cuemon; using Cuemon.Configuration; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Configuration options that is related to messages. +/// +/// The type of the payload constraint to the interface. +public class MessageAsyncEnumerableOptions : IValidatableParameterObject where T : IRequest { /// - /// Configuration options that is related to messages. + /// Initializes a new instance of the class. /// - /// The type of the payload constraint to the interface. - public class MessageAsyncEnumerableOptions : IValidatableParameterObject where T : IRequest + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// new ConcurrentBag<IDictionary<string, object>>() + /// + /// + /// + /// null + /// + /// + /// + /// null + /// + /// + /// + public MessageAsyncEnumerableOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// new ConcurrentBag<IDictionary<string, object>>() - /// - /// - /// - /// null - /// - /// - /// - /// null - /// - /// - /// - public MessageAsyncEnumerableOptions() - { - AcknowledgedProperties = new ConcurrentBag>(); - } + AcknowledgedProperties = new ConcurrentBag>(); + } - /// - /// Gets or sets the delegate that is invoked once for each message fetched from a source. - /// - /// The delegate that is invoked once for each message fetched from a source. - public Func, Task> MessageCallback { get; set; } + /// + /// Gets or sets the delegate that is invoked once for each message fetched from a source. + /// + /// The delegate that is invoked once for each message fetched from a source. + public Func, Task> MessageCallback { get; set; } - /// - /// Gets or sets the implementation of an that is used to store all acknowledged properties. Default is a new instance of . - /// - /// The implementation of an that is used to store all acknowledged properties. - public IProducerConsumerCollection> AcknowledgedProperties { get; set; } + /// + /// Gets or sets the implementation of an that is used to store all acknowledged properties. Default is a new instance of . + /// + /// The implementation of an that is used to store all acknowledged properties. + public IProducerConsumerCollection> AcknowledgedProperties { get; set; } - /// - /// Gets or sets the delegate that is invoked at the end of a sequence with all acknowledged properties. - /// - /// The delegate that is invoked at the end of a sequence with all acknowledged properties. - public Func>, Task> AcknowledgedPropertiesCallback { get; set; } + /// + /// Gets or sets the delegate that is invoked at the end of a sequence with all acknowledged properties. + /// + /// The delegate that is invoked at the end of a sequence with all acknowledged properties. + public Func>, Task> AcknowledgedPropertiesCallback { get; set; } - /// - public void ValidateOptions() - { - Validator.ThrowIfInvalidState(AcknowledgedProperties == null, $"{nameof(AcknowledgedProperties)} cannot be null."); - Validator.ThrowIfInvalidState(MessageCallback == null, $"{nameof(MessageCallback)} cannot be null."); - } + /// + public void ValidateOptions() + { + Validator.ThrowIfInvalidState(AcknowledgedProperties == null, $"{nameof(AcknowledgedProperties)} cannot be null."); + Validator.ThrowIfInvalidState(MessageCallback == null, $"{nameof(MessageCallback)} cannot be null."); } } diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerator.cs b/src/Savvyio.Messaging/MessageAsyncEnumerator.cs index 8f7be43a..8e69ad61 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerator.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerator.cs @@ -2,50 +2,49 @@ using System.Threading.Tasks; using Cuemon; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +internal sealed class MessageAsyncEnumerator : IAsyncEnumerator> where T : IRequest { - internal sealed class MessageAsyncEnumerator : IAsyncEnumerator> where T : IRequest + private readonly IAsyncEnumerator> _source; + private readonly MessageAsyncEnumerableOptions _options; + + internal MessageAsyncEnumerator(IAsyncEnumerator> source, MessageAsyncEnumerableOptions options) { - private readonly IAsyncEnumerator> _source; - private readonly MessageAsyncEnumerableOptions _options; + Validator.ThrowIfNull(source); + _source = source; + _options = options; + } - internal MessageAsyncEnumerator(IAsyncEnumerator> source, MessageAsyncEnumerableOptions options) - { - Validator.ThrowIfNull(source); - _source = source; - _options = options; - } + public IMessage Current => _source.Current; - public IMessage Current => _source.Current; + public ValueTask DisposeAsync() + { + return _source.DisposeAsync(); + } - public ValueTask DisposeAsync() + public async ValueTask MoveNextAsync() + { + var mn = await _source.MoveNextAsync().ConfigureAwait(false); + if (mn && _options.MessageCallback != null) { - return _source.DisposeAsync(); + _source.Current.Acknowledged += OnAcknowledgedAsync; + await _options.MessageCallback(_source.Current).ConfigureAwait(false); } - - public async ValueTask MoveNextAsync() + else { - var mn = await _source.MoveNextAsync().ConfigureAwait(false); - if (mn && _options.MessageCallback != null) - { - _source.Current.Acknowledged += OnAcknowledgedAsync; - await _options.MessageCallback(_source.Current).ConfigureAwait(false); - } - else + if (_options.AcknowledgedProperties.Count > 0 && _options.AcknowledgedPropertiesCallback != null) { - if (_options.AcknowledgedProperties.Count > 0 && _options.AcknowledgedPropertiesCallback != null) - { - await _options.AcknowledgedPropertiesCallback(_options.AcknowledgedProperties).ConfigureAwait(false); - } + await _options.AcknowledgedPropertiesCallback(_options.AcknowledgedProperties).ConfigureAwait(false); } - return mn; } + return mn; + } - private Task OnAcknowledgedAsync(object sender, AcknowledgedEventArgs e) - { - _options.AcknowledgedProperties.TryAdd(e.Properties); - if (sender is IAcknowledgeable message) { message.Acknowledged -= OnAcknowledgedAsync; } - return Task.CompletedTask; - } + private Task OnAcknowledgedAsync(object sender, AcknowledgedEventArgs e) + { + _options.AcknowledgedProperties.TryAdd(e.Properties); + if (sender is IAcknowledgeable message) { message.Acknowledged -= OnAcknowledgedAsync; } + return Task.CompletedTask; } } diff --git a/src/Savvyio.Messaging/MessageExtensions.cs b/src/Savvyio.Messaging/MessageExtensions.cs index 708e0322..a27597ab 100644 --- a/src/Savvyio.Messaging/MessageExtensions.cs +++ b/src/Savvyio.Messaging/MessageExtensions.cs @@ -1,34 +1,33 @@ using System; using Cuemon; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Extension methods for the interface. +/// +public static class MessageExtensions { /// - /// Extension methods for the interface. + /// Clones the specified using either the specified or the default implementation that return a new instance of . /// - public static class MessageExtensions + /// The type of the payload constraint to the interface. + /// The to clone. + /// The function delegate that is used to clone the specified . Default is null. + /// An implementation of that is an otherwise clone of the specified . + /// + /// cannot be null. + /// + public static IMessage Clone(this IMessage message, Func> copier = null) where T : IRequest { - /// - /// Clones the specified using either the specified or the default implementation that return a new instance of . - /// - /// The type of the payload constraint to the interface. - /// The to clone. - /// The function delegate that is used to clone the specified . Default is null. - /// An implementation of that is an otherwise clone of the specified . - /// - /// cannot be null. - /// - public static IMessage Clone(this IMessage message, Func> copier = null) where T : IRequest + Validator.ThrowIfNull(message); + return copier?.Invoke() ?? new Message() { - Validator.ThrowIfNull(message); - return copier?.Invoke() ?? new Message() - { - Data = message.Data, - Id = message.Id, - Source = message.Source, - Time = message.Time, - Type = message.Type - }; - } + Data = message.Data, + Id = message.Id, + Source = message.Source, + Time = message.Time, + Type = message.Type + }; } } diff --git a/src/Savvyio.Messaging/MessageOptions.cs b/src/Savvyio.Messaging/MessageOptions.cs index 7c77058c..445bc3b5 100644 --- a/src/Savvyio.Messaging/MessageOptions.cs +++ b/src/Savvyio.Messaging/MessageOptions.cs @@ -3,60 +3,59 @@ using Cuemon.Configuration; using Cuemon.Extensions; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +/// +/// Configuration options that is related to wrapping an implementation inside a message. +/// +/// +public class MessageOptions : IValidatableParameterObject { /// - /// Configuration options that is related to wrapping an implementation inside a message. + /// Initializes a new instance of the class. /// - /// - public class MessageOptions : IValidatableParameterObject + /// + /// The following table shows the initial property values for an instance of . + /// + /// + /// Property + /// Initial Value + /// + /// + /// + /// Guid.NewGuid().ToString("N") + /// + /// + /// + public MessageOptions() { - /// - /// Initializes a new instance of the class. - /// - /// - /// The following table shows the initial property values for an instance of . - /// - /// - /// Property - /// Initial Value - /// - /// - /// - /// Guid.NewGuid().ToString("N") - /// - /// - /// - public MessageOptions() - { - MessageId = Guid.NewGuid().ToString("N"); - Time = null; - } + MessageId = Guid.NewGuid().ToString("N"); + Time = null; + } - /// - /// Gets or sets the identifier of the message. - /// - /// The identifier of the message. - public string MessageId { get; set; } + /// + /// Gets or sets the identifier of the message. + /// + /// The identifier of the message. + public string MessageId { get; set; } - /// - /// Gets or sets the time, expressed as the Coordinated Universal Time (UTC), of the message. - /// - /// The point in time the message was generated. - public DateTime? Time { get; set; } + /// + /// Gets or sets the time, expressed as the Coordinated Universal Time (UTC), of the message. + /// + /// The point in time the message was generated. + public DateTime? Time { get; set; } - /// - /// Determines whether the public read-write properties of this instance are in a valid state. - /// - /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. - /// - /// cannot be null, empty or consist only of white-space characters - or - - /// (when set) was not expressed as the Coordinated Universal Time (UTC). - /// - public virtual void ValidateOptions() - { - Validator.ThrowIfInvalidState(MessageId.IsNullOrWhiteSpace()); - Validator.ThrowIfInvalidState(Time.HasValue && Time.Value.Kind != DateTimeKind.Utc); - } + /// + /// Determines whether the public read-write properties of this instance are in a valid state. + /// + /// This method is expected to throw exceptions when one or more conditions fails to be in a valid state. + /// + /// cannot be null, empty or consist only of white-space characters - or - + /// (when set) was not expressed as the Coordinated Universal Time (UTC). + /// + public virtual void ValidateOptions() + { + Validator.ThrowIfInvalidState(MessageId.IsNullOrWhiteSpace()); + Validator.ThrowIfInvalidState(Time.HasValue && Time.Value.Kind != DateTimeKind.Utc); } } diff --git a/src/Savvyio.Queries/Query.cs b/src/Savvyio.Queries/Query.cs index d5d4af05..048154e0 100644 --- a/src/Savvyio.Queries/Query.cs +++ b/src/Savvyio.Queries/Query.cs @@ -1,20 +1,19 @@ -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Provides a default implementation of of the interface. +/// +/// The type of the result to return. +/// +/// +public abstract record Query : Request, IQuery { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// The type of the result to return. - /// - /// - public abstract record Query : Request, IQuery + /// The optional metadata to merge with this instance. + protected Query(IMetadata metadata = null) { - /// - /// Initializes a new instance of the class. - /// - /// The optional metadata to merge with this instance. - protected Query(IMetadata metadata = null) - { - this.MergeMetadata(metadata); - } + this.MergeMetadata(metadata); } } diff --git a/src/Savvyio.Queries/QueryDispatcher.cs b/src/Savvyio.Queries/QueryDispatcher.cs index ee9e1054..de0a2d59 100644 --- a/src/Savvyio.Queries/QueryDispatcher.cs +++ b/src/Savvyio.Queries/QueryDispatcher.cs @@ -4,46 +4,45 @@ using Cuemon.Threading; using Savvyio.Dispatchers; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Provides a default implementation of of the interface. +/// +/// +/// +public class QueryDispatcher : RequestReplyDispatcher, IQueryDispatcher { /// - /// Provides a default implementation of of the interface. + /// Initializes a new instance of the class. /// - /// - /// - public class QueryDispatcher : RequestReplyDispatcher, IQueryDispatcher + /// The provider of service implementations. + public QueryDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) { - /// - /// Initializes a new instance of the class. - /// - /// The provider of service implementations. - public QueryDispatcher(IServiceLocator serviceLocator) : base(serviceLocator) - { - } + } - /// - /// Queries the specified using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// TResult. - public TResult Query(IQuery request) - { - Validator.ThrowIfNull(request); - return Dispatch(request, handler => handler.Delegates); - } + /// + /// Queries the specified using Request-Reply/In-Out MEP. + /// + /// The type of the result to return. + /// The to request. + /// TResult. + public TResult Query(IQuery request) + { + Validator.ThrowIfNull(request); + return Dispatch(request, handler => handler.Delegates); + } - /// - /// Queries the specified asynchronous using Request-Reply/In-Out MEP. - /// - /// The type of the result to return. - /// The to request. - /// The which may be configured. - /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. - public Task QueryAsync(IQuery request, Action setup = null) - { - Validator.ThrowIfNull(request); - return DispatchAsync(request, handler => handler.Delegates, setup); - } + /// + /// Queries the specified asynchronous using Request-Reply/In-Out MEP. + /// + /// The type of the result to return. + /// The to request. + /// The which may be configured. + /// A that represents the asynchronous operation. The task result contains the outcome of the query operation. + public Task QueryAsync(IQuery request, Action setup = null) + { + Validator.ThrowIfNull(request); + return DispatchAsync(request, handler => handler.Delegates, setup); } } diff --git a/src/Savvyio.Queries/QueryHandler.cs b/src/Savvyio.Queries/QueryHandler.cs index 36addfdc..0e8a0d1c 100644 --- a/src/Savvyio.Queries/QueryHandler.cs +++ b/src/Savvyio.Queries/QueryHandler.cs @@ -1,31 +1,30 @@ using Savvyio.Handlers; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Provides a generic and consistent way of handling Query objects that implements the interface. This is an abstract class. +/// +/// +public abstract class QueryHandler : IQueryHandler { /// - /// Provides a generic and consistent way of handling Query objects that implements the interface. This is an abstract class. + /// Initializes a new instance of the class. /// - /// - public abstract class QueryHandler : IQueryHandler + protected QueryHandler() { - /// - /// Initializes a new instance of the class. - /// - protected QueryHandler() - { - Delegates = HandlerFactory.CreateRequestReply(RegisterDelegates); - } + Delegates = HandlerFactory.CreateRequestReply(RegisterDelegates); + } - /// - /// Registers the delegates responsible of handling types that implements the interface. - /// - /// The registry that store the delegates of type . - protected abstract void RegisterDelegates(IRequestReplyRegistry handlers); + /// + /// Registers the delegates responsible of handling types that implements the interface. + /// + /// The registry that store the delegates of type . + protected abstract void RegisterDelegates(IRequestReplyRegistry handlers); - /// - /// Gets the activator responsible of invoking delegates that handles . - /// - /// The activator responsible of invoking delegates that handles . - public IRequestReplyActivator Delegates { get; } - } + /// + /// Gets the activator responsible of invoking delegates that handles . + /// + /// The activator responsible of invoking delegates that handles . + public IRequestReplyActivator Delegates { get; } } diff --git a/src/Savvyio.Queries/SavvyioOptionsExtensions.cs b/src/Savvyio.Queries/SavvyioOptionsExtensions.cs index 3a2625aa..8a4665a1 100644 --- a/src/Savvyio.Queries/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Queries/SavvyioOptionsExtensions.cs @@ -1,30 +1,29 @@ -namespace Savvyio.Queries +namespace Savvyio.Queries; + +/// +/// Extension methods for the class. +/// +public static class SavvyioOptionsExtensions { /// - /// Extension methods for the class. + /// Adds an implementation of the interface to (if not already registered). /// - public static class SavvyioOptionsExtensions + /// The type that implements the interface. + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddQueryHandler(this SavvyioOptions options) where TImplementation : class, IQueryHandler { - /// - /// Adds an implementation of the interface to (if not already registered). - /// - /// The type that implements the interface. - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddQueryHandler(this SavvyioOptions options) where TImplementation : class, IQueryHandler - { - options.AddHandler(); - return options; - } + options.AddHandler(); + return options; + } - /// - /// Adds a default implementation of the interface. - /// - /// The to extend. - /// A reference to so that additional configuration calls can be chained. - public static SavvyioOptions AddQueryDispatcher(this SavvyioOptions options) - { - return options.AddDispatcher(); - } + /// + /// Adds a default implementation of the interface. + /// + /// The to extend. + /// A reference to so that additional configuration calls can be chained. + public static SavvyioOptions AddQueryDispatcher(this SavvyioOptions options) + { + return options.AddDispatcher(); } } diff --git a/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs b/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs index d95004d6..306d7351 100644 --- a/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs +++ b/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs @@ -1,35 +1,34 @@ using System.Data; using Dapper; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public static class DbConnectionExtensions { - public static class DbConnectionExtensions + public static IDbConnection SetDefaults(this IDbConnection cnn) { - public static IDbConnection SetDefaults(this IDbConnection cnn) - { - SqlMapper.AddTypeHandler(new GuidHandler()); - cnn.Open(); - return cnn; - } + SqlMapper.AddTypeHandler(new GuidHandler()); + cnn.Open(); + return cnn; + } - public static IDbConnection AddAccountTable(this IDbConnection cnn) - { - cnn.ExecuteAsync("CREATE TABLE AccountProjection (Id INTEGER PRIMARY KEY, FullName VARCHAR(255), EmailAddress VARCHAR(512))"); - return cnn; - } + public static IDbConnection AddAccountTable(this IDbConnection cnn) + { + cnn.ExecuteAsync("CREATE TABLE AccountProjection (Id INTEGER PRIMARY KEY, FullName VARCHAR(255), EmailAddress VARCHAR(512))"); + return cnn; + } - public static IDbConnection AddPlatformProviderTable(this IDbConnection cnn) - { - cnn.ExecuteAsync("CREATE TABLE PlatformProviderProjection (Id CHAR(36) PRIMARY KEY, Name VARCHAR(255), ThirdLevelDomainName VARCHAR(128), Description VARCHAR(512), " + - "MinimumPasswordLength INTEGER, " + - "EnforcePasswordHistory INTEGER, " + - "MinimumPasswordAge INTEGER, " + - "MaximumPasswordAge INTEGER, " + - "AccountLockoutThreshold INTEGER, " + - "AccountLockoutDuration INTEGER, " + - "AccountLockoutCounterReset INTEGER, " + - "PasswordComplexityRequirement INTEGER"); - return cnn; - } + public static IDbConnection AddPlatformProviderTable(this IDbConnection cnn) + { + cnn.ExecuteAsync("CREATE TABLE PlatformProviderProjection (Id CHAR(36) PRIMARY KEY, Name VARCHAR(255), ThirdLevelDomainName VARCHAR(128), Description VARCHAR(512), " + + "MinimumPasswordLength INTEGER, " + + "EnforcePasswordHistory INTEGER, " + + "MinimumPasswordAge INTEGER, " + + "MaximumPasswordAge INTEGER, " + + "AccountLockoutThreshold INTEGER, " + + "AccountLockoutDuration INTEGER, " + + "AccountLockoutCounterReset INTEGER, " + + "PasswordComplexityRequirement INTEGER"); + return cnn; } } diff --git a/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs b/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs index 2fcb243e..dfaca7c1 100644 --- a/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs +++ b/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs @@ -2,12 +2,11 @@ using System.Data; using Dapper; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class GuidHandler : SqlMapper.TypeHandler { - public class GuidHandler : SqlMapper.TypeHandler - { - public override void SetValue(IDbDataParameter parameter, Guid value) => parameter.Value = value; + public override void SetValue(IDbDataParameter parameter, Guid value) => parameter.Value = value; - public override Guid Parse(object value) => Guid.Parse((string)value); - } + public override Guid Parse(object value) => Guid.Parse((string)value); } diff --git a/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs b/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs index 7dc8116b..c2389830 100644 --- a/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs +++ b/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs @@ -6,21 +6,20 @@ using Savvyio.Extensions.DependencyInjection.EFCore; using Savvyio.Extensions.DependencyInjection.EFCore.Domain; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class CustomEfCoreDataSource : EfCoreAggregateDataSource { - public class CustomEfCoreDataSource : EfCoreAggregateDataSource + public CustomEfCoreDataSource(IDomainEventDispatcher dispatcher) : base(dispatcher, new EfCoreDataSourceOptions() { - public CustomEfCoreDataSource(IDomainEventDispatcher dispatcher) : base(dispatcher, new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase(nameof(Account)).EnableDetailedErrors().LogTo(Console.WriteLine), - ModelConstructor = mb => - { - mb.AddAccount(); - } - }) + ContextConfigurator = b => b.UseInMemoryDatabase(nameof(Account)).EnableDetailedErrors().LogTo(Console.WriteLine), + ModelConstructor = mb => { + mb.AddAccount(); } - - public IPersistentRepository Account => new EfCoreAggregateRepository(this); + }) + { } + + public IPersistentRepository Account => new EfCoreAggregateRepository(this); } diff --git a/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs b/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs index 6369cb64..7485698a 100644 --- a/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs +++ b/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs @@ -2,15 +2,14 @@ using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ValueGeneration; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class LongValueGenerator : ValueGenerator { - public class LongValueGenerator : ValueGenerator + public override long Next(EntityEntry entry) { - public override long Next(EntityEntry entry) - { - return Generate.RandomNumber(1, 100000); - } - - public override bool GeneratesTemporaryValues { get; } + return Generate.RandomNumber(1, 100000); } + + public override bool GeneratesTemporaryValues { get; } } diff --git a/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs b/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs index 732bc890..831a54c5 100644 --- a/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs +++ b/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs @@ -2,56 +2,55 @@ using Newtonsoft.Json; using Savvyio.Assets.Domain; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public static class ModelBuilderExtensions { - public static class ModelBuilderExtensions + public static ModelBuilder AddAccount(this ModelBuilder mb) { - public static ModelBuilder AddAccount(this ModelBuilder mb) + return mb.Entity(entity => { - return mb.Entity(entity => - { - entity.ToTable(nameof(Account)); - entity.HasKey(x => new { x.Id }); - entity.Property(x => x.Id) - .HasColumnName("id") - .HasValueGenerator() - .ValueGeneratedOnAdd(); - entity.Property(x => x.PlatformProviderId) - .HasColumnName("platformProviderId") - .HasColumnType("uniqueidentifier"); - entity.Property(x => x.EmailAddress) - .HasColumnName("emailAddress") - .HasColumnType("varchar(256)"); - entity.Property(x => x.FullName) - .HasColumnName("fullName") - .HasColumnType("varchar(256)"); - entity.Property(x => x.Metadata) - .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); - }); - } + entity.ToTable(nameof(Account)); + entity.HasKey(x => new { x.Id }); + entity.Property(x => x.Id) + .HasColumnName("id") + .HasValueGenerator() + .ValueGeneratedOnAdd(); + entity.Property(x => x.PlatformProviderId) + .HasColumnName("platformProviderId") + .HasColumnType("uniqueidentifier"); + entity.Property(x => x.EmailAddress) + .HasColumnName("emailAddress") + .HasColumnType("varchar(256)"); + entity.Property(x => x.FullName) + .HasColumnName("fullName") + .HasColumnType("varchar(256)"); + entity.Property(x => x.Metadata) + .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); + }); + } - public static ModelBuilder AddPlatformProvider(this ModelBuilder mb) + public static ModelBuilder AddPlatformProvider(this ModelBuilder mb) + { + return mb.Entity(entity => { - return mb.Entity(entity => - { - entity.ToTable(nameof(PlatformProvider)); - entity.HasKey(x => new { x.Id }); - entity.Property(x => x.Id) - .HasColumnName("id"); - entity.Property(x => x.Policy) - .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); - entity.Property(x => x.Name) - .HasColumnName("name") - .HasColumnType("varchar(256)"); - entity.Property(x => x.ThirdLevelDomainName) - .HasColumnName("thirdLevelDomainName") - .HasColumnType("varchar(256)"); - entity.Property(x => x.Description) - .HasColumnName("description") - .HasColumnType("varchar(256)"); - entity.Property(x => x.Metadata) - .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); - }); - } + entity.ToTable(nameof(PlatformProvider)); + entity.HasKey(x => new { x.Id }); + entity.Property(x => x.Id) + .HasColumnName("id"); + entity.Property(x => x.Policy) + .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); + entity.Property(x => x.Name) + .HasColumnName("name") + .HasColumnType("varchar(256)"); + entity.Property(x => x.ThirdLevelDomainName) + .HasColumnName("thirdLevelDomainName") + .HasColumnType("varchar(256)"); + entity.Property(x => x.Description) + .HasColumnName("description") + .HasColumnType("varchar(256)"); + entity.Property(x => x.Metadata) + .HasConversion(ap => JsonConvert.SerializeObject(ap), ap => JsonConvert.DeserializeObject(ap)); + }); } } diff --git a/test/Savvyio.Assets.Tests/AccountCommandHandler.cs b/test/Savvyio.Assets.Tests/AccountCommandHandler.cs index bad4819b..e6ec7f41 100644 --- a/test/Savvyio.Assets.Tests/AccountCommandHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountCommandHandler.cs @@ -8,53 +8,52 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Handlers; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class AccountCommandHandler : CommandHandler { - public class AccountCommandHandler : CommandHandler + private readonly IMediator _mediator; + private readonly IUnitOfWork _uow; + private readonly IPersistentRepository _accountRepository; + + public AccountCommandHandler(IMediator mediator = null, IUnitOfWork uow = null, IPersistentRepository accountRepository = null) { - private readonly IMediator _mediator; - private readonly IUnitOfWork _uow; - private readonly IPersistentRepository _accountRepository; + _mediator = mediator; + _uow = uow; + _accountRepository = accountRepository; + } - public AccountCommandHandler(IMediator mediator = null, IUnitOfWork uow = null, IPersistentRepository accountRepository = null) + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.RegisterAsync(CreateAccountAsync); + handlers.RegisterAsync(async c => { - _mediator = mediator; - _uow = uow; - _accountRepository = accountRepository; - } + var account = new Account(c.Id); + account.ChangeFullName(c.FullName); + account.ChangeEmailAddress(c.EmailAddress); + _accountRepository?.Add(account); // store in db + await _uow.SaveChangesAsync(); + await _mediator.PublishAsync(new AccountUpdated(account.Id, account.FullName, account.EmailAddress)); // raise integration event + }); + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) + public async Task CreateAccountAsync(CreateAccount c) + { + var account = new Account(c.PlatformProviderId, c.FullName, c.EmailAddress).MergeMetadata(c); + + // check unique email + // through domain event - look at OnInProcAccountInitiated in Savvyio.Assets.Domain.Handlers.AccountDomainEventHandler + try { - handlers.RegisterAsync(CreateAccountAsync); - handlers.RegisterAsync(async c => - { - var account = new Account(c.Id); - account.ChangeFullName(c.FullName); - account.ChangeEmailAddress(c.EmailAddress); - _accountRepository?.Add(account); // store in db - await _uow.SaveChangesAsync(); - await _mediator.PublishAsync(new AccountUpdated(account.Id, account.FullName, account.EmailAddress)); // raise integration event - }); + _accountRepository.Add(account); + await _uow.SaveChangesAsync(); // store in db } - - public async Task CreateAccountAsync(CreateAccount c) + catch (Exception) { - var account = new Account(c.PlatformProviderId, c.FullName, c.EmailAddress).MergeMetadata(c); - - // check unique email - // through domain event - look at OnInProcAccountInitiated in Savvyio.Assets.Domain.Handlers.AccountDomainEventHandler - try - { - _accountRepository.Add(account); - await _uow.SaveChangesAsync(); // store in db - } - catch (Exception) - { - _accountRepository.Remove(account); // undo add - throw; - } - - await _mediator.PublishAsync(new AccountCreated(account.Id, account.FullName, account.EmailAddress).MergeMetadata(account)); // raise integration event + _accountRepository.Remove(account); // undo add + throw; } + + await _mediator.PublishAsync(new AccountCreated(account.Id, account.FullName, account.EmailAddress).MergeMetadata(account)); // raise integration event } } diff --git a/test/Savvyio.Assets.Tests/AccountEventHandler.cs b/test/Savvyio.Assets.Tests/AccountEventHandler.cs index c0e0dd45..97685c09 100644 --- a/test/Savvyio.Assets.Tests/AccountEventHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountEventHandler.cs @@ -12,51 +12,50 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class AccountEventHandler : IntegrationEventHandler { - public class AccountEventHandler : IntegrationEventHandler + private readonly ITestOutputHelper _output; + private readonly ITestStore _testStore; + private readonly IPersistentDataStore _platformProviderDao; + private readonly IPersistentDataStore _accountDao; + private readonly IPublisher _eventBus; + + public AccountEventHandler(ITestOutputHelper output = null, ITestStore testStore = null, IPersistentDataStore accountDao = null, IPersistentDataStore platformProviderDao = null, IPublisher eventBus = null) { - private readonly ITestOutputHelper _output; - private readonly ITestStore _testStore; - private readonly IPersistentDataStore _platformProviderDao; - private readonly IPersistentDataStore _accountDao; - private readonly IPublisher _eventBus; + _output = output; + _testStore = testStore; + _accountDao = accountDao; + _platformProviderDao = platformProviderDao; + _eventBus = eventBus; + } - public AccountEventHandler(ITestOutputHelper output = null, ITestStore testStore = null, IPersistentDataStore accountDao = null, IPersistentDataStore platformProviderDao = null, IPublisher eventBus = null) - { - _output = output; - _testStore = testStore; - _accountDao = accountDao; - _platformProviderDao = platformProviderDao; - _eventBus = eventBus; - } + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.RegisterAsync(OnOutProcAccountCreated); + handlers.RegisterAsync(OnOutProcAccountUpdated); + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.RegisterAsync(OnOutProcAccountCreated); - handlers.RegisterAsync(OnOutProcAccountUpdated); - } + private Task OnOutProcAccountUpdated(AccountUpdated e) + { + _testStore?.Add(e); + _eventBus?.PublishAsync(e.ToMessage("urn:event:account-updated".ToSnsUri(), nameof(AccountUpdated))); + _output?.WriteLines($"IE {nameof(OnOutProcAccountUpdated)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private Task OnOutProcAccountUpdated(AccountUpdated e) + public async Task OnOutProcAccountCreated(AccountCreated e) + { + _testStore?.Add(e); + if (_eventBus != null) { - _testStore?.Add(e); - _eventBus?.PublishAsync(e.ToMessage("urn:event:account-updated".ToSnsUri(), nameof(AccountUpdated))); - _output?.WriteLines($"IE {nameof(OnOutProcAccountUpdated)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; + await _eventBus.PublishAsync(e.ToMessage("account-created-flow-test.fifo".ToSnsUri(), nameof(AccountCreated))).ConfigureAwait(false); } - - public async Task OnOutProcAccountCreated(AccountCreated e) + _output?.WriteLines($"IE {nameof(OnOutProcAccountCreated)}", JsonSerializer.Serialize(e)); + if (_accountDao != null) { - _testStore?.Add(e); - if (_eventBus != null) - { - await _eventBus.PublishAsync(e.ToMessage("account-created-flow-test.fifo".ToSnsUri(), nameof(AccountCreated))).ConfigureAwait(false); - } - _output?.WriteLines($"IE {nameof(OnOutProcAccountCreated)}", JsonSerializer.Serialize(e)); - if (_accountDao != null) - { - await _accountDao.CreateAsync(new AccountProjection(e.Id, e.FullName, e.EmailAddress)).ConfigureAwait(false); - } + await _accountDao.CreateAsync(new AccountProjection(e.Id, e.FullName, e.EmailAddress)).ConfigureAwait(false); } } } diff --git a/test/Savvyio.Assets.Tests/AccountQueryHandler.cs b/test/Savvyio.Assets.Tests/AccountQueryHandler.cs index 653dc12e..e6f21098 100644 --- a/test/Savvyio.Assets.Tests/AccountQueryHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountQueryHandler.cs @@ -6,35 +6,34 @@ using Savvyio.Handlers; using Savvyio.Queries; -namespace Savvyio.Assets -{ - public class AccountQueryHandler : QueryHandler - { - private readonly IReadableDataStore _accountDao; +namespace Savvyio.Assets; - public AccountQueryHandler(IReadableDataStore accountDao = null) - { - _accountDao = accountDao; - } +public class AccountQueryHandler : QueryHandler +{ + private readonly IReadableDataStore _accountDao; - protected override void RegisterDelegates(IRequestReplyRegistry handlers) - { - handlers.RegisterAsync(GetAccountAsync); - handlers.RegisterAsync(s => Task.FromResult(new AccountProjection(222, "A", "B"))); - handlers.RegisterAsync(GetFakeAccountAsync); - handlers.RegisterAsync(_ => Task.FromResult(new AccountCreated(222, "A", "B"))); - } + public AccountQueryHandler(IReadableDataStore accountDao = null) + { + _accountDao = accountDao; + } - private Task GetFakeAccountAsync(GetFakeAccount a) - { - return Task.FromResult(new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where")); - } + protected override void RegisterDelegates(IRequestReplyRegistry handlers) + { + handlers.RegisterAsync(GetAccountAsync); + handlers.RegisterAsync(s => Task.FromResult(new AccountProjection(222, "A", "B"))); + handlers.RegisterAsync(GetFakeAccountAsync); + handlers.RegisterAsync(_ => Task.FromResult(new AccountCreated(222, "A", "B"))); + } - private async Task GetAccountAsync(GetAccount arg1) - { - var dao = await _accountDao.GetByIdAsync(arg1.Id); - return dao; - } + private Task GetFakeAccountAsync(GetFakeAccount a) + { + return Task.FromResult(new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where")); + } + private async Task GetAccountAsync(GetAccount arg1) + { + var dao = await _accountDao.GetByIdAsync(arg1.Id); + return dao; } + } diff --git a/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs b/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs index ce3fbf5a..424906d6 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs @@ -2,21 +2,20 @@ using Savvyio.Assets.Domain; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record CreateAccount : Command { - public record CreateAccount : Command + public CreateAccount(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) { - public CreateAccount(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) - { - PlatformProviderId = platformProviderId; - FullName = fullName; - EmailAddress = emailAddress; - } + PlatformProviderId = platformProviderId; + FullName = fullName; + EmailAddress = emailAddress; + } - public Guid PlatformProviderId { get; } + public Guid PlatformProviderId { get; } - public string FullName { get; } + public string FullName { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs b/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs index b2ac8907..62e71f3e 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs @@ -1,21 +1,20 @@ using Savvyio.Assets.Domain; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record CreateAccountWithValueObjects : Command { - public record CreateAccountWithValueObjects : Command + public CreateAccountWithValueObjects(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) { - public CreateAccountWithValueObjects(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) - { - PlatformProviderId = platformProviderId; - FullName = fullName; - EmailAddress = emailAddress; - } + PlatformProviderId = platformProviderId; + FullName = fullName; + EmailAddress = emailAddress; + } - public PlatformProviderId PlatformProviderId { get; } + public PlatformProviderId PlatformProviderId { get; } - public FullName FullName { get; } + public FullName FullName { get; } - public EmailAddress EmailAddress { get; } - } + public EmailAddress EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs b/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs index f7fd1dcc..1d39bfe9 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs @@ -1,20 +1,19 @@ using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record CreateMemberCommand : Command { - public record CreateMemberCommand : Command + public CreateMemberCommand(string name, byte age, string emailAddress) { - public CreateMemberCommand(string name, byte age, string emailAddress) - { - Name = name; - Age = age; - EmailAddress = emailAddress; - } + Name = name; + Age = age; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public byte Age { get; } + public byte Age { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs b/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs index a4a6b922..da6d1a11 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs @@ -1,21 +1,20 @@ using Savvyio.Assets.Domain; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record CreatePlatformProvider : Command { - public record CreatePlatformProvider : Command + public CreatePlatformProvider(Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) { - public CreatePlatformProvider(Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) - { - Name = name; - ThirdLevelDomainName = thirdLevelDomainName; - Description = description; - } + Name = name; + ThirdLevelDomainName = thirdLevelDomainName; + Description = description; + } - public string Name { get; } + public string Name { get; } - public string ThirdLevelDomainName { get; } + public string ThirdLevelDomainName { get; } - public string Description { get; } - } + public string Description { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs b/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs index 413b2afc..730de9ab 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs @@ -1,21 +1,20 @@ using Savvyio.Assets.Domain; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record UpdateAccount : Command { - public record UpdateAccount : Command + public UpdateAccount(AccountId id, FullName fullName, EmailAddress emailAddress) { - public UpdateAccount(AccountId id, FullName fullName, EmailAddress emailAddress) - { - Id = id; - FullName = fullName; - EmailAddress = emailAddress; - } + Id = id; + FullName = fullName; + EmailAddress = emailAddress; + } - public long Id { get; } + public long Id { get; } - public string FullName { get; } + public string FullName { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs index 01fdb000..4476e303 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs @@ -2,24 +2,23 @@ using Savvyio.Assets.Domain; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record UpdatePlatformProvider : Command { - public record UpdatePlatformProvider : Command + public UpdatePlatformProvider(PlatformProviderId id, Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) { - public UpdatePlatformProvider(PlatformProviderId id, Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) - { - Id = id; - Name = name; - ThirdLevelDomainName = thirdLevelDomainName; - Description = description; - } + Id = id; + Name = name; + ThirdLevelDomainName = thirdLevelDomainName; + Description = description; + } - public Guid Id { get; } + public Guid Id { get; } - public string Name { get; } + public string Name { get; } - public string ThirdLevelDomainName { get; } + public string ThirdLevelDomainName { get; } - public string Description { get; } - } + public string Description { get; } } diff --git a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs index d541f04f..f0bcdb74 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs @@ -1,39 +1,38 @@ using System; using Savvyio.Commands; -namespace Savvyio.Assets.Commands +namespace Savvyio.Assets.Commands; + +public record UpdatePlatformProviderAccountPolicy : Command { - public record UpdatePlatformProviderAccountPolicy : Command + public UpdatePlatformProviderAccountPolicy(Guid id, int minimumPasswordLength, int enforcePasswordHistory, TimeSpan minimumPasswordAge, TimeSpan maximumPasswordAge, int accountLockoutThreshold, TimeSpan accountLockoutDuration, TimeSpan accountLockoutCounterReset, bool passwordComplexityRequirement) { - public UpdatePlatformProviderAccountPolicy(Guid id, int minimumPasswordLength, int enforcePasswordHistory, TimeSpan minimumPasswordAge, TimeSpan maximumPasswordAge, int accountLockoutThreshold, TimeSpan accountLockoutDuration, TimeSpan accountLockoutCounterReset, bool passwordComplexityRequirement) - { - Id = id; - MinimumPasswordLength = minimumPasswordLength; - EnforcePasswordHistory = enforcePasswordHistory; - MinimumPasswordAge = minimumPasswordAge; - MaximumPasswordAge = maximumPasswordAge; - AccountLockoutThreshold = accountLockoutThreshold; - AccountLockoutDuration = accountLockoutDuration; - AccountLockoutCounterReset = accountLockoutCounterReset; - PasswordComplexityRequirement = passwordComplexityRequirement; - } + Id = id; + MinimumPasswordLength = minimumPasswordLength; + EnforcePasswordHistory = enforcePasswordHistory; + MinimumPasswordAge = minimumPasswordAge; + MaximumPasswordAge = maximumPasswordAge; + AccountLockoutThreshold = accountLockoutThreshold; + AccountLockoutDuration = accountLockoutDuration; + AccountLockoutCounterReset = accountLockoutCounterReset; + PasswordComplexityRequirement = passwordComplexityRequirement; + } - public Guid Id { get; } + public Guid Id { get; } - public int MinimumPasswordLength { get; } + public int MinimumPasswordLength { get; } - public int EnforcePasswordHistory { get; } + public int EnforcePasswordHistory { get; } - public TimeSpan MinimumPasswordAge { get; } + public TimeSpan MinimumPasswordAge { get; } - public TimeSpan MaximumPasswordAge { get; } + public TimeSpan MaximumPasswordAge { get; } - public int AccountLockoutThreshold { get; } + public int AccountLockoutThreshold { get; } - public TimeSpan AccountLockoutDuration { get; } + public TimeSpan AccountLockoutDuration { get; } - public TimeSpan AccountLockoutCounterReset { get; } + public TimeSpan AccountLockoutCounterReset { get; } - public bool PasswordComplexityRequirement { get; } - } + public bool PasswordComplexityRequirement { get; } } diff --git a/test/Savvyio.Assets.Tests/DbMarker.cs b/test/Savvyio.Assets.Tests/DbMarker.cs index ef6a69c7..1acf7748 100644 --- a/test/Savvyio.Assets.Tests/DbMarker.cs +++ b/test/Savvyio.Assets.Tests/DbMarker.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public struct DbMarker { - public struct DbMarker - { - } +} - public struct AnotherDbMarker - { - } +public struct AnotherDbMarker +{ } diff --git a/test/Savvyio.Assets.Tests/Domain/Account.cs b/test/Savvyio.Assets.Tests/Domain/Account.cs index e40817fe..6312cb33 100644 --- a/test/Savvyio.Assets.Tests/Domain/Account.cs +++ b/test/Savvyio.Assets.Tests/Domain/Account.cs @@ -3,76 +3,75 @@ using Savvyio.Assets.Domain.Events; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public class Account : AggregateRoot { - public class Account : AggregateRoot + Account() // efcore { - Account() // efcore - { - } + } - public Account(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) - { - Validator.ThrowIfNull(platformProviderId, nameof(platformProviderId)); - Validator.ThrowIfNull(fullName, nameof(fullName)); - Validator.ThrowIfNull(emailAddress, nameof(emailAddress)); - PlatformProviderId = platformProviderId; - FullName = fullName; - EmailAddress = emailAddress; - AddEvent(new AccountInitiated(this)); - } + public Account(PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) + { + Validator.ThrowIfNull(platformProviderId, nameof(platformProviderId)); + Validator.ThrowIfNull(fullName, nameof(fullName)); + Validator.ThrowIfNull(emailAddress, nameof(emailAddress)); + PlatformProviderId = platformProviderId; + FullName = fullName; + EmailAddress = emailAddress; + AddEvent(new AccountInitiated(this)); + } - public Account(AccountId id) : base(id) - { - } + public Account(AccountId id) : base(id) + { + } - public Guid PlatformProviderId { get; private set; } + public Guid PlatformProviderId { get; private set; } - public string FullName { get; private set; } + public string FullName { get; private set; } - public string EmailAddress { get; private set; } + public string EmailAddress { get; private set; } - public void ChangeFullName(FullName fullName) - { - Validator.ThrowIfNull(fullName, nameof(fullName)); - if (fullName.Equals((FullName)FullName)) { return; } - FullName = fullName; - AddEvent(new AccountFullNameChanged(this)); - } + public void ChangeFullName(FullName fullName) + { + Validator.ThrowIfNull(fullName, nameof(fullName)); + if (fullName.Equals((FullName)FullName)) { return; } + FullName = fullName; + AddEvent(new AccountFullNameChanged(this)); + } - public void ChangeEmailAddress(EmailAddress emailAddress) - { - Validator.ThrowIfNull(emailAddress, nameof(emailAddress)); - if (emailAddress.Equals((EmailAddress)EmailAddress)) { return; } - EmailAddress = emailAddress; - AddEvent(new AccountEmailAddressChanged(this)); - } + public void ChangeEmailAddress(EmailAddress emailAddress) + { + Validator.ThrowIfNull(emailAddress, nameof(emailAddress)); + if (emailAddress.Equals((EmailAddress)EmailAddress)) { return; } + EmailAddress = emailAddress; + AddEvent(new AccountEmailAddressChanged(this)); + } - public void Promote(Credentials credentials) - { - Validator.ThrowIfNull(credentials, nameof(credentials)); - var identity = new UserAccount(Id, credentials.UserName); - AddEvent(new UserAccountInitiated(identity)); - ChangePassword(credentials); - } + public void Promote(Credentials credentials) + { + Validator.ThrowIfNull(credentials, nameof(credentials)); + var identity = new UserAccount(Id, credentials.UserName); + AddEvent(new UserAccountInitiated(identity)); + ChangePassword(credentials); + } - public void ChangePassword(Credentials credentials) - { - Validator.ThrowIfNull(credentials, nameof(credentials)); - var password = new UserAccountPassword(Id, credentials); - AddEvent(new UserAccountPasswordInitiated(password)); - } + public void ChangePassword(Credentials credentials) + { + Validator.ThrowIfNull(credentials, nameof(credentials)); + var password = new UserAccountPassword(Id, credentials); + AddEvent(new UserAccountPasswordInitiated(password)); + } - public void RegisterFailedLogonAttempt(string userHostAddress) - { - Validator.ThrowIfNullOrWhitespace(userHostAddress); - var failedLogonAttempt = new UserAccountFailedLogonAttempt(Id, userHostAddress); - AddEvent(new UserAccountFailedLogonAttemptCreated(failedLogonAttempt)); - } + public void RegisterFailedLogonAttempt(string userHostAddress) + { + Validator.ThrowIfNullOrWhitespace(userHostAddress); + var failedLogonAttempt = new UserAccountFailedLogonAttempt(Id, userHostAddress); + AddEvent(new UserAccountFailedLogonAttemptCreated(failedLogonAttempt)); + } - public void Demote() - { - AddEvent(new UserAccountRemoved(new UserAccount(Id))); - } + public void Demote() + { + AddEvent(new UserAccountRemoved(new UserAccount(Id))); } } diff --git a/test/Savvyio.Assets.Tests/Domain/AccountId.cs b/test/Savvyio.Assets.Tests/Domain/AccountId.cs index 2b6d34e9..d7b1751e 100644 --- a/test/Savvyio.Assets.Tests/Domain/AccountId.cs +++ b/test/Savvyio.Assets.Tests/Domain/AccountId.cs @@ -1,18 +1,17 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public sealed record AccountId : SingleValueObject { - public sealed record AccountId : SingleValueObject + public static implicit operator AccountId(long value) { - public static implicit operator AccountId(long value) - { - return new AccountId(value); - } + return new AccountId(value); + } - public AccountId(long id) : base(id) - { - Validator.ThrowIfLowerThanOrEqual(id, 0, nameof(id)); - } + public AccountId(long id) : base(id) + { + Validator.ThrowIfLowerThanOrEqual(id, 0, nameof(id)); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Coordinates.cs b/test/Savvyio.Assets.Tests/Domain/Coordinates.cs index 28e4a4d9..d6a42c0a 100644 --- a/test/Savvyio.Assets.Tests/Domain/Coordinates.cs +++ b/test/Savvyio.Assets.Tests/Domain/Coordinates.cs @@ -1,22 +1,21 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record Coordinates : ValueObject { - public record Coordinates : ValueObject + public Coordinates(double latitude, double longitude) { - public Coordinates(double latitude, double longitude) - { - Validator.ThrowIfLowerThan(latitude, -90, nameof(latitude)); - Validator.ThrowIfGreaterThan(latitude, 90, nameof(latitude)); - Validator.ThrowIfLowerThan(longitude, -180, nameof(longitude)); - Validator.ThrowIfGreaterThan(longitude, 180, nameof(longitude)); - Latitude = latitude; - Longitude = longitude; - } + Validator.ThrowIfLowerThan(latitude, -90, nameof(latitude)); + Validator.ThrowIfGreaterThan(latitude, 90, nameof(latitude)); + Validator.ThrowIfLowerThan(longitude, -180, nameof(longitude)); + Validator.ThrowIfGreaterThan(longitude, 180, nameof(longitude)); + Latitude = latitude; + Longitude = longitude; + } - public double Latitude { get; } + public double Latitude { get; } - public double Longitude { get; } - } + public double Longitude { get; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Credentials.cs b/test/Savvyio.Assets.Tests/Domain/Credentials.cs index 58a6d48c..cb6f459a 100644 --- a/test/Savvyio.Assets.Tests/Domain/Credentials.cs +++ b/test/Savvyio.Assets.Tests/Domain/Credentials.cs @@ -4,29 +4,28 @@ using Cuemon.Security.Cryptography; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record Credentials : ValueObject { - public record Credentials : ValueObject + public Credentials(string username, string password, string salt) { - public Credentials(string username, string password, string salt) - { - Validator.ThrowIfNullOrWhitespace(username); - Validator.ThrowIfNullOrWhitespace(password); - Validator.ThrowIfNullOrWhitespace(salt); - UserName = username; - Hash = KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(); - Salt = salt; - } + Validator.ThrowIfNullOrWhitespace(username); + Validator.ThrowIfNullOrWhitespace(password); + Validator.ThrowIfNullOrWhitespace(salt); + UserName = username; + Hash = KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(); + Salt = salt; + } - public string UserName { get; private set; } + public string UserName { get; private set; } - public string Hash { get; private set; } + public string Hash { get; private set; } - public string Salt { get; private set; } + public string Salt { get; private set; } - public override string ToString() - { - return DelimitedString.Create(Arguments.ToEnumerableOf(UserName, Hash), o => o.Delimiter = ":"); - } + public override string ToString() + { + return DelimitedString.Create(Arguments.ToEnumerableOf(UserName, Hash), o => o.Delimiter = ":"); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Description.cs b/test/Savvyio.Assets.Tests/Domain/Description.cs index 7cc5ca54..4ce954d9 100644 --- a/test/Savvyio.Assets.Tests/Domain/Description.cs +++ b/test/Savvyio.Assets.Tests/Domain/Description.cs @@ -1,21 +1,20 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record Description : SingleValueObject { - public record Description : SingleValueObject + public static implicit operator Description(string value) { - public static implicit operator Description(string value) - { - return new Description(value); - } + return new Description(value); + } - public Description(string value = null) : base(value) + public Description(string value = null) : base(value) + { + Validator.CheckParameter(value, () => { - Validator.CheckParameter(value, () => - { - if (value != null) { Validator.ThrowIfGreaterThan(value.Length, 1024, nameof(value)); } - }); - } + if (value != null) { Validator.ThrowIfGreaterThan(value.Length, 1024, nameof(value)); } + }); } } diff --git a/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs b/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs index 8dade1c0..00fbcd6e 100644 --- a/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs +++ b/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs @@ -1,19 +1,18 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record EmailAddress : SingleValueObject { - public record EmailAddress : SingleValueObject + public static implicit operator EmailAddress(string value) { - public static implicit operator EmailAddress(string value) - { - return new EmailAddress(value); - } + return new EmailAddress(value); + } - public EmailAddress(string value) : base(value) - { - Validator.ThrowIfNullOrWhitespace(value); - Validator.ThrowIfNotEmailAddress(value); - } + public EmailAddress(string value) : base(value) + { + Validator.ThrowIfNullOrWhitespace(value); + Validator.ThrowIfNotEmailAddress(value); } } diff --git a/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs b/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs index 4c1727f0..2dbe43a3 100644 --- a/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs +++ b/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs @@ -5,69 +5,68 @@ using Savvyio.Domain.EventSourcing; using Savvyio.Handlers; -namespace Savvyio.Assets.Domain.EventSourcing +namespace Savvyio.Assets.Domain.EventSourcing; + +public class TracedAccount : TracedAggregateRoot { - public class TracedAccount : TracedAggregateRoot + TracedAccount(Guid id, IEnumerable events) : this(new TracedAccountId(id), events) // EfCoreTracedAggregateRepository { - TracedAccount(Guid id, IEnumerable events) : this(new TracedAccountId(id), events) // EfCoreTracedAggregateRepository - { - } + } - public TracedAccount(TracedAccountId id, IEnumerable events) : base(id, events) - { - } + public TracedAccount(TracedAccountId id, IEnumerable events) : base(id, events) + { + } - public TracedAccount(TracedAccountId id, PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) - { - Validator.ThrowIfNull(platformProviderId); - Validator.ThrowIfNull(fullName); - Validator.ThrowIfNull(emailAddress); - AddEvent(new TracedAccountInitiated(id, platformProviderId, fullName, emailAddress)); - } + public TracedAccount(TracedAccountId id, PlatformProviderId platformProviderId, FullName fullName, EmailAddress emailAddress) + { + Validator.ThrowIfNull(platformProviderId); + Validator.ThrowIfNull(fullName); + Validator.ThrowIfNull(emailAddress); + AddEvent(new TracedAccountInitiated(id, platformProviderId, fullName, emailAddress)); + } - protected override void RegisterDelegates(IFireForgetRegistry handler) - { - handler.Register(OnInitiated); - handler.Register(OnChangeFullName); - handler.Register(OnEmailChanged); - } + protected override void RegisterDelegates(IFireForgetRegistry handler) + { + handler.Register(OnInitiated); + handler.Register(OnChangeFullName); + handler.Register(OnEmailChanged); + } - private void OnInitiated(TracedAccountInitiated e) - { - Id = e.Id; - PlatformProviderId = e.PlatformProviderId; - FullName = e.FullName; - EmailAddress = e.EmailAddress; - } + private void OnInitiated(TracedAccountInitiated e) + { + Id = e.Id; + PlatformProviderId = e.PlatformProviderId; + FullName = e.FullName; + EmailAddress = e.EmailAddress; + } - private void OnChangeFullName(TracedAccountFullNameChanged e) - { - FullName = e.FullName; - } + private void OnChangeFullName(TracedAccountFullNameChanged e) + { + FullName = e.FullName; + } - private void OnEmailChanged(TracedAccountEmailAddressChanged e) - { - EmailAddress = e.EmailAddress; - } + private void OnEmailChanged(TracedAccountEmailAddressChanged e) + { + EmailAddress = e.EmailAddress; + } - public Guid PlatformProviderId { get; private set; } + public Guid PlatformProviderId { get; private set; } - public string FullName { get; private set; } + public string FullName { get; private set; } - public string EmailAddress { get; private set; } + public string EmailAddress { get; private set; } - public void ChangeFullName(FullName fullName) - { - Validator.ThrowIfNull(fullName); - if (fullName.Equals((FullName)FullName)) { return; } - AddEvent(new TracedAccountFullNameChanged(fullName)); - } + public void ChangeFullName(FullName fullName) + { + Validator.ThrowIfNull(fullName); + if (fullName.Equals((FullName)FullName)) { return; } + AddEvent(new TracedAccountFullNameChanged(fullName)); + } - public void ChangeEmailAddress(EmailAddress emailAddress) - { - Validator.ThrowIfNull(emailAddress); - if (emailAddress.Equals((EmailAddress)EmailAddress)) { return; } - AddEvent(new TracedAccountEmailAddressChanged(emailAddress)); - } + public void ChangeEmailAddress(EmailAddress emailAddress) + { + Validator.ThrowIfNull(emailAddress); + if (emailAddress.Equals((EmailAddress)EmailAddress)) { return; } + AddEvent(new TracedAccountEmailAddressChanged(emailAddress)); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs index 755b0534..47e894a7 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs @@ -1,14 +1,13 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record AccountEmailAddressChanged : DomainEvent { - public record AccountEmailAddressChanged : DomainEvent + public AccountEmailAddressChanged(Account account) { - public AccountEmailAddressChanged(Account account) - { - EmailAddress = account.EmailAddress; - } - - public string EmailAddress { get; private set; } + EmailAddress = account.EmailAddress; } + + public string EmailAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs index b77c7b67..17562745 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs @@ -1,14 +1,13 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record AccountFullNameChanged : DomainEvent { - public record AccountFullNameChanged : DomainEvent + public AccountFullNameChanged(Account account) { - public AccountFullNameChanged(Account account) - { - FullName = account.FullName; - } - - public string FullName { get; private set; } + FullName = account.FullName; } + + public string FullName { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs index 654194f8..ad9553d2 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs @@ -1,25 +1,24 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record AccountInitiated : DomainEvent { - public record AccountInitiated : DomainEvent + public AccountInitiated() { - public AccountInitiated() - { - } + } - public AccountInitiated(Account account) - { - PlatformProviderId = account.PlatformProviderId; - FullName = account.FullName; - EmailAddress = account.EmailAddress; - } + public AccountInitiated(Account account) + { + PlatformProviderId = account.PlatformProviderId; + FullName = account.FullName; + EmailAddress = account.EmailAddress; + } - public Guid PlatformProviderId { get; private set; } + public Guid PlatformProviderId { get; private set; } - public string FullName { get; private set; } + public string FullName { get; private set; } - public string EmailAddress { get; private set; } - } + public string EmailAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs index f2ff7ac9..53fce971 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs @@ -1,11 +1,10 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record AccountInitiatedChained : DomainEvent { - public record AccountInitiatedChained : DomainEvent + public AccountInitiatedChained() { - public AccountInitiatedChained() - { - } } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs index 8ddd84f9..e82bc579 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs @@ -1,24 +1,23 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record PlatformProviderAccountPolicyChanged : DomainEvent { - public record PlatformProviderAccountPolicyChanged : DomainEvent + PlatformProviderAccountPolicyChanged() { - PlatformProviderAccountPolicyChanged() - { - } + } - public PlatformProviderAccountPolicyChanged(PlatformProvider provider) - { - Id = provider.Id; - Policy = provider.Policy; - } + public PlatformProviderAccountPolicyChanged(PlatformProvider provider) + { + Id = provider.Id; + Policy = provider.Policy; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public PlatformProviderAccountPolicy Policy { get; private set; } - } + public PlatformProviderAccountPolicy Policy { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs index 71d96d03..927d6ba7 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs @@ -1,22 +1,21 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record PlatformProviderDescriptionChanged : DomainEvent { - public record PlatformProviderDescriptionChanged : DomainEvent + PlatformProviderDescriptionChanged() { - PlatformProviderDescriptionChanged() - { - } + } - public PlatformProviderDescriptionChanged(PlatformProvider provider) - { - Id = provider.Id; - Description = provider.Description; - } + public PlatformProviderDescriptionChanged(PlatformProvider provider) + { + Id = provider.Id; + Description = provider.Description; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string Description { get; private set; } - } + public string Description { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs index f03dce9f..3c19d646 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs @@ -1,31 +1,30 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record PlatformProviderInitiated : DomainEvent { - public record PlatformProviderInitiated : DomainEvent + PlatformProviderInitiated() { - PlatformProviderInitiated() - { - } + } - public PlatformProviderInitiated(PlatformProvider provider) - { - Id = provider.Id; - Name = provider.Name; - ThirdLevelDomainName = provider.ThirdLevelDomainName; - Description = provider.Description; - Policy = provider.Policy; - } + public PlatformProviderInitiated(PlatformProvider provider) + { + Id = provider.Id; + Name = provider.Name; + ThirdLevelDomainName = provider.ThirdLevelDomainName; + Description = provider.Description; + Policy = provider.Policy; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string Name { get; private set; } + public string Name { get; private set; } - public string ThirdLevelDomainName { get; private set; } + public string ThirdLevelDomainName { get; private set; } - public string Description { get; private set; } + public string Description { get; private set; } - public PlatformProviderAccountPolicy Policy { get; private set; } - } + public PlatformProviderAccountPolicy Policy { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs index 9898db89..1abd8e08 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs @@ -1,23 +1,22 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record PlatformProviderNameChanged : DomainEvent { - public record PlatformProviderNameChanged : DomainEvent + PlatformProviderNameChanged() { - PlatformProviderNameChanged() - { - } + } - public PlatformProviderNameChanged(PlatformProvider provider) - { - Id = provider.Id; - Name = provider.Name; - } + public PlatformProviderNameChanged(PlatformProvider provider) + { + Id = provider.Id; + Name = provider.Name; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string Name { get; private set; } - } + public string Name { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs index d03c47d8..0241b198 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs @@ -1,22 +1,21 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record PlatformProviderThirdLevelDomainNameChanged : DomainEvent { - public record PlatformProviderThirdLevelDomainNameChanged : DomainEvent + PlatformProviderThirdLevelDomainNameChanged() { - PlatformProviderThirdLevelDomainNameChanged() - { - } + } - public PlatformProviderThirdLevelDomainNameChanged(PlatformProvider provider) - { - Id = provider.Id; - ThirdLevelDomainName = provider.ThirdLevelDomainName; - } + public PlatformProviderThirdLevelDomainNameChanged(PlatformProvider provider) + { + Id = provider.Id; + ThirdLevelDomainName = provider.ThirdLevelDomainName; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string ThirdLevelDomainName { get; private set; } - } + public string ThirdLevelDomainName { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs index 54ce64da..2d99e6ec 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs @@ -1,14 +1,13 @@ using Savvyio.Domain.EventSourcing; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record TracedAccountEmailAddressChanged : TracedDomainEvent { - public record TracedAccountEmailAddressChanged : TracedDomainEvent + public TracedAccountEmailAddressChanged(string emailAddress) { - public TracedAccountEmailAddressChanged(string emailAddress) - { - EmailAddress = emailAddress; - } - - public string EmailAddress { get; private set; } + EmailAddress = emailAddress; } + + public string EmailAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs index cff09762..8fff4aac 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs @@ -1,14 +1,13 @@ using Savvyio.Domain.EventSourcing; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record TracedAccountFullNameChanged : TracedDomainEvent { - public record TracedAccountFullNameChanged : TracedDomainEvent + public TracedAccountFullNameChanged(string fullName) { - public TracedAccountFullNameChanged(string fullName) - { - FullName = fullName; - } - - public string FullName { get; private set; } + FullName = fullName; } + + public string FullName { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs index 641957fb..65ba4a5d 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs @@ -1,24 +1,23 @@ using System; using Savvyio.Domain.EventSourcing; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record TracedAccountInitiated : TracedDomainEvent { - public record TracedAccountInitiated : TracedDomainEvent + public TracedAccountInitiated(Guid id, Guid platformProviderId, string fullName, string emailAddress) { - public TracedAccountInitiated(Guid id, Guid platformProviderId, string fullName, string emailAddress) - { - Id = id; - PlatformProviderId = platformProviderId; - FullName = fullName; - EmailAddress = emailAddress; - } + Id = id; + PlatformProviderId = platformProviderId; + FullName = fullName; + EmailAddress = emailAddress; + } - public Guid Id { get; } + public Guid Id { get; } - public Guid PlatformProviderId { get; } + public Guid PlatformProviderId { get; } - public string FullName { get; } + public string FullName { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs index 1660c196..2fde30b1 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs @@ -1,21 +1,20 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record UserAccountFailedLogonAttemptCreated : DomainEvent { - public record UserAccountFailedLogonAttemptCreated : DomainEvent + public UserAccountFailedLogonAttemptCreated() { - public UserAccountFailedLogonAttemptCreated() - { - } + } - public UserAccountFailedLogonAttemptCreated(UserAccountFailedLogonAttempt failedLogonAttempt) - { - AccountId = failedLogonAttempt.AccountId; - UserHostAddress = failedLogonAttempt.UserHostAddress; - } + public UserAccountFailedLogonAttemptCreated(UserAccountFailedLogonAttempt failedLogonAttempt) + { + AccountId = failedLogonAttempt.AccountId; + UserHostAddress = failedLogonAttempt.UserHostAddress; + } - public long AccountId { get; private set; } + public long AccountId { get; private set; } - public string UserHostAddress { get; private set; } - } + public string UserHostAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs index 4f459dab..d2feb187 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs @@ -1,18 +1,17 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record UserAccountInitiated : DomainEvent { - public record UserAccountInitiated : DomainEvent + public UserAccountInitiated() { - public UserAccountInitiated() - { - } - - public UserAccountInitiated(UserAccount account) - { - UserName = account.UserName; - } + } - public string UserName { get; private set; } + public UserAccountInitiated(UserAccount account) + { + UserName = account.UserName; } + + public string UserName { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs index 7648034d..69837127 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs @@ -1,24 +1,23 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record UserAccountPasswordInitiated : DomainEvent { - public record UserAccountPasswordInitiated : DomainEvent + public UserAccountPasswordInitiated() { - public UserAccountPasswordInitiated() - { - } + } - public UserAccountPasswordInitiated(UserAccountPassword password) - { - AccountId = password.AccountId; - Hash = password.Hash; - Salt = password.Salt; - } + public UserAccountPasswordInitiated(UserAccountPassword password) + { + AccountId = password.AccountId; + Hash = password.Hash; + Salt = password.Salt; + } - public long AccountId { get; private set; } + public long AccountId { get; private set; } - public string Hash { get; private set; } + public string Hash { get; private set; } - public string Salt { get; private set; } - } + public string Salt { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs index 59c4a308..cbbbe15c 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs @@ -1,18 +1,17 @@ using Savvyio.Domain; -namespace Savvyio.Assets.Domain.Events +namespace Savvyio.Assets.Domain.Events; + +public record UserAccountRemoved : DomainEvent { - public record UserAccountRemoved : DomainEvent + public UserAccountRemoved() { - public UserAccountRemoved() - { - } - - public UserAccountRemoved(UserAccount account) - { - Id = account.Id; - } + } - public long Id { get; private set; } + public UserAccountRemoved(UserAccount account) + { + Id = account.Id; } + + public long Id { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/FullName.cs b/test/Savvyio.Assets.Tests/Domain/FullName.cs index a439f4dc..c8c53168 100644 --- a/test/Savvyio.Assets.Tests/Domain/FullName.cs +++ b/test/Savvyio.Assets.Tests/Domain/FullName.cs @@ -1,22 +1,21 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record FullName : SingleValueObject { - public record FullName : SingleValueObject + public static implicit operator FullName(string value) { - public static implicit operator FullName(string value) - { - return new FullName(value); - } + return new FullName(value); + } - public FullName(string firstName, string lastName) : this($"{firstName?.Trim()} {lastName?.Trim()}") - { - } + public FullName(string firstName, string lastName) : this($"{firstName?.Trim()} {lastName?.Trim()}") + { + } - public FullName(string value) : base(value) - { - Validator.ThrowIfNullOrWhitespace(value); - } + public FullName(string value) : base(value) + { + Validator.ThrowIfNullOrWhitespace(value); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs b/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs index 5eb3cf14..cc0d391a 100644 --- a/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs +++ b/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs @@ -10,84 +10,83 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.Assets.Domain.Handlers +namespace Savvyio.Assets.Domain.Handlers; + +public class AccountDomainEventHandler : DomainEventHandler { - public class AccountDomainEventHandler : DomainEventHandler - { - private readonly ITestOutputHelper _output; - private readonly ITestStore _testStore; - private readonly IDomainEventDispatcher _dispatcher; - private readonly ISearchableDataStore _accountDao; + private readonly ITestOutputHelper _output; + private readonly ITestStore _testStore; + private readonly IDomainEventDispatcher _dispatcher; + private readonly ISearchableDataStore _accountDao; - public AccountDomainEventHandler(ITestOutputHelper output = null, ITestStore testStore = null, IDomainEventDispatcher dispatcher = null, ISearchableDataStore accountDao = null) - { - _output = output; - _testStore = testStore; - _dispatcher = dispatcher; - _accountDao = accountDao; - } + public AccountDomainEventHandler(ITestOutputHelper output = null, ITestStore testStore = null, IDomainEventDispatcher dispatcher = null, ISearchableDataStore accountDao = null) + { + _output = output; + _testStore = testStore; + _dispatcher = dispatcher; + _accountDao = accountDao; + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.RegisterAsync(OnInProcAccountInitiated); - handlers.RegisterAsync(OnInProcAccountEmailAddressChanged); - handlers.RegisterAsync(OnInProcAccountFullNameChanged); - handlers.RegisterAsync(OnInProcAccountInitiatedChained); - handlers.RegisterAsync(OnInProcTracedAccountInitiated); - handlers.RegisterAsync(OnInProcTracedAccountEmailAddressChanged); - } + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.RegisterAsync(OnInProcAccountInitiated); + handlers.RegisterAsync(OnInProcAccountEmailAddressChanged); + handlers.RegisterAsync(OnInProcAccountFullNameChanged); + handlers.RegisterAsync(OnInProcAccountInitiatedChained); + handlers.RegisterAsync(OnInProcTracedAccountInitiated); + handlers.RegisterAsync(OnInProcTracedAccountEmailAddressChanged); + } - private Task OnInProcTracedAccountInitiated(TracedAccountInitiated e) - { - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcTracedAccountInitiated)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - } + private Task OnInProcTracedAccountInitiated(TracedAccountInitiated e) + { + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcTracedAccountInitiated)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private Task OnInProcTracedAccountEmailAddressChanged(TracedAccountEmailAddressChanged e) - { - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcTracedAccountEmailAddressChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - } + private Task OnInProcTracedAccountEmailAddressChanged(TracedAccountEmailAddressChanged e) + { + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcTracedAccountEmailAddressChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private Task OnInProcAccountInitiatedChained(AccountInitiatedChained e) - { - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcAccountInitiatedChained)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - } + private Task OnInProcAccountInitiatedChained(AccountInitiatedChained e) + { + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcAccountInitiatedChained)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private Task OnInProcAccountFullNameChanged(AccountFullNameChanged e) - { - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcAccountFullNameChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - } + private Task OnInProcAccountFullNameChanged(AccountFullNameChanged e) + { + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcAccountFullNameChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private Task OnInProcAccountEmailAddressChanged(AccountEmailAddressChanged e) - { - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcAccountEmailAddressChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - } + private Task OnInProcAccountEmailAddressChanged(AccountEmailAddressChanged e) + { + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcAccountEmailAddressChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + } - private async Task OnInProcAccountInitiated(AccountInitiated e) + private async Task OnInProcAccountInitiated(AccountInitiated e) + { + if (_accountDao != null) { - if (_accountDao != null) + var dao = await _accountDao.FindAllAsync(o => { - var dao = await _accountDao.FindAllAsync(o => - { - o.CommandText = "SELECT * FROM AccountProjection WHERE EmailAddress = @EmailAddress"; - o.Parameters = new { e.EmailAddress }; - }).SingleOrDefaultAsync().ConfigureAwait(false); + o.CommandText = "SELECT * FROM AccountProjection WHERE EmailAddress = @EmailAddress"; + o.Parameters = new { e.EmailAddress }; + }).SingleOrDefaultAsync().ConfigureAwait(false); - if (dao != null) { throw new ValidationException("Email address has already been registered."); } - } - - _testStore?.Add(e); - _output?.WriteLines($"DE {nameof(OnInProcAccountInitiated)}", JsonSerializer.Serialize(e)); - await _dispatcher.RaiseAsync(new AccountInitiatedChained().MergeMetadata(e).SetCausationId(e.GetEventId())).ConfigureAwait(false); + if (dao != null) { throw new ValidationException("Email address has already been registered."); } } + + _testStore?.Add(e); + _output?.WriteLines($"DE {nameof(OnInProcAccountInitiated)}", JsonSerializer.Serialize(e)); + await _dispatcher.RaiseAsync(new AccountInitiatedChained().MergeMetadata(e).SetCausationId(e.GetEventId())).ConfigureAwait(false); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs b/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs index 96b567aa..3c772da6 100644 --- a/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs +++ b/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs @@ -6,51 +6,50 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.Assets.Domain.Handlers +namespace Savvyio.Assets.Domain.Handlers; + +public class PlatformProviderDomainEventHandler : DomainEventHandler { - public class PlatformProviderDomainEventHandler : DomainEventHandler + private readonly ITestOutputHelper _output; + private readonly ITestStore _testStore; + + public PlatformProviderDomainEventHandler(ITestOutputHelper output = null, ITestStore testStore = null) { - private readonly ITestOutputHelper _output; - private readonly ITestStore _testStore; + _output = output; + _testStore = testStore; + } - public PlatformProviderDomainEventHandler(ITestOutputHelper output = null, ITestStore testStore = null) + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.RegisterAsync(e => { - _output = output; - _testStore = testStore; - } - - protected override void RegisterDelegates(IFireForgetRegistry handlers) + _testStore.Add(e); + _output.WriteLines($"DE {nameof(PlatformProviderAccountPolicyChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); + handlers.RegisterAsync(e => + { + _testStore.Add(e); + _output.WriteLines($"DE {nameof(PlatformProviderInitiated)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); + handlers.RegisterAsync(e => + { + _testStore.Add(e); + _output.WriteLines($"DE {nameof(PlatformProviderDescriptionChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); + handlers.RegisterAsync(e => + { + _testStore.Add(e); + _output.WriteLines($"DE {nameof(PlatformProviderNameChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); + handlers.RegisterAsync(e => { - handlers.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"DE {nameof(PlatformProviderAccountPolicyChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - handlers.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"DE {nameof(PlatformProviderInitiated)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - handlers.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"DE {nameof(PlatformProviderDescriptionChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - handlers.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"DE {nameof(PlatformProviderNameChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - handlers.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"DE {nameof(PlatformProviderThirdLevelDomainNameChanged)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - } + _testStore.Add(e); + _output.WriteLines($"DE {nameof(PlatformProviderThirdLevelDomainNameChanged)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Name.cs b/test/Savvyio.Assets.Tests/Domain/Name.cs index 1f31f033..15eaa69d 100644 --- a/test/Savvyio.Assets.Tests/Domain/Name.cs +++ b/test/Savvyio.Assets.Tests/Domain/Name.cs @@ -1,18 +1,17 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record Name : SingleValueObject { - public record Name : SingleValueObject + public static implicit operator Name(string value) { - public static implicit operator Name(string value) - { - return new Name(value); - } + return new Name(value); + } - public Name(string value) : base(value) - { - Validator.ThrowIfNullOrWhitespace(value); - } + public Name(string value) : base(value) + { + Validator.ThrowIfNullOrWhitespace(value); } } diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs index 73b71e62..cdf2a1d8 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs @@ -3,68 +3,67 @@ using Savvyio.Assets.Domain.Events; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public class PlatformProvider : AggregateRoot { - public class PlatformProvider : AggregateRoot + PlatformProvider() // efcore { - PlatformProvider() // efcore - { - } + } - public PlatformProvider(Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) - { - Validator.ThrowIfNull(name); - Validator.ThrowIfNull(thirdLevelDomainName); - Id = Guid.NewGuid(); - Name = name; - ThirdLevelDomainName = thirdLevelDomainName; - Description = description ?? new Description(); - Policy = new PlatformProviderAccountPolicy(); - AddEvent(new PlatformProviderInitiated(this)); - } + public PlatformProvider(Name name, ThirdLevelDomainName thirdLevelDomainName, Description description = null) + { + Validator.ThrowIfNull(name); + Validator.ThrowIfNull(thirdLevelDomainName); + Id = Guid.NewGuid(); + Name = name; + ThirdLevelDomainName = thirdLevelDomainName; + Description = description ?? new Description(); + Policy = new PlatformProviderAccountPolicy(); + AddEvent(new PlatformProviderInitiated(this)); + } - public PlatformProvider(PlatformProviderId id) : base(id) - { - } + public PlatformProvider(PlatformProviderId id) : base(id) + { + } - public string Name { get; private set; } + public string Name { get; private set; } - public string ThirdLevelDomainName { get; private set; } + public string ThirdLevelDomainName { get; private set; } - public string Description { get; private set; } + public string Description { get; private set; } - public PlatformProviderAccountPolicy Policy { get; private set; } + public PlatformProviderAccountPolicy Policy { get; private set; } - public void ChangeName(Name name) - { - Validator.ThrowIfNullOrWhitespace(name); - if (name.Equals((Name)Name)) { return; } - Name = name; - AddEvent(new PlatformProviderNameChanged(this)); - } + public void ChangeName(Name name) + { + Validator.ThrowIfNullOrWhitespace(name); + if (name.Equals((Name)Name)) { return; } + Name = name; + AddEvent(new PlatformProviderNameChanged(this)); + } - public void ChangeThirdLevelDomainName(ThirdLevelDomainName thirdLevelDomainName) - { - Validator.ThrowIfNull(thirdLevelDomainName); - if (thirdLevelDomainName.Equals((ThirdLevelDomainName)ThirdLevelDomainName)) { return; } - ThirdLevelDomainName = thirdLevelDomainName; - AddEvent(new PlatformProviderThirdLevelDomainNameChanged(this)); - } + public void ChangeThirdLevelDomainName(ThirdLevelDomainName thirdLevelDomainName) + { + Validator.ThrowIfNull(thirdLevelDomainName); + if (thirdLevelDomainName.Equals((ThirdLevelDomainName)ThirdLevelDomainName)) { return; } + ThirdLevelDomainName = thirdLevelDomainName; + AddEvent(new PlatformProviderThirdLevelDomainNameChanged(this)); + } - public void ChangeDescription(Description description) - { - Validator.ThrowIfNull(description); - if (Description != null && description.Equals((Description)Description)) { return; } - Description = description; - AddEvent(new PlatformProviderDescriptionChanged(this)); - } + public void ChangeDescription(Description description) + { + Validator.ThrowIfNull(description); + if (Description != null && description.Equals((Description)Description)) { return; } + Description = description; + AddEvent(new PlatformProviderDescriptionChanged(this)); + } - public void ChangeAccountPolicy(PlatformProviderAccountPolicy policy) - { - Validator.ThrowIfNull(policy); - if (policy.Equals(Policy)) { return; } - Policy = policy; - AddEvent(new PlatformProviderAccountPolicyChanged(this)); - } + public void ChangeAccountPolicy(PlatformProviderAccountPolicy policy) + { + Validator.ThrowIfNull(policy); + if (policy.Equals(Policy)) { return; } + Policy = policy; + AddEvent(new PlatformProviderAccountPolicyChanged(this)); } } diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs index 32c7b852..2d789881 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs @@ -1,40 +1,39 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record PlatformProviderAccountPolicy : ValueObject { - public record PlatformProviderAccountPolicy : ValueObject + public PlatformProviderAccountPolicy() : this(8, 0, TimeSpan.Zero, TimeSpan.Zero, 10, TimeSpan.Zero, TimeSpan.Zero, true) { - public PlatformProviderAccountPolicy() : this(8, 0, TimeSpan.Zero, TimeSpan.Zero, 10, TimeSpan.Zero, TimeSpan.Zero, true) - { - } + } - public PlatformProviderAccountPolicy(int minimumPasswordLength, int enforcePasswordHistory, TimeSpan minimumPasswordAge, TimeSpan maximumPasswordAge, int accountLockoutThreshold, TimeSpan accountLockoutDuration, TimeSpan accountLockoutCounterReset, bool passwordComplexityRequirement) - { - MinimumPasswordLength = minimumPasswordLength; - EnforcePasswordHistory = enforcePasswordHistory; - MinimumPasswordAge = minimumPasswordAge.Ticks; - MaximumPasswordAge = maximumPasswordAge.Ticks; - AccountLockoutThreshold = accountLockoutThreshold; - AccountLockoutDuration = accountLockoutDuration.Ticks; - AccountLockoutCounterReset = accountLockoutCounterReset.Ticks; - PasswordComplexityRequirement = passwordComplexityRequirement; - } + public PlatformProviderAccountPolicy(int minimumPasswordLength, int enforcePasswordHistory, TimeSpan minimumPasswordAge, TimeSpan maximumPasswordAge, int accountLockoutThreshold, TimeSpan accountLockoutDuration, TimeSpan accountLockoutCounterReset, bool passwordComplexityRequirement) + { + MinimumPasswordLength = minimumPasswordLength; + EnforcePasswordHistory = enforcePasswordHistory; + MinimumPasswordAge = minimumPasswordAge.Ticks; + MaximumPasswordAge = maximumPasswordAge.Ticks; + AccountLockoutThreshold = accountLockoutThreshold; + AccountLockoutDuration = accountLockoutDuration.Ticks; + AccountLockoutCounterReset = accountLockoutCounterReset.Ticks; + PasswordComplexityRequirement = passwordComplexityRequirement; + } - public int MinimumPasswordLength { get; private set; } + public int MinimumPasswordLength { get; private set; } - public int EnforcePasswordHistory { get; private set; } + public int EnforcePasswordHistory { get; private set; } - public long MinimumPasswordAge { get; private set; } + public long MinimumPasswordAge { get; private set; } - public long MaximumPasswordAge { get; private set; } + public long MaximumPasswordAge { get; private set; } - public int AccountLockoutThreshold { get; private set; } + public int AccountLockoutThreshold { get; private set; } - public long AccountLockoutDuration { get; private set; } + public long AccountLockoutDuration { get; private set; } - public long AccountLockoutCounterReset { get; private set; } + public long AccountLockoutCounterReset { get; private set; } - public bool PasswordComplexityRequirement { get; private set; } - } + public bool PasswordComplexityRequirement { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs index 3fb3287d..c9807a48 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs @@ -2,18 +2,17 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public sealed record PlatformProviderId : SingleValueObject { - public sealed record PlatformProviderId : SingleValueObject + public static implicit operator PlatformProviderId(Guid value) { - public static implicit operator PlatformProviderId(Guid value) - { - return new PlatformProviderId(value); - } + return new PlatformProviderId(value); + } - public PlatformProviderId(Guid id) : base(id) - { - Validator.ThrowIfEqual(id, Guid.Empty, nameof(id)); - } + public PlatformProviderId(Guid id) : base(id) + { + Validator.ThrowIfEqual(id, Guid.Empty, nameof(id)); } } diff --git a/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs b/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs index a2ee9e93..e9d3a52d 100644 --- a/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs +++ b/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs @@ -1,19 +1,18 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record ThirdLevelDomainName : SingleValueObject { - public record ThirdLevelDomainName : SingleValueObject + public static implicit operator ThirdLevelDomainName(string value) { - public static implicit operator ThirdLevelDomainName(string value) - { - return new ThirdLevelDomainName(value); - } + return new ThirdLevelDomainName(value); + } - public ThirdLevelDomainName(string value) : base(value) - { - Validator.ThrowIfNullOrWhitespace(value); - Validator.ThrowIfDifferent(Alphanumeric.Letters, value, nameof(value), $"One or more invalid character(s) specified. Allowed characters are: {Alphanumeric.Letters}"); - } + public ThirdLevelDomainName(string value) : base(value) + { + Validator.ThrowIfNullOrWhitespace(value); + Validator.ThrowIfDifferent(Alphanumeric.Letters, value, nameof(value), $"One or more invalid character(s) specified. Allowed characters are: {Alphanumeric.Letters}"); } } diff --git a/test/Savvyio.Assets.Tests/Domain/Timestamp.cs b/test/Savvyio.Assets.Tests/Domain/Timestamp.cs index a1d5389a..96ce0e80 100644 --- a/test/Savvyio.Assets.Tests/Domain/Timestamp.cs +++ b/test/Savvyio.Assets.Tests/Domain/Timestamp.cs @@ -1,19 +1,18 @@ using System; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record Timestamp : ValueObject { - public record Timestamp : ValueObject + public Timestamp(DateTimeOffset value) { - public Timestamp(DateTimeOffset value) - { - Value = value; - } + Value = value; + } - public DateTimeOffset Value { get; } + public DateTimeOffset Value { get; } - public string TimeZone { get; set; } + public string TimeZone { get; set; } - public bool IsDaylightSavingTime { get; set; } - } + public bool IsDaylightSavingTime { get; set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs b/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs index 7fef2967..76bc4ba6 100644 --- a/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs +++ b/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs @@ -2,18 +2,17 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public record TracedAccountId : SingleValueObject { - public record TracedAccountId : SingleValueObject + public static implicit operator TracedAccountId(Guid value) { - public static implicit operator TracedAccountId(Guid value) - { - return new TracedAccountId(value); - } + return new TracedAccountId(value); + } - public TracedAccountId(Guid id) : base(id) - { - Validator.ThrowIfTrue(() => id == Guid.Empty, nameof(id), "Value cannot be an empty UUID."); - } + public TracedAccountId(Guid id) : base(id) + { + Validator.ThrowIfTrue(() => id == Guid.Empty, nameof(id), "Value cannot be an empty UUID."); } } diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccount.cs b/test/Savvyio.Assets.Tests/Domain/UserAccount.cs index a653dd48..5323b974 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccount.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccount.cs @@ -2,31 +2,30 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public class UserAccount : Entity { - public class UserAccount : Entity + public UserAccount(AccountId accountId, string userName) : base(accountId) { - public UserAccount(AccountId accountId, string userName) : base(accountId) - { - Validator.ThrowIfNullOrWhitespace(userName); - UserName = userName; - } + Validator.ThrowIfNullOrWhitespace(userName); + UserName = userName; + } - public UserAccount(AccountId id) : base(id) - { + public UserAccount(AccountId id) : base(id) + { - } + } - public string UserName { get; private set; } + public string UserName { get; private set; } - public int FailedLogonAttemptCount { get; private set; } + public int FailedLogonAttemptCount { get; private set; } - public int SuccessfulLogonCount { get; private set; } + public int SuccessfulLogonCount { get; private set; } - public DateTimeOffset LastLogon { get; private set; } + public DateTimeOffset LastLogon { get; private set; } - public DateTimeOffset AccountLockout { get; private set; } + public DateTimeOffset AccountLockout { get; private set; } - public DateTimeOffset AccountLockoutReset { get; private set; } - } + public DateTimeOffset AccountLockoutReset { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs b/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs index be6cc7a3..ff53c773 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs @@ -1,21 +1,20 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public class UserAccountFailedLogonAttempt : Entity { - public class UserAccountFailedLogonAttempt : Entity + public UserAccountFailedLogonAttempt(AccountId accountId, string userHostAddress) { - public UserAccountFailedLogonAttempt(AccountId accountId, string userHostAddress) - { - Validator.ThrowIfNull(accountId); - Validator.ThrowIfNullOrWhitespace(userHostAddress); + Validator.ThrowIfNull(accountId); + Validator.ThrowIfNullOrWhitespace(userHostAddress); - AccountId = accountId; - UserHostAddress = userHostAddress; - } + AccountId = accountId; + UserHostAddress = userHostAddress; + } - public long AccountId { get; private set; } + public long AccountId { get; private set; } - public string UserHostAddress { get; private set; } - } + public string UserHostAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs b/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs index c193845a..ce45074e 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs @@ -1,24 +1,23 @@ using Cuemon; using Savvyio.Domain; -namespace Savvyio.Assets.Domain +namespace Savvyio.Assets.Domain; + +public class UserAccountPassword : Entity { - public class UserAccountPassword : Entity + public UserAccountPassword(AccountId accountId, Credentials password) { - public UserAccountPassword(AccountId accountId, Credentials password) - { - Validator.ThrowIfNull(accountId); - Validator.ThrowIfNull(password); + Validator.ThrowIfNull(accountId); + Validator.ThrowIfNull(password); - AccountId = accountId; - Hash = password.Hash; - Salt = password.Salt; - } + AccountId = accountId; + Hash = password.Hash; + Salt = password.Salt; + } - public long AccountId { get; private set; } + public long AccountId { get; private set; } - public string Hash { get; private set; } + public string Hash { get; private set; } - public string Salt { get; private set; } - } + public string Salt { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs index 6622a123..4a029afe 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs @@ -1,24 +1,23 @@ using Savvyio.EventDriven; -namespace Savvyio.Assets.EventDriven +namespace Savvyio.Assets.EventDriven; + +public record AccountCreated : IntegrationEvent { - public record AccountCreated : IntegrationEvent + AccountCreated() { - AccountCreated() - { - } + } - public AccountCreated(long id, string fullName, string emailAddress) - { - Id = id; - FullName = fullName; - EmailAddress = emailAddress; - } + public AccountCreated(long id, string fullName, string emailAddress) + { + Id = id; + FullName = fullName; + EmailAddress = emailAddress; + } - public long Id { get; private set; } + public long Id { get; private set; } - public string FullName { get; private set; } + public string FullName { get; private set; } - public string EmailAddress { get; private set; } - } + public string EmailAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs b/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs index 48eb5ee4..ffb41c04 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs @@ -1,24 +1,23 @@ using Savvyio.EventDriven; -namespace Savvyio.Assets.EventDriven +namespace Savvyio.Assets.EventDriven; + +public record AccountUpdated : IntegrationEvent { - public record AccountUpdated : IntegrationEvent + AccountUpdated() { - AccountUpdated() - { - } + } - public AccountUpdated(long id, string fullName, string emailAddress) - { - Id = id; - FullName = fullName; - EmailAddress = emailAddress; - } + public AccountUpdated(long id, string fullName, string emailAddress) + { + Id = id; + FullName = fullName; + EmailAddress = emailAddress; + } - public long Id { get; private set; } + public long Id { get; private set; } - public string FullName { get; private set; } + public string FullName { get; private set; } - public string EmailAddress { get; private set; } - } + public string EmailAddress { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs index 093e5d6c..5a84feac 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs @@ -1,17 +1,16 @@ using Savvyio.EventDriven; -namespace Savvyio.Assets.EventDriven +namespace Savvyio.Assets.EventDriven; + +public record MemberCreated : IntegrationEvent { - public record MemberCreated : IntegrationEvent + public MemberCreated(string name, string emailAddress) { - public MemberCreated(string name, string emailAddress) - { - Name = name; - EmailAddress = emailAddress; - } + Name = name; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs index 2129bb09..e1cee350 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs @@ -2,31 +2,30 @@ using Savvyio.Assets.Domain; using Savvyio.EventDriven; -namespace Savvyio.Assets.EventDriven +namespace Savvyio.Assets.EventDriven; + +public record PlatformProviderCreated : IntegrationEvent { - public record PlatformProviderCreated : IntegrationEvent + PlatformProviderCreated() { - PlatformProviderCreated() - { - } + } - public PlatformProviderCreated(PlatformProvider provider) - { - Id = provider.Id; - Name = provider.Name; - ThirdLevelDomainName = provider.ThirdLevelDomainName; - Description = provider.Description; - Policy = provider.Policy; - } + public PlatformProviderCreated(PlatformProvider provider) + { + Id = provider.Id; + Name = provider.Name; + ThirdLevelDomainName = provider.ThirdLevelDomainName; + Description = provider.Description; + Policy = provider.Policy; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string Name { get; private set; } + public string Name { get; private set; } - public string ThirdLevelDomainName { get; private set; } + public string ThirdLevelDomainName { get; private set; } - public string Description { get; private set; } + public string Description { get; private set; } - public PlatformProviderAccountPolicy Policy { get; private set; } - } + public PlatformProviderAccountPolicy Policy { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs index 7815bda9..8ce11dcc 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs @@ -2,31 +2,30 @@ using Savvyio.Assets.Domain; using Savvyio.EventDriven; -namespace Savvyio.Assets.EventDriven +namespace Savvyio.Assets.EventDriven; + +public record PlatformProviderUpdated : IntegrationEvent { - public record PlatformProviderUpdated : IntegrationEvent + PlatformProviderUpdated() { - PlatformProviderUpdated() - { - } + } - public PlatformProviderUpdated(PlatformProvider provider) - { - Id = provider.Id; - Name = provider.Name; - ThirdLevelDomainName = provider.ThirdLevelDomainName; - Description = provider.Description; - Policy = provider.Policy; - } + public PlatformProviderUpdated(PlatformProvider provider) + { + Id = provider.Id; + Name = provider.Name; + ThirdLevelDomainName = provider.ThirdLevelDomainName; + Description = provider.Description; + Policy = provider.Policy; + } - public Guid Id { get; private set; } + public Guid Id { get; private set; } - public string Name { get; private set; } + public string Name { get; private set; } - public string ThirdLevelDomainName { get; private set; } + public string ThirdLevelDomainName { get; private set; } - public string Description { get; private set; } + public string Description { get; private set; } - public PlatformProviderAccountPolicy Policy { get; private set; } - } + public PlatformProviderAccountPolicy Policy { get; private set; } } diff --git a/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs b/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs index 34d39154..2e7ff3ee 100644 --- a/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs +++ b/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs @@ -12,67 +12,66 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class PlatformProviderHandler : ICommandHandler, IIntegrationEventHandler { - public class PlatformProviderHandler : ICommandHandler, IIntegrationEventHandler + private readonly IMediator _mediator; + private readonly ITestOutputHelper _output; + private readonly IPersistentDataStore, PlatformProvider> _activeRecordRepository; + private readonly ITestStore _testStore; + + public PlatformProviderHandler(IMediator mediator = null, ITestOutputHelper output = null, ITestStore testStore = null, IPersistentDataStore, PlatformProvider> activeRecordRepository = null) { - private readonly IMediator _mediator; - private readonly ITestOutputHelper _output; - private readonly IPersistentDataStore, PlatformProvider> _activeRecordRepository; - private readonly ITestStore _testStore; + _mediator = mediator; + _output = output; + _testStore = testStore; + _activeRecordRepository = activeRecordRepository; + } - public PlatformProviderHandler(IMediator mediator = null, ITestOutputHelper output = null, ITestStore testStore = null, IPersistentDataStore, PlatformProvider> activeRecordRepository = null) + IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(handler => + { + handler.RegisterAsync(e => { - _mediator = mediator; - _output = output; - _testStore = testStore; - _activeRecordRepository = activeRecordRepository; - } + _testStore.Add(e); + _output.WriteLines($"IE {nameof(PlatformProviderCreated)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; + }); - IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(handler => + handler.RegisterAsync(e => { - handler.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"IE {nameof(PlatformProviderCreated)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); - - handler.RegisterAsync(e => - { - _testStore.Add(e); - _output.WriteLines($"IE {nameof(PlatformProviderUpdated)}", JsonSerializer.Serialize(e)); - return Task.CompletedTask; - }); + _testStore.Add(e); + _output.WriteLines($"IE {nameof(PlatformProviderUpdated)}", JsonSerializer.Serialize(e)); + return Task.CompletedTask; }); + }); - IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(handler => + IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(handler => + { + handler.RegisterAsync(async c => { - handler.RegisterAsync(async c => - { - _output.WriteLines($"C {nameof(CreatePlatformProvider)}", JsonSerializer.Serialize(c)); - var provider = new PlatformProvider(c.Name, c.ThirdLevelDomainName, c.Description).MergeMetadata(c); - await _activeRecordRepository.CreateAsync(provider); // store in db - await _mediator.PublishAsync(new PlatformProviderCreated(provider).MergeMetadata(c)); - }); + _output.WriteLines($"C {nameof(CreatePlatformProvider)}", JsonSerializer.Serialize(c)); + var provider = new PlatformProvider(c.Name, c.ThirdLevelDomainName, c.Description).MergeMetadata(c); + await _activeRecordRepository.CreateAsync(provider); // store in db + await _mediator.PublishAsync(new PlatformProviderCreated(provider).MergeMetadata(c)); + }); - handler.RegisterAsync(async c => - { - var provider = new PlatformProvider(c.Id); - provider.ChangeDescription(c.Description); - provider.ChangeName(c.Name); - provider.ChangeThirdLevelDomainName(c.ThirdLevelDomainName); - await _activeRecordRepository.UpdateAsync(provider); // store in db - await _mediator.PublishAsync(new PlatformProviderUpdated(provider)); - }); + handler.RegisterAsync(async c => + { + var provider = new PlatformProvider(c.Id); + provider.ChangeDescription(c.Description); + provider.ChangeName(c.Name); + provider.ChangeThirdLevelDomainName(c.ThirdLevelDomainName); + await _activeRecordRepository.UpdateAsync(provider); // store in db + await _mediator.PublishAsync(new PlatformProviderUpdated(provider)); + }); - handler.RegisterAsync(async c => - { - var provider = new PlatformProvider(c.Id); - provider.ChangeAccountPolicy(new PlatformProviderAccountPolicy(c.MinimumPasswordLength, c.EnforcePasswordHistory, c.MinimumPasswordAge, c.MaximumPasswordAge, c.AccountLockoutThreshold, c.AccountLockoutDuration, c.AccountLockoutCounterReset, c.PasswordComplexityRequirement)); - await _activeRecordRepository.UpdateAsync(provider); - await _mediator.PublishAsync(new PlatformProviderUpdated(provider)); - }); + handler.RegisterAsync(async c => + { + var provider = new PlatformProvider(c.Id); + provider.ChangeAccountPolicy(new PlatformProviderAccountPolicy(c.MinimumPasswordLength, c.EnforcePasswordHistory, c.MinimumPasswordAge, c.MaximumPasswordAge, c.AccountLockoutThreshold, c.AccountLockoutDuration, c.AccountLockoutCounterReset, c.PasswordComplexityRequirement)); + await _activeRecordRepository.UpdateAsync(provider); + await _mediator.PublishAsync(new PlatformProviderUpdated(provider)); }); - } + }); } diff --git a/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs b/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs index 1acb9c15..f6ebb023 100644 --- a/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs +++ b/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs @@ -1,28 +1,27 @@ -namespace Savvyio.Assets.Queries +namespace Savvyio.Assets.Queries; + +public class AccountProjection { - public class AccountProjection + public AccountProjection() { - public AccountProjection() - { - } + } - public AccountProjection(long id, string fullName, string emailAddress) - { - Id = id; - FullName = fullName; - EmailAddress = emailAddress; - } + public AccountProjection(long id, string fullName, string emailAddress) + { + Id = id; + FullName = fullName; + EmailAddress = emailAddress; + } - public AccountProjection(string fullName, string emailAddress) - { - FullName = fullName; - EmailAddress = emailAddress; - } + public AccountProjection(string fullName, string emailAddress) + { + FullName = fullName; + EmailAddress = emailAddress; + } - public long Id { get; set; } + public long Id { get; set; } - public string FullName { get; set; } + public string FullName { get; set; } - public string EmailAddress { get; set; } - } + public string EmailAddress { get; set; } } diff --git a/test/Savvyio.Assets.Tests/Queries/GetAccount.cs b/test/Savvyio.Assets.Tests/Queries/GetAccount.cs index 2d0eb459..3e01391a 100644 --- a/test/Savvyio.Assets.Tests/Queries/GetAccount.cs +++ b/test/Savvyio.Assets.Tests/Queries/GetAccount.cs @@ -1,14 +1,13 @@ using Savvyio.Queries; -namespace Savvyio.Assets.Queries +namespace Savvyio.Assets.Queries; + +public record GetAccount : Query { - public record GetAccount : Query + public GetAccount(long id) { - public GetAccount(long id) - { - Id = id; - } - - public long Id { get; } + Id = id; } + + public long Id { get; } } diff --git a/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs b/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs index e96a1938..8bf1d1a8 100644 --- a/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs +++ b/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs @@ -1,15 +1,14 @@ using Savvyio.Assets.EventDriven; using Savvyio.Queries; -namespace Savvyio.Assets.Queries +namespace Savvyio.Assets.Queries; + +public record GetFakeAccount : Query { - public record GetFakeAccount : Query + public GetFakeAccount(long id) { - public GetFakeAccount(long id) - { - Id = id; - } - - public long Id { get; } + Id = id; } + + public long Id { get; } } diff --git a/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs b/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs index 9c6a697a..c14b72f3 100644 --- a/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs +++ b/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs @@ -1,35 +1,34 @@ using System; -namespace Savvyio.Assets.Queries +namespace Savvyio.Assets.Queries; + +public class PlatformProviderProjection { - public class PlatformProviderProjection + public PlatformProviderProjection() { - public PlatformProviderProjection() - { - } + } - public Guid Id { get; set; } + public Guid Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string ThirdLevelDomainName { get; set; } + public string ThirdLevelDomainName { get; set; } - public string Description { get; set; } + public string Description { get; set; } - public int MinimumPasswordLength { get; set; } + public int MinimumPasswordLength { get; set; } - public int EnforcePasswordHistory { get; set; } + public int EnforcePasswordHistory { get; set; } - public long MinimumPasswordAge { get; set; } + public long MinimumPasswordAge { get; set; } - public long MaximumPasswordAge { get; set; } + public long MaximumPasswordAge { get; set; } - public int AccountLockoutThreshold { get; set; } + public int AccountLockoutThreshold { get; set; } - public long AccountLockoutDuration { get; set; } + public long AccountLockoutDuration { get; set; } - public long AccountLockoutCounterReset { get; set; } + public long AccountLockoutCounterReset { get; set; } - public bool PasswordComplexityRequirement { get; set; } - } + public bool PasswordComplexityRequirement { get; set; } } diff --git a/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs b/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs index 1c7ef5d7..008a396c 100644 --- a/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs +++ b/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs @@ -1,6 +1,5 @@ -namespace Savvyio.Commands.Assets +namespace Savvyio.Commands.Assets; + +internal record DefaultCommand : Command { - internal record DefaultCommand : Command - { - } } diff --git a/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs b/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs index fe23e4c5..53f2329a 100644 --- a/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs +++ b/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs @@ -2,25 +2,24 @@ using Codebelt.Extensions.Xunit; using Savvyio.Handlers; -namespace Savvyio.Commands.Assets +namespace Savvyio.Commands.Assets; + +internal class DefaultCommandHandler : CommandHandler { - internal class DefaultCommandHandler : CommandHandler - { - private readonly ITestStore _ts; + private readonly ITestStore _ts; - public DefaultCommandHandler(ITestStore ts) - { - _ts = ts; - } + public DefaultCommandHandler(ITestStore ts) + { + _ts = ts; + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.Register(_ => _ts.Add(nameof(DefaultCommand))); + handlers.RegisterAsync(_ => { - handlers.Register(_ => _ts.Add(nameof(DefaultCommand))); - handlers.RegisterAsync(_ => - { - _ts.Add(nameof(DefaultCommand) + "Async"); - return Task.CompletedTask; - }); - } + _ts.Add(nameof(DefaultCommand) + "Async"); + return Task.CompletedTask; + }); } } diff --git a/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs b/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs index 9ea9cd2a..5159b69f 100644 --- a/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs +++ b/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs @@ -7,41 +7,40 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +public class CommandDispatcherTest : Test { - public class CommandDispatcherTest : Test + public CommandDispatcherTest(ITestOutputHelper output) : base(output) { - public CommandDispatcherTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CommandDispatcher_Ensure_Initialization_Defaults() - { - var sp = new ServiceCollection().AddServiceLocator().BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); + [Fact] + public void CommandDispatcher_Ensure_Initialization_Defaults() + { + var sp = new ServiceCollection().AddServiceLocator().BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); - Assert.Throws(() => sut.Commit(new DefaultCommand())); - Assert.ThrowsAsync(() => sut.CommitAsync(new DefaultCommand())); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - } + Assert.Throws(() => sut.Commit(new DefaultCommand())); + Assert.ThrowsAsync(() => sut.CommitAsync(new DefaultCommand())); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + } - [Fact] - public async Task CommandDispatcher_ShouldCommit_DefaultCommand() - { - var sp = new ServiceCollection().AddServiceLocator().AddTransient().AddSingleton, InMemoryTestStore>().BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); - var ts = sp.GetRequiredService>(); + [Fact] + public async Task CommandDispatcher_ShouldCommit_DefaultCommand() + { + var sp = new ServiceCollection().AddServiceLocator().AddTransient().AddSingleton, InMemoryTestStore>().BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); + var ts = sp.GetRequiredService>(); - sut.Commit(new DefaultCommand()); - await sut.CommitAsync(new DefaultCommand()); + sut.Commit(new DefaultCommand()); + await sut.CommitAsync(new DefaultCommand()); - Assert.Collection(ts.Query(), - s => Assert.Equal(s, nameof(DefaultCommand)), - s => Assert.Equal(s, nameof(DefaultCommand) + "Async")); - } + Assert.Collection(ts.Query(), + s => Assert.Equal(s, nameof(DefaultCommand)), + s => Assert.Equal(s, nameof(DefaultCommand) + "Async")); } } diff --git a/test/Savvyio.Commands.Tests/CommandHandlerTest.cs b/test/Savvyio.Commands.Tests/CommandHandlerTest.cs index 9e8c3ec5..57103a3f 100644 --- a/test/Savvyio.Commands.Tests/CommandHandlerTest.cs +++ b/test/Savvyio.Commands.Tests/CommandHandlerTest.cs @@ -4,25 +4,24 @@ using Savvyio.Commands.Assets; using Xunit; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +public class CommandHandlerTest : Test { - public class CommandHandlerTest : Test + public CommandHandlerTest(ITestOutputHelper output) : base(output) { - public CommandHandlerTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task CommandHandler_Ensure_Initialization_Defaults() - { - var sut = new DefaultCommandHandler(new InMemoryTestStore()); + [Fact] + public async Task CommandHandler_Ensure_Initialization_Defaults() + { + var sut = new DefaultCommandHandler(new InMemoryTestStore()); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.True(sut.Delegates.TryInvoke(new DefaultCommand())); - Assert.True((await sut.Delegates.TryInvokeAsync(new DefaultCommand())).Succeeded); - Assert.False(sut.Delegates.TryInvoke(new CreatePlatformProvider("Name", "Tld", "Description"))); - Assert.False((await sut.Delegates.TryInvokeAsync(new CreatePlatformProvider("Name", "Tld", "Description"))).Succeeded); - } + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.True(sut.Delegates.TryInvoke(new DefaultCommand())); + Assert.True((await sut.Delegates.TryInvokeAsync(new DefaultCommand())).Succeeded); + Assert.False(sut.Delegates.TryInvoke(new CreatePlatformProvider("Name", "Tld", "Description"))); + Assert.False((await sut.Delegates.TryInvokeAsync(new CreatePlatformProvider("Name", "Tld", "Description"))).Succeeded); } } diff --git a/test/Savvyio.Commands.Tests/CommandTest.cs b/test/Savvyio.Commands.Tests/CommandTest.cs index 5ddddbf4..bfee754b 100644 --- a/test/Savvyio.Commands.Tests/CommandTest.cs +++ b/test/Savvyio.Commands.Tests/CommandTest.cs @@ -2,25 +2,24 @@ using Savvyio.Commands.Assets; using Xunit; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +public class CommandTest : Test { - public class CommandTest : Test + public CommandTest(ITestOutputHelper output) : base(output) { - public CommandTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DefaultCommand_Ensure_Initialization_Defaults() - { - var sut = new DefaultCommand(); + [Fact] + public void DefaultCommand_Ensure_Initialization_Defaults() + { + var sut = new DefaultCommand(); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.Contains(sut.Metadata, pair => pair.Key == MetadataDictionary.CorrelationId); - } + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.Contains(sut.Metadata, pair => pair.Key == MetadataDictionary.CorrelationId); } } diff --git a/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs index 51ece9cb..eb1cdaff 100644 --- a/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs @@ -4,30 +4,29 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Commands.Messaging +namespace Savvyio.Commands.Messaging; + +public class CommandExtensionsTest : Test { - public class CommandExtensionsTest : Test + public CommandExtensionsTest(ITestOutputHelper output) : base(output) { - public CommandExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EncloseToMessage_CreateMemberCommand_ShouldBeWrappedInMessage() - { - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com"); - var sut2 = "https://fancy.api/members".ToUri(); - var sut3 = "com.example.someevent"; - var sut4 = sut1.ToMessage(sut2, sut3); + [Fact] + public void EncloseToMessage_CreateMemberCommand_ShouldBeWrappedInMessage() + { + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com"); + var sut2 = "https://fancy.api/members".ToUri(); + var sut3 = "com.example.someevent"; + var sut4 = sut1.ToMessage(sut2, sut3); - Assert.Equal(sut1.EmailAddress, sut4.Data.EmailAddress); - Assert.Equal(sut1.Age, sut4.Data.Age); - Assert.Equal(sut1.Name, sut4.Data.Name); - Assert.NotNull(sut4.Id); - Assert.NotNull(sut4.Time); - Assert.Equal(sut1.GetType().ToFullNameIncludingAssemblyName(), sut4.Data.GetMemberType()); - Assert.Equal(sut2.OriginalString, sut4.Source); - Assert.Equal(sut3, sut4.Type); - } + Assert.Equal(sut1.EmailAddress, sut4.Data.EmailAddress); + Assert.Equal(sut1.Age, sut4.Data.Age); + Assert.Equal(sut1.Name, sut4.Data.Name); + Assert.NotNull(sut4.Id); + Assert.NotNull(sut4.Time); + Assert.Equal(sut1.GetType().ToFullNameIncludingAssemblyName(), sut4.Data.GetMemberType()); + Assert.Equal(sut2.OriginalString, sut4.Source); + Assert.Equal(sut3, sut4.Type); } } diff --git a/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs index 83fb3d3c..0d74a5ce 100644 --- a/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs @@ -2,42 +2,41 @@ using Savvyio.Assets; using Xunit; -namespace Savvyio.Commands +namespace Savvyio.Commands; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddHandlers(); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - } + [Fact] + public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddHandlers(); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + } - [Fact] - public void AddCommandHandler_ShouldAddCommandHandler() - { - var sut = new SavvyioOptions().AddCommandHandler(); + [Fact] + public void AddCommandHandler_ShouldAddCommandHandler() + { + var sut = new SavvyioOptions().AddCommandHandler(); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(ICommandHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountCommandHandler), type)); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(ICommandHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountCommandHandler), type)); + } - [Fact] - public void AddCommandDispatcher_ShouldAddCommandDispatcher() - { - var sut = new SavvyioOptions().AddCommandDispatcher(); + [Fact] + public void AddCommandDispatcher_ShouldAddCommandDispatcher() + { + var sut = new SavvyioOptions().AddCommandDispatcher(); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(ICommandDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(CommandDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(ICommandDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(CommandDispatcher), type)); } } diff --git a/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs b/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs index 3aa7b1f4..42d8e19e 100644 --- a/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs +++ b/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs @@ -9,46 +9,45 @@ using Savvyio.Handlers; using Savvyio.Queries; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class AccountHandlers : ICommandHandler, IQueryHandler { - public class AccountHandlers : ICommandHandler, IQueryHandler + private readonly ICommandDispatcher _commandDispatcher; + private readonly ITestStore _commandTestStore; + private readonly ITestStore _queryTestStore; + private readonly IQueryDispatcher _queryDispatcher; + + public AccountHandlers(ICommandDispatcher commandDispatcher = null, ITestStore commandTestStore = null, ITestStore queryTestStore = null, IQueryDispatcher queryDispatcher = null) { - private readonly ICommandDispatcher _commandDispatcher; - private readonly ITestStore _commandTestStore; - private readonly ITestStore _queryTestStore; - private readonly IQueryDispatcher _queryDispatcher; + _commandDispatcher = commandDispatcher; + _commandTestStore = commandTestStore; + _queryTestStore = queryTestStore; + _queryDispatcher = queryDispatcher; + } - public AccountHandlers(ICommandDispatcher commandDispatcher = null, ITestStore commandTestStore = null, ITestStore queryTestStore = null, IQueryDispatcher queryDispatcher = null) + IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(registry => + { + registry.Register(ca => _commandTestStore.Add(ca)); + registry.RegisterAsync(async ca => { - _commandDispatcher = commandDispatcher; - _commandTestStore = commandTestStore; - _queryTestStore = queryTestStore; - _queryDispatcher = queryDispatcher; - } + await Task.Delay(TimeSpan.FromSeconds(0.5)); + _commandTestStore.Add(ca); + }); + }); - IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(registry => + IRequestReplyActivator IRequestReplyHandler.Delegates => HandlerFactory.CreateRequestReply(registry => + { + registry.Register(a => { - registry.Register(ca => _commandTestStore.Add(ca)); - registry.RegisterAsync(async ca => - { - await Task.Delay(TimeSpan.FromSeconds(0.5)); - _commandTestStore.Add(ca); - }); + _queryTestStore.Add(a); + return new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where"); }); - - IRequestReplyActivator IRequestReplyHandler.Delegates => HandlerFactory.CreateRequestReply(registry => + registry.RegisterAsync(async a => { - registry.Register(a => - { - _queryTestStore.Add(a); - return new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where"); - }); - registry.RegisterAsync(async a => - { - await Task.Delay(TimeSpan.FromSeconds(0.5)); - _queryTestStore.Add(a); - return new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where"); - }); + await Task.Delay(TimeSpan.FromSeconds(0.5)); + _queryTestStore.Add(a); + return new AccountCreated(a.Id, $"{a.Id}___{Generate.RandomString(16)}", $"{a.Id}@no.where"); }); - } + }); } diff --git a/test/Savvyio.Core.Tests/Assets/DummyRequest.cs b/test/Savvyio.Core.Tests/Assets/DummyRequest.cs index 87536316..895d747f 100644 --- a/test/Savvyio.Core.Tests/Assets/DummyRequest.cs +++ b/test/Savvyio.Core.Tests/Assets/DummyRequest.cs @@ -1,8 +1,7 @@ using System; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public record DummyRequest(Guid Uuid, int Number) : Request { - public record DummyRequest(Guid Uuid, int Number) : Request - { - } } diff --git a/test/Savvyio.Core.Tests/Assets/FakeCommand.cs b/test/Savvyio.Core.Tests/Assets/FakeCommand.cs index e2ef1780..96e6777f 100644 --- a/test/Savvyio.Core.Tests/Assets/FakeCommand.cs +++ b/test/Savvyio.Core.Tests/Assets/FakeCommand.cs @@ -1,25 +1,24 @@ using System; using Savvyio.Commands; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +internal record FakeCommand : Command { - internal record FakeCommand : Command + public FakeCommand() { - public FakeCommand() - { - Type = null; - } + Type = null; + } - public object Value { get; set; } + public object Value { get; set; } - public Type Type { get; protected set; } - } + public Type Type { get; protected set; } +} - internal record FakeCommand : FakeCommand +internal record FakeCommand : FakeCommand +{ + public FakeCommand() { - public FakeCommand() - { - Type = typeof(T); - } + Type = typeof(T); } } diff --git a/test/Savvyio.Core.Tests/Assets/FakeQuery.cs b/test/Savvyio.Core.Tests/Assets/FakeQuery.cs index efcbbcdf..6a11b144 100644 --- a/test/Savvyio.Core.Tests/Assets/FakeQuery.cs +++ b/test/Savvyio.Core.Tests/Assets/FakeQuery.cs @@ -1,8 +1,7 @@ using Savvyio.Queries; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +internal record FakeQuery : Query { - internal record FakeQuery : Query - { - } } diff --git a/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs b/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs index 68d19811..ff2567ba 100644 --- a/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs +++ b/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs @@ -1,8 +1,7 @@ using System; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public record RootDummyRequest(Guid Uuid, int Number, bool Hidden = false) : DummyRequest(Uuid, Number) { - public record RootDummyRequest(Guid Uuid, int Number, bool Hidden = false) : DummyRequest(Uuid, Number) - { - } } diff --git a/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs b/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs index 1817a1e0..47d46523 100644 --- a/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs +++ b/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs @@ -10,70 +10,69 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +public class FireForgetDispatcherTest : Test { - public class FireForgetDispatcherTest : Test + public FireForgetDispatcherTest(ITestOutputHelper output) : base(output) { - public FireForgetDispatcherTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Dispatch_ShouldFailWithOrphanedHandlerException() - { - var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(FireForgetDispatcherTest).Assembly)); - var sp = sc.BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); + [Fact] + public void Dispatch_ShouldFailWithOrphanedHandlerException() + { + var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(FireForgetDispatcherTest).Assembly)); + var sp = sc.BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); - Assert.Throws(() => sut.Commit(new FakeCommand())); - } + Assert.Throws(() => sut.Commit(new FakeCommand())); + } - [Fact] - public void Dispatch_ShouldDispatchCommandToDesignatedHandler() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(FireForgetDispatcherTest).Assembly, typeof(ICommand).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); + [Fact] + public void Dispatch_ShouldDispatchCommandToDesignatedHandler() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(FireForgetDispatcherTest).Assembly, typeof(ICommand).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); - var sp = sc.BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); - var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var cs = sp.GetRequiredService>(); + var sp = sc.BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); + var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + var cs = sp.GetRequiredService>(); - sut.Commit(ca); + sut.Commit(ca); - Assert.Equal(ca.FullName, cs.QueryFor().Single().FullName); - Assert.Equal(ca.EmailAddress, cs.QueryFor().Single().EmailAddress); - Assert.Equal(ca.PlatformProviderId, cs.QueryFor().Single().PlatformProviderId); - } + Assert.Equal(ca.FullName, cs.QueryFor().Single().FullName); + Assert.Equal(ca.EmailAddress, cs.QueryFor().Single().EmailAddress); + Assert.Equal(ca.PlatformProviderId, cs.QueryFor().Single().PlatformProviderId); + } - [Fact] - public async Task DispatchAsync_ShouldFailWithOrphanedHandlerExceptionAsync() - { - var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(FireForgetDispatcherTest).Assembly)); - var sp = sc.BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); + [Fact] + public async Task DispatchAsync_ShouldFailWithOrphanedHandlerExceptionAsync() + { + var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(FireForgetDispatcherTest).Assembly)); + var sp = sc.BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); - await Assert.ThrowsAsync(async () => await sut.CommitAsync(new FakeCommand())); - } + await Assert.ThrowsAsync(async () => await sut.CommitAsync(new FakeCommand())); + } - [Fact] - public async Task DispatchAsync_ShouldDispatchCommandToDesignatedHandlerAsync() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(FireForgetDispatcherTest).Assembly, typeof(ICommand).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); + [Fact] + public async Task DispatchAsync_ShouldDispatchCommandToDesignatedHandlerAsync() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(FireForgetDispatcherTest).Assembly, typeof(ICommand).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); - var sp = sc.BuildServiceProvider(); - var sut = new CommandDispatcher(sp.GetRequiredService()); - var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var cs = sp.GetRequiredService>(); + var sp = sc.BuildServiceProvider(); + var sut = new CommandDispatcher(sp.GetRequiredService()); + var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + var cs = sp.GetRequiredService>(); - await sut.CommitAsync(ca); + await sut.CommitAsync(ca); - Assert.Equal(ca.FullName, cs.QueryFor().Single().FullName); - Assert.Equal(ca.EmailAddress, cs.QueryFor().Single().EmailAddress); - Assert.Equal(ca.PlatformProviderId, cs.QueryFor().Single().PlatformProviderId); - } + Assert.Equal(ca.FullName, cs.QueryFor().Single().FullName); + Assert.Equal(ca.EmailAddress, cs.QueryFor().Single().EmailAddress); + Assert.Equal(ca.PlatformProviderId, cs.QueryFor().Single().PlatformProviderId); } } diff --git a/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs b/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs index bbe517de..c0fdd82a 100644 --- a/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs +++ b/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs @@ -9,70 +9,69 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio.Dispatchers +namespace Savvyio.Dispatchers; + +public class RequestReplyDispatcherTest : Test { - public class RequestReplyDispatcherTest : Test + public RequestReplyDispatcherTest(ITestOutputHelper output) : base(output) { - public RequestReplyDispatcherTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Dispatch_ShouldFailWithOrphanedHandlerException() - { - var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(RequestReplyDispatcherTest).Assembly)); - var sp = sc.BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); + [Fact] + public void Dispatch_ShouldFailWithOrphanedHandlerException() + { + var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(RequestReplyDispatcherTest).Assembly)); + var sp = sc.BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); - Assert.Throws(() => sut.Query(new FakeQuery())); - } + Assert.Throws(() => sut.Query(new FakeQuery())); + } - [Fact] - public void Dispatch_ShouldDispatchCommandToDesignatedHandler() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(RequestReplyDispatcherTest).Assembly, typeof(IQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); + [Fact] + public void Dispatch_ShouldDispatchCommandToDesignatedHandler() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(RequestReplyDispatcherTest).Assembly, typeof(IQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); - var sp = sc.BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); - var ga = new GetFakeAccount(2313); - var cs = sp.GetRequiredService>(); + var sp = sc.BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); + var ga = new GetFakeAccount(2313); + var cs = sp.GetRequiredService>(); - var result = sut.Query(ga); + var result = sut.Query(ga); - Assert.NotNull(result); - Assert.Equal(ga.Id, result.Id); - Assert.Equal(ga.Id, cs.QueryFor().Single().Id); - } + Assert.NotNull(result); + Assert.Equal(ga.Id, result.Id); + Assert.Equal(ga.Id, cs.QueryFor().Single().Id); + } - [Fact] - public async Task DispatchAsync_ShouldFailWithOrphanedHandlerExceptionAsync() - { - var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(RequestReplyDispatcherTest).Assembly)); - var sp = sc.BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); + [Fact] + public async Task DispatchAsync_ShouldFailWithOrphanedHandlerExceptionAsync() + { + var sc = new ServiceCollection().AddSavvyIO(o => o.AddAssemblyToScan(typeof(RequestReplyDispatcherTest).Assembly)); + var sp = sc.BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); - await Assert.ThrowsAsync(async () => await sut.QueryAsync(new FakeQuery())); - } + await Assert.ThrowsAsync(async () => await sut.QueryAsync(new FakeQuery())); + } - [Fact] - public async Task DispatchAsync_ShouldDispatchCommandToDesignatedHandlerAsync() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(RequestReplyDispatcherTest).Assembly, typeof(IQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); + [Fact] + public async Task DispatchAsync_ShouldDispatchCommandToDesignatedHandlerAsync() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(RequestReplyDispatcherTest).Assembly, typeof(IQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); - var sp = sc.BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); - var ga = new GetFakeAccount(74893297432); - var cs = sp.GetRequiredService>(); + var sp = sc.BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); + var ga = new GetFakeAccount(74893297432); + var cs = sp.GetRequiredService>(); - var result = await sut.QueryAsync(ga); + var result = await sut.QueryAsync(ga); - Assert.NotNull(result); - Assert.StartsWith(ga.Id.ToString(), result.EmailAddress); - Assert.Equal(ga.Id, cs.QueryFor().Single().Id); - } + Assert.NotNull(result); + Assert.StartsWith(ga.Id.ToString(), result.EmailAddress); + Assert.Equal(ga.Id, cs.QueryFor().Single().Id); } } diff --git a/test/Savvyio.Core.Tests/HandlerFactoryTest.cs b/test/Savvyio.Core.Tests/HandlerFactoryTest.cs index 9c6d4da2..ff2d18c3 100644 --- a/test/Savvyio.Core.Tests/HandlerFactoryTest.cs +++ b/test/Savvyio.Core.Tests/HandlerFactoryTest.cs @@ -9,156 +9,155 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class HandlerFactoryTest : Test { - public class HandlerFactoryTest : Test + public HandlerFactoryTest(ITestOutputHelper output) : base(output) { - public HandlerFactoryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CreateFireForget_ShouldInvokeRegisteredHandlers() + [Fact] + public void CreateFireForget_ShouldInvokeRegisteredHandlers() + { + var store = new List(); + var sut1 = HandlerFactory.CreateFireForget(registry => { - var store = new List(); - var sut1 = HandlerFactory.CreateFireForget(registry => - { - registry.Register(c => store.Add(c)); - registry.Register>(c => store.Add(c)); - registry.Register>(c => store.Add(c)); - registry.Register>(c => store.Add(c)); - registry.Register>(c => store.Add(c)); - }); + registry.Register(c => store.Add(c)); + registry.Register>(c => store.Add(c)); + registry.Register>(c => store.Add(c)); + registry.Register>(c => store.Add(c)); + registry.Register>(c => store.Add(c)); + }); - Assert.NotNull(sut1); - Assert.True(sut1.TryInvoke(new FakeCommand())); - Assert.True(sut1.TryInvoke(new FakeCommand())); - Assert.True(sut1.TryInvoke(new FakeCommand())); - Assert.True(sut1.TryInvoke(new FakeCommand())); - Assert.True(sut1.TryInvoke(new FakeCommand())); - Assert.False(sut1.TryInvoke(new FakeCommand())); - Assert.False(sut1.TryInvoke(new FakeCommand())); - Assert.IsType(store.Single(c => c.Type == null)); - Assert.IsType>(store.Single(c => c.Type == typeof(int))); - Assert.IsType>(store.Single(c => c.Type == typeof(Guid))); - Assert.IsType>(store.Single(c => c.Type == typeof(DateTime))); - Assert.IsType>(store.Single(c => c.Type == typeof(Stream))); - } + Assert.NotNull(sut1); + Assert.True(sut1.TryInvoke(new FakeCommand())); + Assert.True(sut1.TryInvoke(new FakeCommand())); + Assert.True(sut1.TryInvoke(new FakeCommand())); + Assert.True(sut1.TryInvoke(new FakeCommand())); + Assert.True(sut1.TryInvoke(new FakeCommand())); + Assert.False(sut1.TryInvoke(new FakeCommand())); + Assert.False(sut1.TryInvoke(new FakeCommand())); + Assert.IsType(store.Single(c => c.Type == null)); + Assert.IsType>(store.Single(c => c.Type == typeof(int))); + Assert.IsType>(store.Single(c => c.Type == typeof(Guid))); + Assert.IsType>(store.Single(c => c.Type == typeof(DateTime))); + Assert.IsType>(store.Single(c => c.Type == typeof(Stream))); + } - [Fact] - public Task CreateFireForget_ShouldInvokeRegisteredHandlersAsync() + [Fact] + public Task CreateFireForget_ShouldInvokeRegisteredHandlersAsync() + { + var store = new List(); + var sut1 = HandlerFactory.CreateFireForget(registry => { - var store = new List(); - var sut1 = HandlerFactory.CreateFireForget(registry => + registry.RegisterAsync((c, _) => + { + store.Add(c); + return Task.CompletedTask; + }); + registry.RegisterAsync>(c => + { + store.Add(c); + return Task.CompletedTask; + }); + registry.RegisterAsync>(c => { - registry.RegisterAsync((c, _) => - { - store.Add(c); - return Task.CompletedTask; - }); - registry.RegisterAsync>(c => - { - store.Add(c); - return Task.CompletedTask; - }); - registry.RegisterAsync>(c => - { - store.Add(c); - return Task.CompletedTask; - }); - registry.RegisterAsync>(c => - { - store.Add(c); - return Task.CompletedTask; - }); - registry.RegisterAsync>(c => - { - store.Add(c); - return Task.CompletedTask; - }); + store.Add(c); + return Task.CompletedTask; }); + registry.RegisterAsync>(c => + { + store.Add(c); + return Task.CompletedTask; + }); + registry.RegisterAsync>(c => + { + store.Add(c); + return Task.CompletedTask; + }); + }); - Assert.NotNull(sut1); - Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.False(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.False(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); - Assert.IsType(store.Single(c => c.Type == null)); - Assert.IsType>(store.Single(c => c.Type == typeof(int))); - Assert.IsType>(store.Single(c => c.Type == typeof(Guid))); - Assert.IsType>(store.Single(c => c.Type == typeof(DateTime))); - Assert.IsType>(store.Single(c => c.Type == typeof(Stream))); + Assert.NotNull(sut1); + Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.True(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.False(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.False(sut1.TryInvokeAsync(new FakeCommand()).GetAwaiter().GetResult().Succeeded); + Assert.IsType(store.Single(c => c.Type == null)); + Assert.IsType>(store.Single(c => c.Type == typeof(int))); + Assert.IsType>(store.Single(c => c.Type == typeof(Guid))); + Assert.IsType>(store.Single(c => c.Type == typeof(DateTime))); + Assert.IsType>(store.Single(c => c.Type == typeof(Stream))); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - [Fact] - public void CreateRequestReply_ShouldInvokeRegisteredHandlers() + [Fact] + public void CreateRequestReply_ShouldInvokeRegisteredHandlers() + { + var sut1 = HandlerFactory.CreateRequestReply(registry => { - var sut1 = HandlerFactory.CreateRequestReply(registry => - { - registry.Register(c => c.Type); - registry.Register, Type>(c => c.Type); - registry.Register, Type>(c => c.Type); - registry.Register, Type>(c => c.Type); - registry.Register, Type>(c => c.Type); - }); + registry.Register(c => c.Type); + registry.Register, Type>(c => c.Type); + registry.Register, Type>(c => c.Type); + registry.Register, Type>(c => c.Type); + registry.Register, Type>(c => c.Type); + }); - Assert.NotNull(sut1); - Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc1)); - Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc2)); - Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc3)); - Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc4)); - Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc5)); - Assert.False(sut1.TryInvoke(new FakeCommand(), out var fc6)); - Assert.False(sut1.TryInvoke(new FakeCommand(), out var fc7)); - Assert.Null(fc1); - Assert.Equal(typeof(int), fc2); - Assert.Equal(typeof(Guid), fc3); - Assert.Equal(typeof(DateTime), fc4); - Assert.Equal(typeof(Stream), fc5); - Assert.Null(fc6); - Assert.Null(fc7); - } + Assert.NotNull(sut1); + Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc1)); + Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc2)); + Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc3)); + Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc4)); + Assert.True(sut1.TryInvoke(new FakeCommand(), out var fc5)); + Assert.False(sut1.TryInvoke(new FakeCommand(), out var fc6)); + Assert.False(sut1.TryInvoke(new FakeCommand(), out var fc7)); + Assert.Null(fc1); + Assert.Equal(typeof(int), fc2); + Assert.Equal(typeof(Guid), fc3); + Assert.Equal(typeof(DateTime), fc4); + Assert.Equal(typeof(Stream), fc5); + Assert.Null(fc6); + Assert.Null(fc7); + } - [Fact] - public async Task CreateRequestReply_ShouldInvokeRegisteredHandlersAsync() + [Fact] + public async Task CreateRequestReply_ShouldInvokeRegisteredHandlersAsync() + { + var sut1 = HandlerFactory.CreateRequestReply(registry => { - var sut1 = HandlerFactory.CreateRequestReply(registry => - { - registry.RegisterAsync((c, _) => Task.FromResult(c.Type)); - registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); - registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); - registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); - registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); - }); + registry.RegisterAsync((c, _) => Task.FromResult(c.Type)); + registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); + registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); + registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); + registry.RegisterAsync, Type>(c => Task.FromResult(c.Type)); + }); - var sut2 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut3 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut4 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut5 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut6 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut7 = await sut1.TryInvokeAsync(new FakeCommand()); - var sut8 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut2 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut3 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut4 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut5 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut6 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut7 = await sut1.TryInvokeAsync(new FakeCommand()); + var sut8 = await sut1.TryInvokeAsync(new FakeCommand()); - Assert.NotNull(sut1); - Assert.True(sut2.Succeeded); - Assert.True(sut3.Succeeded); - Assert.True(sut4.Succeeded); - Assert.True(sut5.Succeeded); - Assert.True(sut6.Succeeded); - Assert.False(sut7.Succeeded); - Assert.False(sut8.Succeeded); - Assert.Null(sut2.Result); - Assert.Equal(typeof(int), sut3.Result); - Assert.Equal(typeof(Guid), sut4.Result); - Assert.Equal(typeof(DateTime), sut5.Result); - Assert.Equal(typeof(Stream), sut6.Result); - Assert.Null(sut7.Result); - Assert.Null(sut8.Result); - } + Assert.NotNull(sut1); + Assert.True(sut2.Succeeded); + Assert.True(sut3.Succeeded); + Assert.True(sut4.Succeeded); + Assert.True(sut5.Succeeded); + Assert.True(sut6.Succeeded); + Assert.False(sut7.Succeeded); + Assert.False(sut8.Succeeded); + Assert.Null(sut2.Result); + Assert.Equal(typeof(int), sut3.Result); + Assert.Equal(typeof(Guid), sut4.Result); + Assert.Equal(typeof(DateTime), sut5.Result); + Assert.Equal(typeof(Stream), sut6.Result); + Assert.Null(sut7.Result); + Assert.Null(sut8.Result); } } diff --git a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs index 7b357710..7d672d70 100644 --- a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs @@ -2,46 +2,45 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +public class SignedMessageOptionsTest : Test { - public class SignedMessageOptionsTest : Test + public SignedMessageOptionsTest(ITestOutputHelper helper) : base(helper) { - public SignedMessageOptionsTest(ITestOutputHelper helper) : base(helper) - { - } + } - [Fact] - public void ValidateOptions_WhenSignatureSecretIsNull_ShouldThrowInvalidOperationException() - { - var options = new SignedMessageOptions(); - options.SignatureSecret = null; + [Fact] + public void ValidateOptions_WhenSignatureSecretIsNull_ShouldThrowInvalidOperationException() + { + var options = new SignedMessageOptions(); + options.SignatureSecret = null; - var ex = Assert.Throws(() => options.ValidateOptions()); + var ex = Assert.Throws(() => options.ValidateOptions()); - TestOutput.WriteLine(ex.Message); + TestOutput.WriteLine(ex.Message); - Assert.Equal("Operation is not valid due to the current state of the object. (Expression 'SignatureSecret == null || SignatureSecret.Length == 0')", ex.Message); - } + Assert.Equal("Operation is not valid due to the current state of the object. (Expression 'SignatureSecret == null || SignatureSecret.Length == 0')", ex.Message); + } - [Fact] - public void ValidateOptions_WhenSignatureSecretIsEmpty_ShouldThrowInvalidOperationException() - { - var options = new SignedMessageOptions(); - options.SignatureSecret = new byte[0]; + [Fact] + public void ValidateOptions_WhenSignatureSecretIsEmpty_ShouldThrowInvalidOperationException() + { + var options = new SignedMessageOptions(); + options.SignatureSecret = new byte[0]; - var ex = Assert.Throws(() => options.ValidateOptions()); + var ex = Assert.Throws(() => options.ValidateOptions()); - TestOutput.WriteLine(ex.Message); + TestOutput.WriteLine(ex.Message); - Assert.Equal("Operation is not valid due to the current state of the object. (Expression 'SignatureSecret == null || SignatureSecret.Length == 0')", ex.Message); - } + Assert.Equal("Operation is not valid due to the current state of the object. (Expression 'SignatureSecret == null || SignatureSecret.Length == 0')", ex.Message); + } - [Fact] - public void ValidateOptions_WhenAllPropertiesAreValid_ShouldNotThrowException() - { - var options = new SignedMessageOptions(); - options.SignatureSecret = new byte[] { 1, 2, 3 }; - options.ValidateOptions(); - } + [Fact] + public void ValidateOptions_WhenAllPropertiesAreValid_ShouldNotThrowException() + { + var options = new SignedMessageOptions(); + options.SignatureSecret = new byte[] { 1, 2, 3 }; + options.ValidateOptions(); } } diff --git a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs index ea6992c6..4d5bffb2 100644 --- a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs @@ -4,83 +4,82 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +public class SignedMessageTest : Test { - public class SignedMessageTest : Test + public SignedMessageTest(ITestOutputHelper helper) : base(helper) + { + } + + [Fact] + public void Constructor_WhenMessageIsNull_ShouldThrowArgumentNullException() { - public SignedMessageTest(ITestOutputHelper helper) : base(helper) - { - } - - [Fact] - public void Constructor_WhenMessageIsNull_ShouldThrowArgumentNullException() - { - var ex = Assert.Throws(() => new SignedMessage(null, "signature")); - - TestOutput.WriteLine(ex.Message); - - Assert.Equal("Value cannot be null. (Parameter 'message')", ex.Message); - } - - [Fact] - public void Constructor_WhenSignatureIsNull_ShouldThrowArgumentNullException() - { - var uuid = Guid.NewGuid(); - var fullName = "John Doe"; - var email = "jdoe@me.com"; - var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); - var ex = Assert.Throws(() => new SignedMessage(message, null)); - - TestOutput.WriteLine(ex.Message); - - Assert.Equal("Value cannot be null. (Parameter 'signature')", ex.Message); - } - - [Fact] - public void Constructor_WhenSignatureIsEmpty_ShouldThrowArgumentException() - { - var uuid = Guid.NewGuid(); - var fullName = "John Doe"; - var email = "jdoe@me.com"; - var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); - var ex = Assert.Throws(() => new SignedMessage(message, string.Empty)); - - TestOutput.WriteLine(ex.Message); - - Assert.Equal("Value cannot be empty. (Parameter 'signature')", ex.Message); - } - - [Fact] - public void Constructor_WhenSignatureIsWhitespace_ShouldThrowArgumentException() - { - var uuid = Guid.NewGuid(); - var fullName = "John Doe"; - var email = "jdoe@me.com"; - var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); - var ex = Assert.Throws(() => new SignedMessage(message, " ")); - - TestOutput.WriteLine(ex.Message); - - Assert.Equal("Value cannot consist only of white-space characters. (Parameter 'signature')", ex.Message); - } - - [Fact] - public void Constructor_WhenAllPropertiesAreValid_ShouldCreateInstance() - { - var uuid = Guid.NewGuid(); - var fullName = "John Doe"; - var email = "jdoe@me.com"; - var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); - var signature = "signature"; - var signedMessage = new SignedMessage(message, signature); - - Assert.NotNull(signedMessage); - Assert.Equal(message.Id, signedMessage.Id); - Assert.Equal(message.Source, signedMessage.Source); - Assert.Equal(message.Type, signedMessage.Type); - Assert.Equal(message.Time, signedMessage.Time); - Assert.Equal(message.Data, signedMessage.Data); - Assert.Equal(signature, signedMessage.Signature); - } + var ex = Assert.Throws(() => new SignedMessage(null, "signature")); + + TestOutput.WriteLine(ex.Message); + + Assert.Equal("Value cannot be null. (Parameter 'message')", ex.Message); + } + + [Fact] + public void Constructor_WhenSignatureIsNull_ShouldThrowArgumentNullException() + { + var uuid = Guid.NewGuid(); + var fullName = "John Doe"; + var email = "jdoe@me.com"; + var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); + var ex = Assert.Throws(() => new SignedMessage(message, null)); + + TestOutput.WriteLine(ex.Message); + + Assert.Equal("Value cannot be null. (Parameter 'signature')", ex.Message); + } + + [Fact] + public void Constructor_WhenSignatureIsEmpty_ShouldThrowArgumentException() + { + var uuid = Guid.NewGuid(); + var fullName = "John Doe"; + var email = "jdoe@me.com"; + var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); + var ex = Assert.Throws(() => new SignedMessage(message, string.Empty)); + + TestOutput.WriteLine(ex.Message); + + Assert.Equal("Value cannot be empty. (Parameter 'signature')", ex.Message); + } + + [Fact] + public void Constructor_WhenSignatureIsWhitespace_ShouldThrowArgumentException() + { + var uuid = Guid.NewGuid(); + var fullName = "John Doe"; + var email = "jdoe@me.com"; + var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); + var ex = Assert.Throws(() => new SignedMessage(message, " ")); + + TestOutput.WriteLine(ex.Message); + + Assert.Equal("Value cannot consist only of white-space characters. (Parameter 'signature')", ex.Message); + } + + [Fact] + public void Constructor_WhenAllPropertiesAreValid_ShouldCreateInstance() + { + var uuid = Guid.NewGuid(); + var fullName = "John Doe"; + var email = "jdoe@me.com"; + var message = new Message("MyId", "uri:source".ToUri(), nameof(CreateAccount), new CreateAccount(uuid, fullName, email)); + var signature = "signature"; + var signedMessage = new SignedMessage(message, signature); + + Assert.NotNull(signedMessage); + Assert.Equal(message.Id, signedMessage.Id); + Assert.Equal(message.Source, signedMessage.Source); + Assert.Equal(message.Type, signedMessage.Type); + Assert.Equal(message.Time, signedMessage.Time); + Assert.Equal(message.Data, signedMessage.Data); + Assert.Equal(signature, signedMessage.Signature); } } diff --git a/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs b/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs index 177a076d..3ebcfc20 100644 --- a/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs @@ -3,54 +3,53 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class MessageOptionsTest : Test { - public class MessageOptionsTest : Test + public MessageOptionsTest(ITestOutputHelper output) : base(output) { - public MessageOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void MessageOptions_ShouldHaveDefaultValues() - { - var sut = new MessageOptions(); + [Fact] + public void MessageOptions_ShouldHaveDefaultValues() + { + var sut = new MessageOptions(); - Assert.NotNull(sut.MessageId); - Assert.Null(sut.Time); - } + Assert.NotNull(sut.MessageId); + Assert.Null(sut.Time); + } - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - public void MessageOptions_ThrowsInvalidOperationException_WhenMessageIdIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string messageId) + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void MessageOptions_ThrowsInvalidOperationException_WhenMessageIdIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string messageId) + { + var sut1 = new MessageOptions { - var sut1 = new MessageOptions - { - MessageId = messageId - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(MessageOptions.MessageId)}.IsNullOrWhiteSpace()')", sut2.Message); - Assert.Equal($"{nameof(MessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void MessageOptions_ThrowsInvalidOperationException_WhenTimeIsLocal() + MessageId = messageId + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(MessageOptions.MessageId)}.IsNullOrWhiteSpace()')", sut2.Message); + Assert.Equal($"{nameof(MessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } + + [Fact] + public void MessageOptions_ThrowsInvalidOperationException_WhenTimeIsLocal() + { + var sut1 = new MessageOptions { - var sut1 = new MessageOptions - { - Time = DateTime.Now - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(MessageOptions.Time)}.HasValue && {nameof(MessageOptions.Time)}.Value.Kind != DateTimeKind.Utc')", sut2.Message); - Assert.Equal($"{nameof(MessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Time = DateTime.Now + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(MessageOptions.Time)}.HasValue && {nameof(MessageOptions.Time)}.Value.Kind != DateTimeKind.Utc')", sut2.Message); + Assert.Equal($"{nameof(MessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); } } diff --git a/test/Savvyio.Core.Tests/Messaging/MessageTest.cs b/test/Savvyio.Core.Tests/Messaging/MessageTest.cs index c46f2886..4fa8b364 100644 --- a/test/Savvyio.Core.Tests/Messaging/MessageTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/MessageTest.cs @@ -6,60 +6,59 @@ using Savvyio.Assets; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class MessageTest : Test { - public class MessageTest : Test + public MessageTest(ITestOutputHelper output) : base(output) { - public MessageTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_WithRequiredArguments_RemainingArgumentsShouldHaveDefaultValues() - { - var id = Generate.RandomString(16); - var source = "urn:source".ToUri(); - var dataUuid = Guid.NewGuid(); - var dataNumber = Generate.RandomNumber(); - var data = new RootDummyRequest(dataUuid, dataNumber); - var utcNow = DateTime.UtcNow; - var sut = new Message(id, source, nameof(RootDummyRequest), data); + [Fact] + public void Ctor_WithRequiredArguments_RemainingArgumentsShouldHaveDefaultValues() + { + var id = Generate.RandomString(16); + var source = "urn:source".ToUri(); + var dataUuid = Guid.NewGuid(); + var dataNumber = Generate.RandomNumber(); + var data = new RootDummyRequest(dataUuid, dataNumber); + var utcNow = DateTime.UtcNow; + var sut = new Message(id, source, nameof(RootDummyRequest), data); - TestOutput.WriteLine(sut.Data.ToString()); + TestOutput.WriteLine(sut.Data.ToString()); - var convertedTime = sut.Time!; - Assert.Equal(id, sut.Id); - Assert.Equal(source.OriginalString, sut.Source); - Assert.Equal(data, sut.Data); - Assert.Equal(data.GetType().ToFullNameIncludingAssemblyName(), sut.Data.GetMemberType()); - Assert.Equal(nameof(RootDummyRequest), sut.Type); - Assert.Equal(DateTimeKind.Utc, convertedTime.Value.Kind); - Assert.InRange(convertedTime.Value, utcNow.Subtract(TimeSpan.FromSeconds(2)), utcNow.Add(TimeSpan.FromSeconds(2))); - } + var convertedTime = sut.Time!; + Assert.Equal(id, sut.Id); + Assert.Equal(source.OriginalString, sut.Source); + Assert.Equal(data, sut.Data); + Assert.Equal(data.GetType().ToFullNameIncludingAssemblyName(), sut.Data.GetMemberType()); + Assert.Equal(nameof(RootDummyRequest), sut.Type); + Assert.Equal(DateTimeKind.Utc, convertedTime.Value.Kind); + Assert.InRange(convertedTime.Value, utcNow.Subtract(TimeSpan.FromSeconds(2)), utcNow.Add(TimeSpan.FromSeconds(2))); + } - [Fact] - public void Ctor_WithBothRequiredAndOptionalArguments() - { - var id = Generate.RandomString(16); - var source = "urn:source".ToUri(); - var dataUuid = Guid.NewGuid(); - var dataNumber = Generate.RandomNumber(); - var dataType = typeof(DummyRequest); - var type = "com.example.someevent"; - var data = new RootDummyRequest(dataUuid, dataNumber).SetMemberType(dataType); - var utcNow = DateTime.UtcNow; - var sut1 = new Message(id, source, type, data, utcNow); + [Fact] + public void Ctor_WithBothRequiredAndOptionalArguments() + { + var id = Generate.RandomString(16); + var source = "urn:source".ToUri(); + var dataUuid = Guid.NewGuid(); + var dataNumber = Generate.RandomNumber(); + var dataType = typeof(DummyRequest); + var type = "com.example.someevent"; + var data = new RootDummyRequest(dataUuid, dataNumber).SetMemberType(dataType); + var utcNow = DateTime.UtcNow; + var sut1 = new Message(id, source, type, data, utcNow); - TestOutput.WriteLine(sut1.Data.ToString()); + TestOutput.WriteLine(sut1.Data.ToString()); - var convertedTime = sut1.Time!; - Assert.Equal(id, sut1.Id); - Assert.Equal(source.OriginalString, sut1.Source); - Assert.Equal(data, sut1.Data); - Assert.Equal(type, sut1.Type); - Assert.Equal(dataType.ToFullNameIncludingAssemblyName(), sut1.Data.GetMemberType()); - Assert.Equal(DateTimeKind.Utc, convertedTime.Value.Kind); - Assert.Equal(utcNow, convertedTime); - } + var convertedTime = sut1.Time!; + Assert.Equal(id, sut1.Id); + Assert.Equal(source.OriginalString, sut1.Source); + Assert.Equal(data, sut1.Data); + Assert.Equal(type, sut1.Type); + Assert.Equal(dataType.ToFullNameIncludingAssemblyName(), sut1.Data.GetMemberType()); + Assert.Equal(DateTimeKind.Utc, convertedTime.Value.Kind); + Assert.Equal(utcNow, convertedTime); } } diff --git a/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs index 14416b9b..a68f79f2 100644 --- a/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs @@ -6,193 +6,192 @@ using Cuemon.Reflection; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class MetadataDictionaryTest : Test { - public class MetadataDictionaryTest : Test + public MetadataDictionaryTest(ITestOutputHelper output) : base(output) { - public MetadataDictionaryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Indexer_ShouldGetAndSetElementWithSpecifiedKey() - { - var sut = new MetadataDictionary(); - sut["key1"] = "value"; - sut["key2"] = Guid.Empty; - sut["key3"] = int.MaxValue; - - Assert.Equal(sut["key1"], "value"); - Assert.Equal(sut["key2"], Guid.Empty); - Assert.Equal(sut["key3"], int.MaxValue); - } + [Fact] + public void Indexer_ShouldGetAndSetElementWithSpecifiedKey() + { + var sut = new MetadataDictionary(); + sut["key1"] = "value"; + sut["key2"] = Guid.Empty; + sut["key3"] = int.MaxValue; + + Assert.Equal(sut["key1"], "value"); + Assert.Equal(sut["key2"], Guid.Empty); + Assert.Equal(sut["key3"], int.MaxValue); + } - [Fact] - public void ReservedKeywords_ShouldMatchNumberOfPublicConst() + [Fact] + public void ReservedKeywords_ShouldMatchNumberOfPublicConst() + { + var sut = typeof(MetadataDictionary); + var mr = new MemberReflection(o => { - var sut = typeof(MetadataDictionary); - var mr = new MemberReflection(o => - { - o.ExcludeInheritancePath = true; - }); + o.ExcludeInheritancePath = true; + }); - var reservedKeywords = MetadataDictionary.ReservedKeywords; - var keywordConstants = sut.GetFields(mr.Flags).Where(fi => fi.IsPublic).Select(fi => fi.Name); + var reservedKeywords = MetadataDictionary.ReservedKeywords; + var keywordConstants = sut.GetFields(mr.Flags).Where(fi => fi.IsPublic).Select(fi => fi.Name); - Assert.Equal(reservedKeywords, keywordConstants); - } + Assert.Equal(reservedKeywords, keywordConstants); + } - [Fact] - public void Count_ShouldMatchNumberOfElements() + [Fact] + public void Count_ShouldMatchNumberOfElements() + { + var sut = new MetadataDictionary(); + for (var i = 0; i < 10; i++) { - var sut = new MetadataDictionary(); - for (var i = 0; i < 10; i++) - { - sut.Add(i.ToString(), i); - } - - Assert.Equal(sut.Count, 10); + sut.Add(i.ToString(), i); } - [Fact] - public void IsReadOnly_ShouldBeFalse() - { - var sut = new MetadataDictionary(); - - Assert.False(sut.IsReadOnly); - } + Assert.Equal(sut.Count, 10); + } - [Fact] - public void Keys_ShouldAllBeNumbers() - { - var sut = new MetadataDictionary(); - for (var i = 0; i < 10; i++) - { - sut.Add(i.ToString(), i); - } + [Fact] + public void IsReadOnly_ShouldBeFalse() + { + var sut = new MetadataDictionary(); - Assert.Equal(Generate.RangeOf(10, i => i.ToString()), sut.Keys); - } + Assert.False(sut.IsReadOnly); + } - [Fact] - public void Values_ShouldAllBeNumbers() + [Fact] + public void Keys_ShouldAllBeNumbers() + { + var sut = new MetadataDictionary(); + for (var i = 0; i < 10; i++) { - var sut = new MetadataDictionary(); - for (var i = 0; i < 10; i++) - { - sut.Add(i.ToString(), i); - } - - Assert.Equal(Generate.RangeOf(10, i => i), sut.Values.Cast()); + sut.Add(i.ToString(), i); } - [Fact] - public void Add_ShouldAddElementWithSpecifiedKey() + Assert.Equal(Generate.RangeOf(10, i => i.ToString()), sut.Keys); + } + + [Fact] + public void Values_ShouldAllBeNumbers() + { + var sut = new MetadataDictionary(); + for (var i = 0; i < 10; i++) { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); - - Assert.Equal(sut["key1"], "value"); - Assert.Equal(sut["key2"], Guid.Empty); - Assert.Equal(sut["key3"], int.MaxValue); + sut.Add(i.ToString(), i); } - [Fact] - public void Clear_ShouldRemoveAllElements() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); - sut.Clear(); + Assert.Equal(Generate.RangeOf(10, i => i), sut.Values.Cast()); + } - Assert.Empty(sut); - } + [Fact] + public void Add_ShouldAddElementWithSpecifiedKey() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); + + Assert.Equal(sut["key1"], "value"); + Assert.Equal(sut["key2"], Guid.Empty); + Assert.Equal(sut["key3"], int.MaxValue); + } - [Fact] - public void CopyTo_ShouldCopyElementsToArray() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); + [Fact] + public void Clear_ShouldRemoveAllElements() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); + sut.Clear(); - var col = new KeyValuePair[3]; - sut.CopyTo(col, 0); + Assert.Empty(sut); + } - Assert.Equal(sut, col); - } + [Fact] + public void CopyTo_ShouldCopyElementsToArray() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); - [Fact] - public void Contains_ShouldFindMatchingItems() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); - - Assert.True(sut.Contains(new KeyValuePair("key1", "value"))); - Assert.True(sut.Contains(new KeyValuePair("key2", Guid.Empty))); - Assert.True(sut.Contains(new KeyValuePair("key3", int.MaxValue))); - Assert.False(sut.Contains(new KeyValuePair("key4", DateTime.MaxValue))); - } + var col = new KeyValuePair[3]; + sut.CopyTo(col, 0); - [Fact] - public void ContainsKey_ShouldFindMatchingItems() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); - - Assert.True(sut.ContainsKey("key1")); - Assert.True(sut.ContainsKey("key2")); - Assert.True(sut.ContainsKey("key3")); - Assert.False(sut.ContainsKey("key4")); - } + Assert.Equal(sut, col); + } - [Fact] - public void Remove_ShouldRemoveItemByKey() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); + [Fact] + public void Contains_ShouldFindMatchingItems() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); + + Assert.True(sut.Contains(new KeyValuePair("key1", "value"))); + Assert.True(sut.Contains(new KeyValuePair("key2", Guid.Empty))); + Assert.True(sut.Contains(new KeyValuePair("key3", int.MaxValue))); + Assert.False(sut.Contains(new KeyValuePair("key4", DateTime.MaxValue))); + } - sut.Remove("key1"); + [Fact] + public void ContainsKey_ShouldFindMatchingItems() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); + + Assert.True(sut.ContainsKey("key1")); + Assert.True(sut.ContainsKey("key2")); + Assert.True(sut.ContainsKey("key3")); + Assert.False(sut.ContainsKey("key4")); + } - Assert.False(sut.ContainsKey("key1")); - Assert.True(sut.Count == 2, "sut.Count == 2"); - } + [Fact] + public void Remove_ShouldRemoveItemByKey() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); - [Fact] - public void Remove_ShouldRemoveItemByKeyValuePair() - { - var kvp = new KeyValuePair("key1", "value"); - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); + sut.Remove("key1"); - sut.Remove(kvp); + Assert.False(sut.ContainsKey("key1")); + Assert.True(sut.Count == 2, "sut.Count == 2"); + } - Assert.False(sut.Contains(kvp)); - Assert.True(sut.Count == 2, "sut.Count == 2"); - } + [Fact] + public void Remove_ShouldRemoveItemByKeyValuePair() + { + var kvp = new KeyValuePair("key1", "value"); + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); - [Fact] - public void TryGetValue_ShouldRetrieveValue() - { - var sut = new MetadataDictionary(); - sut.Add("key1", "value"); - sut.Add("key2", Guid.Empty); - sut.Add(new KeyValuePair("key3", int.MaxValue)); + sut.Remove(kvp); - sut.TryGetValue("key2", out var key2Value); + Assert.False(sut.Contains(kvp)); + Assert.True(sut.Count == 2, "sut.Count == 2"); + } - Assert.Equal(Guid.Empty, key2Value); - } + [Fact] + public void TryGetValue_ShouldRetrieveValue() + { + var sut = new MetadataDictionary(); + sut.Add("key1", "value"); + sut.Add("key2", Guid.Empty); + sut.Add(new KeyValuePair("key3", int.MaxValue)); + + sut.TryGetValue("key2", out var key2Value); + + Assert.Equal(Guid.Empty, key2Value); } } diff --git a/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs b/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs index 28da0db3..9d1eccb4 100644 --- a/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs +++ b/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs @@ -3,170 +3,169 @@ using Cuemon.Extensions.Reflection; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class MetadataExtensionsTest : Test { - public class MetadataExtensionsTest : Test + public MetadataExtensionsTest(ITestOutputHelper output) : base(output) { - public MetadataExtensionsTest(ITestOutputHelper output) : base(output) - { - - } + + } - private class TestMetadata : IMetadata - { - public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); - } + private class TestMetadata : IMetadata + { + public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); + } - [Fact] - public void GetCausationId_ShouldReturnCausationId() - { - var request = new TestMetadata(); - request.Metadata[MetadataDictionary.CausationId] = "causation-id"; + [Fact] + public void GetCausationId_ShouldReturnCausationId() + { + var request = new TestMetadata(); + request.Metadata[MetadataDictionary.CausationId] = "causation-id"; - var result = request.GetCausationId(); + var result = request.GetCausationId(); - Assert.Equal("causation-id", result); - } + Assert.Equal("causation-id", result); + } - [Fact] - public void GetCorrelationId_ShouldReturnCorrelationId() - { - var request = new TestMetadata(); - request.Metadata[MetadataDictionary.CorrelationId] = "correlation-id"; + [Fact] + public void GetCorrelationId_ShouldReturnCorrelationId() + { + var request = new TestMetadata(); + request.Metadata[MetadataDictionary.CorrelationId] = "correlation-id"; - var result = request.GetCorrelationId(); + var result = request.GetCorrelationId(); - Assert.Equal("correlation-id", result); - } + Assert.Equal("correlation-id", result); + } - [Fact] - public void GetRequestId_ShouldReturnRequestId() - { - var request = new TestMetadata(); - request.SetRequestId("request-id"); + [Fact] + public void GetRequestId_ShouldReturnRequestId() + { + var request = new TestMetadata(); + request.SetRequestId("request-id"); - var result = request.GetRequestId(); + var result = request.GetRequestId(); - Assert.Equal("request-id", result); - } + Assert.Equal("request-id", result); + } - [Fact] - public void GetMemberType_ShouldReturnMemberType() - { - var request = new TestMetadata(); - request.Metadata[MetadataDictionary.MemberType] = "member-type"; + [Fact] + public void GetMemberType_ShouldReturnMemberType() + { + var request = new TestMetadata(); + request.Metadata[MetadataDictionary.MemberType] = "member-type"; - var result = request.GetMemberType(); + var result = request.GetMemberType(); - Assert.Equal("member-type", result); - } + Assert.Equal("member-type", result); + } - [Fact] - public void SetCausationId_ShouldSetCausationId() - { - var request = new TestMetadata(); + [Fact] + public void SetCausationId_ShouldSetCausationId() + { + var request = new TestMetadata(); - request.SetCausationId("new-causation-id"); + request.SetCausationId("new-causation-id"); - Assert.Equal("new-causation-id", request.Metadata[MetadataDictionary.CausationId]); - } + Assert.Equal("new-causation-id", request.Metadata[MetadataDictionary.CausationId]); + } - [Fact] - public void SetCorrelationId_ShouldSetCorrelationId() - { - var request = new TestMetadata(); + [Fact] + public void SetCorrelationId_ShouldSetCorrelationId() + { + var request = new TestMetadata(); - request.SetCorrelationId("new-correlation-id"); + request.SetCorrelationId("new-correlation-id"); - Assert.Equal("new-correlation-id", request.Metadata[MetadataDictionary.CorrelationId]); - } + Assert.Equal("new-correlation-id", request.Metadata[MetadataDictionary.CorrelationId]); + } - [Fact] - public void SetRequestId_ShouldSetRequestId() - { - var request = new TestMetadata(); + [Fact] + public void SetRequestId_ShouldSetRequestId() + { + var request = new TestMetadata(); - request.SetRequestId("new-request-id"); + request.SetRequestId("new-request-id"); - Assert.Equal("new-request-id", request.Metadata[MetadataDictionary.RequestId]); - } + Assert.Equal("new-request-id", request.Metadata[MetadataDictionary.RequestId]); + } - [Fact] - public void SetEventId_ShouldSetEventId() - { - var request = new TestMetadata(); + [Fact] + public void SetEventId_ShouldSetEventId() + { + var request = new TestMetadata(); - request.SetEventId("new-event-id"); + request.SetEventId("new-event-id"); - Assert.Equal("new-event-id", request.Metadata[MetadataDictionary.EventId]); - } + Assert.Equal("new-event-id", request.Metadata[MetadataDictionary.EventId]); + } - [Fact] - public void SetTimestamp_ShouldSetTimestamp() - { - var request = new TestMetadata(); - var timestamp = DateTime.UtcNow; + [Fact] + public void SetTimestamp_ShouldSetTimestamp() + { + var request = new TestMetadata(); + var timestamp = DateTime.UtcNow; - request.SetTimestamp(timestamp); + request.SetTimestamp(timestamp); - Assert.Equal(timestamp, request.Metadata[MetadataDictionary.Timestamp]); - } + Assert.Equal(timestamp, request.Metadata[MetadataDictionary.Timestamp]); + } - [Fact] - public void SetTimestamp_ShouldSetCurrentUtcTimestamp_WhenNoTimestampProvided() - { - var request = new TestMetadata(); + [Fact] + public void SetTimestamp_ShouldSetCurrentUtcTimestamp_WhenNoTimestampProvided() + { + var request = new TestMetadata(); - request.SetTimestamp(); + request.SetTimestamp(); - Assert.True(request.Metadata.ContainsKey(MetadataDictionary.Timestamp)); - Assert.IsType(request.Metadata[MetadataDictionary.Timestamp]); - } + Assert.True(request.Metadata.ContainsKey(MetadataDictionary.Timestamp)); + Assert.IsType(request.Metadata[MetadataDictionary.Timestamp]); + } - [Fact] - public void SetMemberType_ShouldSetMemberType() - { - var request = new TestMetadata(); - var type = typeof(string); + [Fact] + public void SetMemberType_ShouldSetMemberType() + { + var request = new TestMetadata(); + var type = typeof(string); - request.SetMemberType(type); + request.SetMemberType(type); - Assert.Equal(type.ToFullNameIncludingAssemblyName(), request.Metadata[MetadataDictionary.MemberType]); - } + Assert.Equal(type.ToFullNameIncludingAssemblyName(), request.Metadata[MetadataDictionary.MemberType]); + } - [Fact] - public void SaveMetadata_ShouldAddOrUpdateMetadata() - { - var request = new TestMetadata(); + [Fact] + public void SaveMetadata_ShouldAddOrUpdateMetadata() + { + var request = new TestMetadata(); - request.SaveMetadata("key", "value"); + request.SaveMetadata("key", "value"); - Assert.Equal("value", request.Metadata["key"]); - } + Assert.Equal("value", request.Metadata["key"]); + } - [Fact] - public void MergeMetadata_ShouldCopyMetadataFromSourceToDestination() - { - var source = new TestMetadata(); - source.Metadata["key1"] = "value1"; - var destination = new TestMetadata(); + [Fact] + public void MergeMetadata_ShouldCopyMetadataFromSourceToDestination() + { + var source = new TestMetadata(); + source.Metadata["key1"] = "value1"; + var destination = new TestMetadata(); - destination.MergeMetadata(source); + destination.MergeMetadata(source); - Assert.Equal("value1", destination.Metadata["key1"]); - } + Assert.Equal("value1", destination.Metadata["key1"]); + } - [Fact] - public void MergeMetadata_ShouldNotOverwriteExistingMetadata() - { - var source = new TestMetadata(); - source.Metadata["key1"] = "value1"; - var destination = new TestMetadata(); - destination.Metadata["key1"] = "existing-value"; + [Fact] + public void MergeMetadata_ShouldNotOverwriteExistingMetadata() + { + var source = new TestMetadata(); + source.Metadata["key1"] = "value1"; + var destination = new TestMetadata(); + destination.Metadata["key1"] = "existing-value"; - destination.MergeMetadata(source); + destination.MergeMetadata(source); - Assert.Equal("existing-value", destination.Metadata["key1"]); - } + Assert.Equal("existing-value", destination.Metadata["key1"]); } } diff --git a/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs b/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs index d99b7c50..75628352 100644 --- a/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs +++ b/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs @@ -6,29 +6,28 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class OrphanedHandlerExceptionTest : Test { - public class OrphanedHandlerExceptionTest : Test + public OrphanedHandlerExceptionTest(ITestOutputHelper output) : base(output) { - public OrphanedHandlerExceptionTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void Ctor_ShouldBeSerializableAndHaveCorrectDefaultMessage() - { - var sut = OrphanedHandlerException.Create(new FakeCommand(), "fake"); + } - using (var stream = JsonFormatter.SerializeObject(sut)) - { - TestOutput.WriteLine(stream.ToEncodedString(o => o.LeaveOpen = true)); + [Fact] + public void Ctor_ShouldBeSerializableAndHaveCorrectDefaultMessage() + { + var sut = OrphanedHandlerException.Create(new FakeCommand(), "fake"); - var desEx = JsonFormatter.DeserializeObject(stream); + using (var stream = JsonFormatter.SerializeObject(sut)) + { + TestOutput.WriteLine(stream.ToEncodedString(o => o.LeaveOpen = true)); - Assert.Equal(sut.Message, desEx.Message); - Assert.Equal(sut.ToString(), desEx.ToString()); - } + var desEx = JsonFormatter.DeserializeObject(stream); + Assert.Equal(sut.Message, desEx.Message); + Assert.Equal(sut.ToString(), desEx.ToString()); } + } } diff --git a/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs b/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs index 48f23786..8da5005d 100644 --- a/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs +++ b/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs @@ -5,181 +5,180 @@ using Savvyio.Reflection; using Xunit; -namespace Savvyio.Reflection +namespace Savvyio.Reflection; + +public class AssemblyContextTest : Test { - public class AssemblyContextTest : Test + public AssemblyContextTest(ITestOutputHelper output) : base(output) { - public AssemblyContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CurrentDomainAssemblies_ShouldReturnNonEmptyList() - { - var assemblies = AssemblyContext.CurrentDomainAssemblies; + [Fact] + public void CurrentDomainAssemblies_ShouldReturnNonEmptyList() + { + var assemblies = AssemblyContext.CurrentDomainAssemblies; - Assert.NotNull(assemblies); - Assert.NotEmpty(assemblies); - } + Assert.NotNull(assemblies); + Assert.NotEmpty(assemblies); + } - [Fact] - public void CurrentDomainAssemblies_ShouldNotContainSavvyioCoreAssembly() - { - var savvyioCoreAssembly = typeof(AssemblyContext).Assembly; + [Fact] + public void CurrentDomainAssemblies_ShouldNotContainSavvyioCoreAssembly() + { + var savvyioCoreAssembly = typeof(AssemblyContext).Assembly; - Assert.DoesNotContain(savvyioCoreAssembly, AssemblyContext.CurrentDomainAssemblies); - } + Assert.DoesNotContain(savvyioCoreAssembly, AssemblyContext.CurrentDomainAssemblies); + } - [Fact] - public void CurrentDomainAssemblies_ShouldNotContainSystemOrMicrosoftAssemblies() + [Fact] + public void CurrentDomainAssemblies_ShouldNotContainSystemOrMicrosoftAssemblies() + { + foreach (var assembly in AssemblyContext.CurrentDomainAssemblies) { - foreach (var assembly in AssemblyContext.CurrentDomainAssemblies) - { - Assert.False(assembly.FullName?.StartsWith(nameof(System), StringComparison.Ordinal), - $"Assembly '{assembly.FullName}' should have been filtered out."); - Assert.False(assembly.FullName?.StartsWith(nameof(Microsoft), StringComparison.Ordinal), - $"Assembly '{assembly.FullName}' should have been filtered out."); - } + Assert.False(assembly.FullName?.StartsWith(nameof(System), StringComparison.Ordinal), + $"Assembly '{assembly.FullName}' should have been filtered out."); + Assert.False(assembly.FullName?.StartsWith(nameof(Microsoft), StringComparison.Ordinal), + $"Assembly '{assembly.FullName}' should have been filtered out."); } + } - [Fact] - public void AssemblyFilterCallback_ShouldReturnDefaultNonNullDelegate() - { - var callback = AssemblyContext.AssemblyFilterCallback; + [Fact] + public void AssemblyFilterCallback_ShouldReturnDefaultNonNullDelegate() + { + var callback = AssemblyContext.AssemblyFilterCallback; - Assert.NotNull(callback); - } + Assert.NotNull(callback); + } - [Fact] - public void AssemblyFilterCallback_ShouldAcceptCustomDelegate() + [Fact] + public void AssemblyFilterCallback_ShouldAcceptCustomDelegate() + { + var original = AssemblyContext.AssemblyFilterCallback; + try { - var original = AssemblyContext.AssemblyFilterCallback; - try - { - Func custom = _ => true; - AssemblyContext.AssemblyFilterCallback = custom; - - Assert.Same(custom, AssemblyContext.AssemblyFilterCallback); - } - finally - { - AssemblyContext.AssemblyFilterCallback = original; - } - } + Func custom = _ => true; + AssemblyContext.AssemblyFilterCallback = custom; - [Fact] - public void AssemblyFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + Assert.Same(custom, AssemblyContext.AssemblyFilterCallback); + } + finally { - Assert.Throws(() => AssemblyContext.AssemblyFilterCallback = null); + AssemblyContext.AssemblyFilterCallback = original; } + } - [Fact] - public void AssemblyDependenciesCallback_ShouldReturnDefaultNonNullDelegate() - { - var callback = AssemblyContext.AssemblyDependenciesCallback; + [Fact] + public void AssemblyFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + { + Assert.Throws(() => AssemblyContext.AssemblyFilterCallback = null); + } - Assert.NotNull(callback); - } + [Fact] + public void AssemblyDependenciesCallback_ShouldReturnDefaultNonNullDelegate() + { + var callback = AssemblyContext.AssemblyDependenciesCallback; + + Assert.NotNull(callback); + } - [Fact] - public void AssemblyDependenciesCallback_ShouldAcceptCustomDelegate() + [Fact] + public void AssemblyDependenciesCallback_ShouldAcceptCustomDelegate() + { + var original = AssemblyContext.AssemblyDependenciesCallback; + try { - var original = AssemblyContext.AssemblyDependenciesCallback; - try - { - Func> custom = a => Enumerable.Repeat(a, 1); - AssemblyContext.AssemblyDependenciesCallback = custom; - - Assert.Same(custom, AssemblyContext.AssemblyDependenciesCallback); - } - finally - { - AssemblyContext.AssemblyDependenciesCallback = original; - } - } + Func> custom = a => Enumerable.Repeat(a, 1); + AssemblyContext.AssemblyDependenciesCallback = custom; - [Fact] - public void AssemblyDependenciesCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + Assert.Same(custom, AssemblyContext.AssemblyDependenciesCallback); + } + finally { - Assert.Throws(() => AssemblyContext.AssemblyDependenciesCallback = null); + AssemblyContext.AssemblyDependenciesCallback = original; } + } - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldReturnDefaultNonNullDelegate() - { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; + [Fact] + public void AssemblyDependenciesCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + { + Assert.Throws(() => AssemblyContext.AssemblyDependenciesCallback = null); + } - Assert.NotNull(callback); - } + [Fact] + public void AssemblyDependenciesFilterCallback_ShouldReturnDefaultNonNullDelegate() + { + var callback = AssemblyContext.AssemblyDependenciesFilterCallback; - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldAcceptCustomDelegate() + Assert.NotNull(callback); + } + + [Fact] + public void AssemblyDependenciesFilterCallback_ShouldAcceptCustomDelegate() + { + var original = AssemblyContext.AssemblyDependenciesFilterCallback; + try { - var original = AssemblyContext.AssemblyDependenciesFilterCallback; - try - { - Func custom = _ => true; - AssemblyContext.AssemblyDependenciesFilterCallback = custom; - - Assert.Same(custom, AssemblyContext.AssemblyDependenciesFilterCallback); - } - finally - { - AssemblyContext.AssemblyDependenciesFilterCallback = original; - } - } + Func custom = _ => true; + AssemblyContext.AssemblyDependenciesFilterCallback = custom; - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + Assert.Same(custom, AssemblyContext.AssemblyDependenciesFilterCallback); + } + finally { - Assert.Throws(() => AssemblyContext.AssemblyDependenciesFilterCallback = null); + AssemblyContext.AssemblyDependenciesFilterCallback = original; } + } - [Fact] - public void AssemblyFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssembly() - { - var callback = AssemblyContext.AssemblyFilterCallback; - var savvyioAssembly = typeof(AssemblyContext).Assembly; + [Fact] + public void AssemblyDependenciesFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + { + Assert.Throws(() => AssemblyContext.AssemblyDependenciesFilterCallback = null); + } - Assert.True(callback(savvyioAssembly)); - } + [Fact] + public void AssemblyFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssembly() + { + var callback = AssemblyContext.AssemblyFilterCallback; + var savvyioAssembly = typeof(AssemblyContext).Assembly; - [Fact] - public void AssemblyFilterCallback_DefaultFilter_ShouldExcludeSystemAssembly() - { - var callback = AssemblyContext.AssemblyFilterCallback; - var systemAssembly = typeof(string).Assembly; + Assert.True(callback(savvyioAssembly)); + } - Assert.False(callback(systemAssembly)); - } + [Fact] + public void AssemblyFilterCallback_DefaultFilter_ShouldExcludeSystemAssembly() + { + var callback = AssemblyContext.AssemblyFilterCallback; + var systemAssembly = typeof(string).Assembly; - [Fact] - public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssemblyName() - { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; - var assemblyName = typeof(AssemblyContext).Assembly.GetName(); + Assert.False(callback(systemAssembly)); + } - Assert.True(callback(assemblyName)); - } + [Fact] + public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssemblyName() + { + var callback = AssemblyContext.AssemblyDependenciesFilterCallback; + var assemblyName = typeof(AssemblyContext).Assembly.GetName(); - [Fact] - public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldExcludeSystemAssemblyName() - { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; - var assemblyName = typeof(string).Assembly.GetName(); + Assert.True(callback(assemblyName)); + } - Assert.False(callback(assemblyName)); - } + [Fact] + public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldExcludeSystemAssemblyName() + { + var callback = AssemblyContext.AssemblyDependenciesFilterCallback; + var assemblyName = typeof(string).Assembly.GetName(); - [Fact] - public void AssemblyDependenciesCallback_DefaultCallback_ShouldYieldAtLeastTheInputAssembly() - { - var callback = AssemblyContext.AssemblyDependenciesCallback; - var assembly = typeof(AssemblyContext).Assembly; + Assert.False(callback(assemblyName)); + } + + [Fact] + public void AssemblyDependenciesCallback_DefaultCallback_ShouldYieldAtLeastTheInputAssembly() + { + var callback = AssemblyContext.AssemblyDependenciesCallback; + var assembly = typeof(AssemblyContext).Assembly; - var result = callback(assembly).ToList(); + var result = callback(assembly).ToList(); - Assert.Contains(assembly, result); - } + Assert.Contains(assembly, result); } } diff --git a/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs index 4a361b9d..752d84fb 100644 --- a/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs @@ -10,112 +10,111 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddDispatchers_ShouldNotAddAnyDispatchersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddDispatchers(); - Assert.Empty(sut.DispatcherServiceTypes); - Assert.Empty(sut.DispatcherImplementationTypes); - } + [Fact] + public void AddDispatchers_ShouldNotAddAnyDispatchersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddDispatchers(); + Assert.Empty(sut.DispatcherServiceTypes); + Assert.Empty(sut.DispatcherImplementationTypes); + } - [Fact] - public void AddDispatchers_ShouldAddDispatchersFromSpecifiedAssemblies() - { - var sut = new SavvyioOptions().AddDispatchers(typeof(Command).Assembly, typeof(DomainEvent).Assembly, typeof(IntegrationEvent).Assembly, typeof(Query<>).Assembly); + [Fact] + public void AddDispatchers_ShouldAddDispatchersFromSpecifiedAssemblies() + { + var sut = new SavvyioOptions().AddDispatchers(typeof(Command).Assembly, typeof(DomainEvent).Assembly, typeof(IntegrationEvent).Assembly, typeof(Query<>).Assembly); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes, - type => Assert.Equal(typeof(ICommandDispatcher), type), - type => Assert.Equal(typeof(IDomainEventDispatcher), type), - type => Assert.Equal(typeof(IIntegrationEventDispatcher), type), - type => Assert.Equal(typeof(IQueryDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes, - type => Assert.Equal(typeof(CommandDispatcher), type), - type => Assert.Equal(typeof(DomainEventDispatcher), type), - type => Assert.Equal(typeof(IntegrationEventDispatcher), type), - type => Assert.Equal(typeof(QueryDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes, + type => Assert.Equal(typeof(ICommandDispatcher), type), + type => Assert.Equal(typeof(IDomainEventDispatcher), type), + type => Assert.Equal(typeof(IIntegrationEventDispatcher), type), + type => Assert.Equal(typeof(IQueryDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes, + type => Assert.Equal(typeof(CommandDispatcher), type), + type => Assert.Equal(typeof(DomainEventDispatcher), type), + type => Assert.Equal(typeof(IntegrationEventDispatcher), type), + type => Assert.Equal(typeof(QueryDispatcher), type)); + } - [Fact] - public void AddDispatchers_ShouldAutomaticallyAddDispatchersFromReferencedAssemblies() - { - var sut = new SavvyioOptions().UseAutomaticDispatcherDiscovery(true); + [Fact] + public void AddDispatchers_ShouldAutomaticallyAddDispatchersFromReferencedAssemblies() + { + var sut = new SavvyioOptions().UseAutomaticDispatcherDiscovery(true); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes.OrderBy(type => type.Name), - type => Assert.Equal(typeof(ICommandDispatcher), type), - type => Assert.Equal(typeof(IDomainEventDispatcher), type), - type => Assert.Equal(typeof(IIntegrationEventDispatcher), type), - type => Assert.Equal(typeof(IMediator), type), - type => Assert.Equal(typeof(IQueryDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes.OrderBy(type => type.Name), - type => Assert.Equal(typeof(CommandDispatcher), type), - type => Assert.Equal(typeof(DomainEventDispatcher), type), - type => Assert.Equal(typeof(IntegrationEventDispatcher), type), - type => Assert.Equal(typeof(Mediator), type), - type => Assert.Equal(typeof(QueryDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes.OrderBy(type => type.Name), + type => Assert.Equal(typeof(ICommandDispatcher), type), + type => Assert.Equal(typeof(IDomainEventDispatcher), type), + type => Assert.Equal(typeof(IIntegrationEventDispatcher), type), + type => Assert.Equal(typeof(IMediator), type), + type => Assert.Equal(typeof(IQueryDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes.OrderBy(type => type.Name), + type => Assert.Equal(typeof(CommandDispatcher), type), + type => Assert.Equal(typeof(DomainEventDispatcher), type), + type => Assert.Equal(typeof(IntegrationEventDispatcher), type), + type => Assert.Equal(typeof(Mediator), type), + type => Assert.Equal(typeof(QueryDispatcher), type)); + } - [Fact] - public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddHandlers(); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - } + [Fact] + public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddHandlers(); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + } - [Fact] - public void AddHandlers_ShouldAddHandlersFromSpecifiedAssemblies() - { - var sut = new SavvyioOptions().AddHandlers(typeof(ICommand).Assembly, typeof(IDomainEvent).Assembly, typeof(IIntegrationEvent).Assembly, typeof(IQuery).Assembly, typeof(Account).Assembly); + [Fact] + public void AddHandlers_ShouldAddHandlersFromSpecifiedAssemblies() + { + var sut = new SavvyioOptions().AddHandlers(typeof(ICommand).Assembly, typeof(IDomainEvent).Assembly, typeof(IIntegrationEvent).Assembly, typeof(IQuery).Assembly, typeof(Account).Assembly); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes, - type => Assert.Equal(typeof(ICommandHandler), type), - type => Assert.Equal(typeof(IDomainEventHandler), type), - type => Assert.Equal(typeof(IIntegrationEventHandler), type), - type => Assert.Equal(typeof(IQueryHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes, - type => Assert.Equal(typeof(AccountCommandHandler), type), - type => Assert.Equal(typeof(PlatformProviderHandler), type), - type => Assert.Equal(typeof(AccountDomainEventHandler), type), - type => Assert.Equal(typeof(PlatformProviderDomainEventHandler), type), - type => Assert.Equal(typeof(AccountEventHandler), type), - type => Assert.Equal(typeof(AccountQueryHandler), type)); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes, + type => Assert.Equal(typeof(ICommandHandler), type), + type => Assert.Equal(typeof(IDomainEventHandler), type), + type => Assert.Equal(typeof(IIntegrationEventHandler), type), + type => Assert.Equal(typeof(IQueryHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes, + type => Assert.Equal(typeof(AccountCommandHandler), type), + type => Assert.Equal(typeof(PlatformProviderHandler), type), + type => Assert.Equal(typeof(AccountDomainEventHandler), type), + type => Assert.Equal(typeof(PlatformProviderDomainEventHandler), type), + type => Assert.Equal(typeof(AccountEventHandler), type), + type => Assert.Equal(typeof(AccountQueryHandler), type)); + } - [Fact] - public void AddHandlers_ShouldAddHandlersAutomaticallyFromReferencedAssemblies() - { - var sut = new SavvyioOptions().UseAutomaticHandlerDiscovery(true); + [Fact] + public void AddHandlers_ShouldAddHandlersAutomaticallyFromReferencedAssemblies() + { + var sut = new SavvyioOptions().UseAutomaticHandlerDiscovery(true); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes.OrderBy(type => type.Name), - type => Assert.Equal(typeof(ICommandHandler), type), - type => Assert.Equal(typeof(IDomainEventHandler), type), - type => Assert.Equal(typeof(IIntegrationEventHandler), type), - type => Assert.Equal(typeof(IQueryHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes.OrderBy(type => type.Name), - type => Assert.Equal(typeof(AccountCommandHandler), type), - type => Assert.Equal(typeof(AccountDomainEventHandler), type), - type => Assert.Equal(typeof(AccountEventHandler), type), - type => Assert.Equal(typeof(AccountHandlers), type), - type => Assert.Equal(typeof(AccountQueryHandler), type), - type => Assert.Equal(typeof(PlatformProviderDomainEventHandler), type), - type => Assert.Equal(typeof(PlatformProviderHandler), type) - ); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes.OrderBy(type => type.Name), + type => Assert.Equal(typeof(ICommandHandler), type), + type => Assert.Equal(typeof(IDomainEventHandler), type), + type => Assert.Equal(typeof(IIntegrationEventHandler), type), + type => Assert.Equal(typeof(IQueryHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes.OrderBy(type => type.Name), + type => Assert.Equal(typeof(AccountCommandHandler), type), + type => Assert.Equal(typeof(AccountDomainEventHandler), type), + type => Assert.Equal(typeof(AccountEventHandler), type), + type => Assert.Equal(typeof(AccountHandlers), type), + type => Assert.Equal(typeof(AccountQueryHandler), type), + type => Assert.Equal(typeof(PlatformProviderDomainEventHandler), type), + type => Assert.Equal(typeof(PlatformProviderHandler), type) + ); } } diff --git a/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs b/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs index 1d46421b..3406b01a 100644 --- a/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs +++ b/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs @@ -1,26 +1,25 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio +namespace Savvyio; + +public class SavvyioOptionsTest : Test { - public class SavvyioOptionsTest : Test + public SavvyioOptionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void SavvyioOptions_Ensure_Initialization_Defaults() - { - var sut = new SavvyioOptions(); + [Fact] + public void SavvyioOptions_Ensure_Initialization_Defaults() + { + var sut = new SavvyioOptions(); - Assert.False(sut.AllowDispatcherDiscovery); - Assert.False(sut.AllowHandlerDiscovery); - Assert.False(sut.IncludeHandlerServicesDescriptor); - Assert.Empty(sut.DispatcherImplementationTypes); - Assert.Empty(sut.DispatcherServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - Assert.Empty(sut.HandlerServiceTypes); - } + Assert.False(sut.AllowDispatcherDiscovery); + Assert.False(sut.AllowHandlerDiscovery); + Assert.False(sut.IncludeHandlerServicesDescriptor); + Assert.Empty(sut.DispatcherImplementationTypes); + Assert.Empty(sut.DispatcherServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + Assert.Empty(sut.HandlerServiceTypes); } } diff --git a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreModelBuilderExtensionsTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreModelBuilderExtensionsTest.cs index 4b517ff7..b169bae6 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreModelBuilderExtensionsTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreModelBuilderExtensionsTest.cs @@ -6,39 +6,38 @@ using Savvyio.Extensions.EFCore; using Xunit; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +public class EfCoreModelBuilderExtensionsTest : Test { - public class EfCoreModelBuilderExtensionsTest : Test + public EfCoreModelBuilderExtensionsTest(ITestOutputHelper output) : base(output) { - public EfCoreModelBuilderExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ModelBuilderExtensions_ShouldApplyConfiguredEventSourcingSchema() + [Fact] + public void ModelBuilderExtensions_ShouldApplyConfiguredEventSourcingSchema() + { + var source = new EfCoreDataSource(new EfCoreDataSourceOptions { - var source = new EfCoreDataSource(new EfCoreDataSourceOptions + ContextConfigurator = b => b.UseInMemoryDatabase("event-sourcing-" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddEventSourcing(o => { - ContextConfigurator = b => b.UseInMemoryDatabase("event-sourcing-" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddEventSourcing(o => - { - o.TableName = "TraceEvents"; - o.CompositePrimaryKeyIdColumnName = "aggregate_id"; - o.CompositePrimaryKeyVersionColumnName = "aggregate_version"; - o.TimestampColumnName = "recorded_at"; - o.TypeColumnName = "aggregate_type"; - o.PayloadColumnName = "body"; - }) - }); + o.TableName = "TraceEvents"; + o.CompositePrimaryKeyIdColumnName = "aggregate_id"; + o.CompositePrimaryKeyVersionColumnName = "aggregate_version"; + o.TimestampColumnName = "recorded_at"; + o.TypeColumnName = "aggregate_type"; + o.PayloadColumnName = "body"; + }) + }); - var schema = source.DbContext.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); + var schema = source.DbContext.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); - Assert.Contains("Relational:TableName: TraceEvents", schema); - Assert.Contains("Relational:ColumnName: aggregate_id", schema); - Assert.Contains("Relational:ColumnName: aggregate_version", schema); - Assert.Contains("Relational:ColumnName: recorded_at", schema); - Assert.Contains("Relational:ColumnName: aggregate_type", schema); - Assert.Contains("Relational:ColumnName: body", schema); - } + Assert.Contains("Relational:TableName: TraceEvents", schema); + Assert.Contains("Relational:ColumnName: aggregate_id", schema); + Assert.Contains("Relational:ColumnName: aggregate_version", schema); + Assert.Contains("Relational:ColumnName: recorded_at", schema); + Assert.Contains("Relational:ColumnName: aggregate_type", schema); + Assert.Contains("Relational:ColumnName: body", schema); } } diff --git a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedAggregateEntityOptionsTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedAggregateEntityOptionsTest.cs index 891a165f..7db7bb12 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedAggregateEntityOptionsTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedAggregateEntityOptionsTest.cs @@ -1,61 +1,60 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +public class EfCoreTracedAggregateEntityOptionsTest : Test { - public class EfCoreTracedAggregateEntityOptionsTest : Test + public EfCoreTracedAggregateEntityOptionsTest(ITestOutputHelper output) : base(output) { - public EfCoreTracedAggregateEntityOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EfCoreTracedAggregateEntityOptions_Ensure_Initialization_Defaults() - { - var sut = new EfCoreTracedAggregateEntityOptions(); + [Fact] + public void EfCoreTracedAggregateEntityOptions_Ensure_Initialization_Defaults() + { + var sut = new EfCoreTracedAggregateEntityOptions(); - Assert.Equal("DomainEvents", sut.TableName); - Assert.Equal("id", sut.CompositePrimaryKeyIdColumnName); - Assert.Equal("uniqueidentifier", sut.CompositePrimaryKeyIdColumnType); - Assert.Equal("version", sut.CompositePrimaryKeyVersionColumnName); - Assert.Equal("int", sut.CompositePrimaryKeyVersionColumnType); - Assert.Equal("timestamp", sut.TimestampColumnName); - Assert.Equal("datetime", sut.TimestampColumnType); - Assert.Equal("clrtype", sut.TypeColumnName); - Assert.Equal("varchar(1024)", sut.TypeColumnType); - Assert.Equal("payload", sut.PayloadColumnName); - Assert.Equal("varchar(max)", sut.PayloadColumnType); - } + Assert.Equal("DomainEvents", sut.TableName); + Assert.Equal("id", sut.CompositePrimaryKeyIdColumnName); + Assert.Equal("uniqueidentifier", sut.CompositePrimaryKeyIdColumnType); + Assert.Equal("version", sut.CompositePrimaryKeyVersionColumnName); + Assert.Equal("int", sut.CompositePrimaryKeyVersionColumnType); + Assert.Equal("timestamp", sut.TimestampColumnName); + Assert.Equal("datetime", sut.TimestampColumnType); + Assert.Equal("clrtype", sut.TypeColumnName); + Assert.Equal("varchar(1024)", sut.TypeColumnType); + Assert.Equal("payload", sut.PayloadColumnName); + Assert.Equal("varchar(max)", sut.PayloadColumnType); + } - [Fact] - public void EfCoreTracedAggregateEntityOptions_ShouldAcceptCustomValues() + [Fact] + public void EfCoreTracedAggregateEntityOptions_ShouldAcceptCustomValues() + { + var sut = new EfCoreTracedAggregateEntityOptions { - var sut = new EfCoreTracedAggregateEntityOptions - { - TableName = "TraceEvents", - CompositePrimaryKeyIdColumnName = "aggregate_id", - CompositePrimaryKeyIdColumnType = "uuid", - CompositePrimaryKeyVersionColumnName = "aggregate_version", - CompositePrimaryKeyVersionColumnType = "bigint", - TimestampColumnName = "recorded_at", - TimestampColumnType = "datetime2", - TypeColumnName = "aggregate_type", - TypeColumnType = "nvarchar(512)", - PayloadColumnName = "body", - PayloadColumnType = "varbinary(max)" - }; + TableName = "TraceEvents", + CompositePrimaryKeyIdColumnName = "aggregate_id", + CompositePrimaryKeyIdColumnType = "uuid", + CompositePrimaryKeyVersionColumnName = "aggregate_version", + CompositePrimaryKeyVersionColumnType = "bigint", + TimestampColumnName = "recorded_at", + TimestampColumnType = "datetime2", + TypeColumnName = "aggregate_type", + TypeColumnType = "nvarchar(512)", + PayloadColumnName = "body", + PayloadColumnType = "varbinary(max)" + }; - Assert.Equal("TraceEvents", sut.TableName); - Assert.Equal("aggregate_id", sut.CompositePrimaryKeyIdColumnName); - Assert.Equal("uuid", sut.CompositePrimaryKeyIdColumnType); - Assert.Equal("aggregate_version", sut.CompositePrimaryKeyVersionColumnName); - Assert.Equal("bigint", sut.CompositePrimaryKeyVersionColumnType); - Assert.Equal("recorded_at", sut.TimestampColumnName); - Assert.Equal("datetime2", sut.TimestampColumnType); - Assert.Equal("aggregate_type", sut.TypeColumnName); - Assert.Equal("nvarchar(512)", sut.TypeColumnType); - Assert.Equal("body", sut.PayloadColumnName); - Assert.Equal("varbinary(max)", sut.PayloadColumnType); - } + Assert.Equal("TraceEvents", sut.TableName); + Assert.Equal("aggregate_id", sut.CompositePrimaryKeyIdColumnName); + Assert.Equal("uuid", sut.CompositePrimaryKeyIdColumnType); + Assert.Equal("aggregate_version", sut.CompositePrimaryKeyVersionColumnName); + Assert.Equal("bigint", sut.CompositePrimaryKeyVersionColumnType); + Assert.Equal("recorded_at", sut.TimestampColumnName); + Assert.Equal("datetime2", sut.TimestampColumnType); + Assert.Equal("aggregate_type", sut.TypeColumnName); + Assert.Equal("nvarchar(512)", sut.TypeColumnType); + Assert.Equal("body", sut.PayloadColumnName); + Assert.Equal("varbinary(max)", sut.PayloadColumnType); } } diff --git a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedDomainEventExtensionsTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedDomainEventExtensionsTest.cs index e063d317..2137198a 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedDomainEventExtensionsTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/EfCoreTracedDomainEventExtensionsTest.cs @@ -5,24 +5,23 @@ using Savvyio.Extensions.Newtonsoft.Json; using Xunit; -namespace Savvyio.Extensions.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; + +public class TracedDomainEventExtensionsTest : Test { - public class TracedDomainEventExtensionsTest : Test + public TracedDomainEventExtensionsTest(ITestOutputHelper output) : base(output) { - public TracedDomainEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void TracedDomainEventExtensions_ShouldConvertDomainEventToByteArray() - { - var domainEvent = new TracedAccountEmailAddressChanged("test@unit.test"); - var expected = NewtonsoftJsonMarshaller.Default.Serialize(domainEvent, typeof(ITracedDomainEvent)).ToByteArray(); + [Fact] + public void TracedDomainEventExtensions_ShouldConvertDomainEventToByteArray() + { + var domainEvent = new TracedAccountEmailAddressChanged("test@unit.test"); + var expected = NewtonsoftJsonMarshaller.Default.Serialize(domainEvent, typeof(ITracedDomainEvent)).ToByteArray(); - var sut = domainEvent.ToByteArray(NewtonsoftJsonMarshaller.Default); + var sut = domainEvent.ToByteArray(NewtonsoftJsonMarshaller.Default); - Assert.NotEmpty(sut); - Assert.Equal(expected, sut); - } + Assert.NotEmpty(sut); + Assert.Equal(expected, sut); } } diff --git a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs index 459c9be1..e4c0a0a0 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs @@ -27,137 +27,137 @@ using System.Threading.Tasks; using Xunit; -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +public class TracedAggregateRootTest : Test { - public class TracedAggregateRootTest : Test + public TracedAggregateRootTest(ITestOutputHelper output) : base(output) { - public TracedAggregateRootTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void TracedAggregateRoot_ShouldApplyAccountInitiatedToAggregate() - { - var id = Guid.NewGuid(); - var providerId = new PlatformProviderId(Guid.NewGuid()); - var fullName = new FullName("Michael", "Mortensen"); - var emailAddress = new EmailAddress("root@gimlichael.dev"); - - var sut = new TracedAccount(id, providerId, fullName, emailAddress); - - Assert.Equal(1, sut.Version); - Assert.Equal(id, sut.Id); - Assert.Equal(fullName, sut.FullName); - Assert.Equal(emailAddress, sut.EmailAddress); - Assert.Equal(providerId, sut.PlatformProviderId); - Assert.Equal(1, sut.Events.Count); - } + [Fact] + public void TracedAggregateRoot_ShouldApplyAccountInitiatedToAggregate() + { + var id = Guid.NewGuid(); + var providerId = new PlatformProviderId(Guid.NewGuid()); + var fullName = new FullName("Michael", "Mortensen"); + var emailAddress = new EmailAddress("root@gimlichael.dev"); + + var sut = new TracedAccount(id, providerId, fullName, emailAddress); + + Assert.Equal(1, sut.Version); + Assert.Equal(id, sut.Id); + Assert.Equal(fullName, sut.FullName); + Assert.Equal(emailAddress, sut.EmailAddress); + Assert.Equal(providerId, sut.PlatformProviderId); + Assert.Equal(1, sut.Events.Count); + } - [Fact] - public void TracedAggregateRoot_ShouldApplyAllEventsToAggregate() - { - var id = Guid.NewGuid(); - var providerId = new PlatformProviderId(Guid.NewGuid()); - var fullName = new FullName("Michael", "Mortennes"); - var emailAddress = new EmailAddress("root@gimlichael.ved"); - - var sut = new TracedAccount(id, providerId, fullName, emailAddress); - sut.ChangeEmailAddress(new EmailAddress("root@gimlichael.dev")); - sut.ChangeFullName(new FullName("Michael Mortensen")); - - Assert.Equal(3, sut.Version); - Assert.Equal(id, sut.Id); - Assert.NotEqual(fullName, sut.FullName); - Assert.NotEqual(emailAddress, sut.EmailAddress); - Assert.Equal(providerId, sut.PlatformProviderId); - Assert.Equal(3, sut.Events.Count); - } + [Fact] + public void TracedAggregateRoot_ShouldApplyAllEventsToAggregate() + { + var id = Guid.NewGuid(); + var providerId = new PlatformProviderId(Guid.NewGuid()); + var fullName = new FullName("Michael", "Mortennes"); + var emailAddress = new EmailAddress("root@gimlichael.ved"); + + var sut = new TracedAccount(id, providerId, fullName, emailAddress); + sut.ChangeEmailAddress(new EmailAddress("root@gimlichael.dev")); + sut.ChangeFullName(new FullName("Michael Mortensen")); + + Assert.Equal(3, sut.Version); + Assert.Equal(id, sut.Id); + Assert.NotEqual(fullName, sut.FullName); + Assert.NotEqual(emailAddress, sut.EmailAddress); + Assert.Equal(providerId, sut.PlatformProviderId); + Assert.Equal(3, sut.Events.Count); + } + + [Theory] + [InlineData(typeof(NewtonsoftJsonMarshaller))] + [InlineData(typeof(JsonMarshaller))] + public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToStorage(Type formatterType) + { + string schema = null; + var sc = new ServiceCollection(); + var dbName = "Dummy_" + Generate.RandomString(10); // ensure unique in-memory database name per test run due to .NET 10 changes from Microsoft + sc.AddSavvyIO(o => o.AddDomainEventDispatcher().AddDomainEventHandler()); - [Theory] - [InlineData(typeof(NewtonsoftJsonMarshaller))] - [InlineData(typeof(JsonMarshaller))] - public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToStorage(Type formatterType) + switch (formatterType) { - string schema = null; - var sc = new ServiceCollection(); - var dbName = "Dummy_" + Generate.RandomString(10); // ensure unique in-memory database name per test run due to .NET 10 changes from Microsoft - sc.AddSavvyIO(o => o.AddDomainEventDispatcher().AddDomainEventHandler()); - - switch (formatterType) - { - case Type newton when newton == typeof(NewtonsoftJsonMarshaller): - sc.AddMarshaller(); - sc.AddEfCoreAggregateDataSource(o => + case Type newton when newton == typeof(NewtonsoftJsonMarshaller): + sc.AddMarshaller(); + sc.AddEfCoreAggregateDataSource(o => + { + o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors().EnableServiceProviderCaching(false).LogTo(Console.WriteLine, LogLevel.Trace); + o.ModelConstructor = mb => { - o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors().EnableServiceProviderCaching(false).LogTo(Console.WriteLine, LogLevel.Trace); - o.ModelConstructor = mb => - { - mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); - schema = mb.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); - TestOutput.WriteLine(schema); - }; - }); - sc.AddEfCoreTracedAggregateRepository(); - break; - case Type builtin when builtin == typeof(JsonMarshaller): - sc.AddMarshaller(); - sc.AddEfCoreAggregateDataSource(o => + mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); + schema = mb.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); + TestOutput.WriteLine(schema); + }; + }); + sc.AddEfCoreTracedAggregateRepository(); + break; + case Type builtin when builtin == typeof(JsonMarshaller): + sc.AddMarshaller(); + sc.AddEfCoreAggregateDataSource(o => + { + o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors().EnableServiceProviderCaching(false).LogTo(Console.WriteLine, LogLevel.Trace); + o.ModelConstructor = mb => { - o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors().EnableServiceProviderCaching(false).LogTo(Console.WriteLine, LogLevel.Trace); - o.ModelConstructor = mb => - { - mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); - schema = mb.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); - TestOutput.WriteLine(schema); - }; - }); - sc.AddEfCoreTracedAggregateRepository(); - break; - } + mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); + schema = mb.Model.ToDebugString(MetadataDebugStringOptions.LongDefault); + TestOutput.WriteLine(schema); + }; + }); + sc.AddEfCoreTracedAggregateRepository(); + break; + } - sc.AddScoped, InMemoryTestStore>(); + sc.AddScoped, InMemoryTestStore>(); - var sp = sc.BuildServiceProvider(); + var sp = sc.BuildServiceProvider(); - var ds = formatterType == typeof(NewtonsoftJsonMarshaller) - ? sp.GetRequiredService>() as IEfCoreDataSource - : sp.GetRequiredService>() as IEfCoreDataSource; - var sut4 = formatterType == typeof(NewtonsoftJsonMarshaller) - ? sp.GetRequiredService>() as ITracedAggregateRepository - : sp.GetRequiredService>() as ITracedAggregateRepository; + var ds = formatterType == typeof(NewtonsoftJsonMarshaller) + ? sp.GetRequiredService>() as IEfCoreDataSource + : sp.GetRequiredService>() as IEfCoreDataSource; + var sut4 = formatterType == typeof(NewtonsoftJsonMarshaller) + ? sp.GetRequiredService>() as ITracedAggregateRepository + : sp.GetRequiredService>() as ITracedAggregateRepository; - var id = Guid.NewGuid(); - var providerId = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; + var id = Guid.NewGuid(); + var providerId = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; - var ta = new TracedAccount(id, providerId, name, email); + var ta = new TracedAccount(id, providerId, name, email); - for (var i = 0; i < 1000; i++) - { - ta.ChangeEmailAddress($"{Generate.RandomString(8)}@gimlichael.dev"); - } + for (var i = 0; i < 1000; i++) + { + ta.ChangeEmailAddress($"{Generate.RandomString(8)}@gimlichael.dev"); + } - ta.ChangeEmailAddress("root@gimlichael.dev"); + ta.ChangeEmailAddress("root@gimlichael.dev"); - sut4.Add(ta); + sut4.Add(ta); - await ds.SaveChangesAsync(); // should raise domain events + await ds.SaveChangesAsync(); // should raise domain events - var sut5 = await sut4.GetByIdAsync(id); + var sut5 = await sut4.GetByIdAsync(id); - Assert.Equal(id, sp.GetRequiredService>().QueryFor().Single().Id); - Assert.Equal(providerId, sp.GetRequiredService>().QueryFor().Single().PlatformProviderId); - Assert.Equal(name, sp.GetRequiredService>().QueryFor().Single().FullName); - Assert.Equal(email, sp.GetRequiredService>().QueryFor().Single().EmailAddress); - Assert.Equal("root@gimlichael.dev", sp.GetRequiredService>().QueryFor().Last().EmailAddress); + Assert.Equal(id, sp.GetRequiredService>().QueryFor().Single().Id); + Assert.Equal(providerId, sp.GetRequiredService>().QueryFor().Single().PlatformProviderId); + Assert.Equal(name, sp.GetRequiredService>().QueryFor().Single().FullName); + Assert.Equal(email, sp.GetRequiredService>().QueryFor().Single().EmailAddress); + Assert.Equal("root@gimlichael.dev", sp.GetRequiredService>().QueryFor().Last().EmailAddress); - Assert.Equal(id, sut5.Id); - Assert.Equal(providerId, sut5.PlatformProviderId); - Assert.Equal(name, sut5.FullName); - Assert.Equal("root@gimlichael.dev", sut5.EmailAddress); + Assert.Equal(id, sut5.Id); + Assert.Equal(providerId, sut5.PlatformProviderId); + Assert.Equal(name, sut5.FullName); + Assert.Equal("root@gimlichael.dev", sut5.EmailAddress); - Assert.True(Match(@"Model: + Assert.True(Match(@"Model: EntityType: EfCoreTracedAggregateEntity Properties: Id (_id, Guid) Required PK AfterSave:Throw @@ -191,116 +191,115 @@ public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToSto InversePropertyAttributeConvention:InverseNavigations: System.Collections.Generic.Dictionary`2[System.Type,System.Collections.Generic.SortedSet`1[System.Type]] NonNullableConventionState: System.Reflection.NullabilityInfoContext ProductVersion: *".ReplaceLineEndings(), schema.ReplaceLineEndings(), o => o.ThrowOnNoMatch = true)); - } + } - [Fact] - public void EfCoreDataStore_ShouldRehydrateFromProvidedEvents() - { - var id = Guid.NewGuid(); - var providerId = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; - var newName = "Michael Mortensen"; - var newEmail = "root@gimlichael.dev"; - var expectedVersion = 3; - - var sut = new TracedAccount(id, Arguments.ToEnumerableOf( - new TracedAccountInitiated(id, providerId, name, email).SetAggregateVersion(1), - new TracedAccountEmailAddressChanged(newEmail).SetAggregateVersion(2), - new TracedAccountFullNameChanged(newName).SetAggregateVersion(3))); - - - Assert.Empty(sut.Events); - Assert.Equal(id, sut.Id); - Assert.Equal(providerId, sut.PlatformProviderId); - Assert.Equal(expectedVersion, sut.Version); - Assert.Equal(newName, sut.FullName); - Assert.Equal(newEmail, sut.EmailAddress); - } + [Fact] + public void EfCoreDataStore_ShouldRehydrateFromProvidedEvents() + { + var id = Guid.NewGuid(); + var providerId = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; + var newName = "Michael Mortensen"; + var newEmail = "root@gimlichael.dev"; + var expectedVersion = 3; + + var sut = new TracedAccount(id, Arguments.ToEnumerableOf( + new TracedAccountInitiated(id, providerId, name, email).SetAggregateVersion(1), + new TracedAccountEmailAddressChanged(newEmail).SetAggregateVersion(2), + new TracedAccountFullNameChanged(newName).SetAggregateVersion(3))); + + + Assert.Empty(sut.Events); + Assert.Equal(id, sut.Id); + Assert.Equal(providerId, sut.PlatformProviderId); + Assert.Equal(expectedVersion, sut.Version); + Assert.Equal(newName, sut.FullName); + Assert.Equal(newEmail, sut.EmailAddress); + } - [Fact] - public void EfCoreTracedAggregateEntity_ShouldExposeExplicitInterfaceMembers() - { - var id = Guid.NewGuid(); - var providerId = new PlatformProviderId(Guid.NewGuid()); - var fullName = new FullName("Test", "User"); - var emailAddress = new EmailAddress("test@unit.test"); - var ta = new TracedAccount(id, providerId, fullName, emailAddress); - var domainEvent = ta.Events.First(); - var marshaller = new JsonMarshaller(); - - var entity = new EfCoreTracedAggregateEntity(ta, domainEvent, marshaller); - - var metadata = ((IMetadata)entity).Metadata; - var events = ((IAggregateRoot)entity).Events; - ((IAggregateRoot)entity).RemoveAllEvents(); // no-op - - Assert.NotNull(metadata); - Assert.Single(events); - Assert.Single(((IAggregateRoot)entity).Events); // RemoveAllEvents is no-op - } + [Fact] + public void EfCoreTracedAggregateEntity_ShouldExposeExplicitInterfaceMembers() + { + var id = Guid.NewGuid(); + var providerId = new PlatformProviderId(Guid.NewGuid()); + var fullName = new FullName("Test", "User"); + var emailAddress = new EmailAddress("test@unit.test"); + var ta = new TracedAccount(id, providerId, fullName, emailAddress); + var domainEvent = ta.Events.First(); + var marshaller = new JsonMarshaller(); + + var entity = new EfCoreTracedAggregateEntity(ta, domainEvent, marshaller); + + var metadata = ((IMetadata)entity).Metadata; + var events = ((IAggregateRoot)entity).Events; + ((IAggregateRoot)entity).RemoveAllEvents(); // no-op + + Assert.NotNull(metadata); + Assert.Single(events); + Assert.Single(((IAggregateRoot)entity).Events); // RemoveAllEvents is no-op + } - [Fact] - public async Task EfCoreTracedAggregateRepository_AddRange_ShouldPersistMultipleAggregates() + [Fact] + public async Task EfCoreTracedAggregateRepository_AddRange_ShouldPersistMultipleAggregates() + { + var sc = new ServiceCollection(); + var dbName = "Dummy_AddRange_" + Generate.RandomString(10); + sc.AddSavvyIO(o => o.AddDomainEventDispatcher().AddDomainEventHandler()); + sc.AddMarshaller(); + sc.AddEfCoreAggregateDataSource(o => { - var sc = new ServiceCollection(); - var dbName = "Dummy_AddRange_" + Generate.RandomString(10); - sc.AddSavvyIO(o => o.AddDomainEventDispatcher().AddDomainEventHandler()); - sc.AddMarshaller(); - sc.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors(); - o.ModelConstructor = mb => mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); - }); - sc.AddEfCoreTracedAggregateRepository(); - sc.AddScoped, InMemoryTestStore>(); - - var sp = sc.BuildServiceProvider(); - var ds = sp.GetRequiredService>() as IEfCoreDataSource; - var sut4 = sp.GetRequiredService>() as ITracedAggregateRepository; - - var id1 = Guid.NewGuid(); - var id2 = Guid.NewGuid(); - var providerId = Guid.NewGuid(); - - var ta1 = new TracedAccount(id1, providerId, "Name1", "email1@test.com"); - var ta2 = new TracedAccount(id2, providerId, "Name2", "email2@test.com"); - - sut4.AddRange([ta1, ta2]); - await ds.SaveChangesAsync(); - - var result1 = await sut4.GetByIdAsync(id1); - var result2 = await sut4.GetByIdAsync(id2); - - Assert.Equal(id1, result1.Id); - Assert.Equal("Name1", result1.FullName); - Assert.Equal(id2, result2.Id); - Assert.Equal("Name2", result2.FullName); - } + o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName).EnableSensitiveDataLogging().EnableDetailedErrors(); + o.ModelConstructor = mb => mb.AddEventSourcing(eo => eo.TableName = $"{nameof(TracedAccount)}_DomainEvents"); + }); + sc.AddEfCoreTracedAggregateRepository(); + sc.AddScoped, InMemoryTestStore>(); - [Fact] - public async Task EfCoreTracedAggregateRepository_GetByIdAsync_ShouldThrowMissingMethodException_WhenEntityLacksRehydrationConstructor() - { - var sc = new ServiceCollection(); - var dbName = "Dummy_NoCtor_" + Generate.RandomString(10); - sc.AddSavvyIO(o => o.AddDomainEventDispatcher()); - sc.AddMarshaller(); - sc.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName); - o.ModelConstructor = mb => mb.AddEventSourcing(eo => eo.TableName = "NoCtorTracedAccount_DomainEvents"); - }); - sc.AddEfCoreTracedAggregateRepository(); - - var sp = sc.BuildServiceProvider(); - var sut = sp.GetRequiredService>() as ITracedAggregateRepository; - - await Assert.ThrowsAsync(() => sut.GetByIdAsync(Guid.NewGuid())); - } + var sp = sc.BuildServiceProvider(); + var ds = sp.GetRequiredService>() as IEfCoreDataSource; + var sut4 = sp.GetRequiredService>() as ITracedAggregateRepository; + + var id1 = Guid.NewGuid(); + var id2 = Guid.NewGuid(); + var providerId = Guid.NewGuid(); + + var ta1 = new TracedAccount(id1, providerId, "Name1", "email1@test.com"); + var ta2 = new TracedAccount(id2, providerId, "Name2", "email2@test.com"); - private class NoCtorTracedAccount : TracedAggregateRoot + sut4.AddRange([ta1, ta2]); + await ds.SaveChangesAsync(); + + var result1 = await sut4.GetByIdAsync(id1); + var result2 = await sut4.GetByIdAsync(id2); + + Assert.Equal(id1, result1.Id); + Assert.Equal("Name1", result1.FullName); + Assert.Equal(id2, result2.Id); + Assert.Equal("Name2", result2.FullName); + } + + [Fact] + public async Task EfCoreTracedAggregateRepository_GetByIdAsync_ShouldThrowMissingMethodException_WhenEntityLacksRehydrationConstructor() + { + var sc = new ServiceCollection(); + var dbName = "Dummy_NoCtor_" + Generate.RandomString(10); + sc.AddSavvyIO(o => o.AddDomainEventDispatcher()); + sc.AddMarshaller(); + sc.AddEfCoreAggregateDataSource(o => { - protected override void RegisterDelegates(IFireForgetRegistry handler) { } - } + o.ContextConfigurator = b => b.UseInMemoryDatabase(dbName); + o.ModelConstructor = mb => mb.AddEventSourcing(eo => eo.TableName = "NoCtorTracedAccount_DomainEvents"); + }); + sc.AddEfCoreTracedAggregateRepository(); + + var sp = sc.BuildServiceProvider(); + var sut = sp.GetRequiredService>() as ITracedAggregateRepository; + + await Assert.ThrowsAsync(() => sut.GetByIdAsync(Guid.NewGuid())); + } + + private class NoCtorTracedAccount : TracedAggregateRoot + { + protected override void RegisterDelegates(IFireForgetRegistry handler) { } } } diff --git a/test/Savvyio.Domain.EventSourcing.Tests/TracedDomainEventExtensionsTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/TracedDomainEventExtensionsTest.cs index 5629af2f..f22978ac 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/TracedDomainEventExtensionsTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/TracedDomainEventExtensionsTest.cs @@ -3,34 +3,33 @@ using Savvyio.Assets.Domain.Events; using Xunit; -namespace Savvyio.Domain.EventSourcing +namespace Savvyio.Domain.EventSourcing; + +public class TracedDomainEventExtensionsTest : Test { - public class TracedDomainEventExtensionsTest : Test + public TracedDomainEventExtensionsTest(ITestOutputHelper output) : base(output) { - public TracedDomainEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void TracedDomainEventExtensions_ShouldSetAndGetAggregateVersion() - { - var domainEvent = new TracedAccountEmailAddressChanged("test@unit.test"); + [Fact] + public void TracedDomainEventExtensions_ShouldSetAndGetAggregateVersion() + { + var domainEvent = new TracedAccountEmailAddressChanged("test@unit.test"); - var sut = domainEvent.SetAggregateVersion(42); + var sut = domainEvent.SetAggregateVersion(42); - Assert.Same(domainEvent, sut); - Assert.Equal(42, sut.GetAggregateVersion()); - } + Assert.Same(domainEvent, sut); + Assert.Equal(42, sut.GetAggregateVersion()); + } - [Fact] - public void TracedDomainEventExtensions_ShouldReturnMemberTypeMetadata() - { - var sut = new TracedAccountInitiated(Guid.NewGuid(), Guid.NewGuid(), "Jane Doe", "jd@office.com"); + [Fact] + public void TracedDomainEventExtensions_ShouldReturnMemberTypeMetadata() + { + var sut = new TracedAccountInitiated(Guid.NewGuid(), Guid.NewGuid(), "Jane Doe", "jd@office.com"); - var memberType = sut.GetMemberType(); + var memberType = sut.GetMemberType(); - Assert.StartsWith(typeof(TracedAccountInitiated).FullName, memberType); - Assert.Contains("Savvyio.Assets.Tests", memberType); - } + Assert.StartsWith(typeof(TracedAccountInitiated).FullName, memberType); + Assert.Contains("Savvyio.Assets.Tests", memberType); } } diff --git a/test/Savvyio.Domain.Tests/AggregateRootTest.cs b/test/Savvyio.Domain.Tests/AggregateRootTest.cs index 1e7e6c69..c5ca5d25 100644 --- a/test/Savvyio.Domain.Tests/AggregateRootTest.cs +++ b/test/Savvyio.Domain.Tests/AggregateRootTest.cs @@ -6,114 +6,113 @@ using Savvyio.Assets.Domain.Events; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class AggregateRootTest : Test { - public class AggregateRootTest : Test + public AggregateRootTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AggregateRoot_Account_ShouldHaveMetadata_FromCommand() + { + var id = Guid.NewGuid(); + var idString = id.ToString("N"); + var fullname = "Michael Mortensen"; + var email = "root@gimlichael.dev"; + var fakeMemberType = typeof(UpdateAccount); + + var command = new CreateAccount(id, fullname, email) + .SetCausationId(idString) + .SetCorrelationId(idString) + .SetMemberType(fakeMemberType); + + var sut = new Account(command.PlatformProviderId, command.FullName, command.EmailAddress).MergeMetadata(command); + + Assert.Collection(sut.Metadata, + pair => + { + Assert.Equal(pair.Key, MetadataDictionary.MemberType); + Assert.Equal(pair.Value, fakeMemberType.ToFullNameIncludingAssemblyName()); + }, + pair => + { + Assert.Equal(pair.Key, MetadataDictionary.CorrelationId); + Assert.Equal(pair.Value, idString); + }, + pair => + { + Assert.Equal(pair.Key, MetadataDictionary.CausationId); + Assert.Equal(pair.Value, idString); + }); + + Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); + } + + [Fact] + public void AggregateRoot_Account_ShouldHaveDefaultMetadata() + { + var fullname = "Michael Mortensen"; + var email = "root@gimlichael.dev"; + + var sut = new Account(Guid.NewGuid(), fullname, email); + + Assert.True(sut.Metadata.Count == 0, "sut.Metadata.Count == 0"); + } + + [Fact] + public void AggregateRoot_PlatformProvider_ShouldRaise_PlatformProviderInitiated_Event() + { + var name = "AmaZure"; + var thirdLvlDomainName = "amz"; + var description = "The next big thing in cloud providers!"; + + var sut = new PlatformProvider(name, thirdLvlDomainName, description); + + Assert.Equal(sut.Description, description); + Assert.Equal(sut.Name, name); + Assert.Equal(sut.ThirdLevelDomainName, thirdLvlDomainName); + Assert.Equal(sut.Policy, new PlatformProviderAccountPolicy()); + Assert.True(sut.Events.Count == 1, "sut.Events.Count == 1"); + Assert.Collection(sut.Events, e => Assert.IsType(e)); + } + + [Fact] + public void AggregateRoot_PlatformProvider_ShouldRaise_FourDifferent_Events() { - public AggregateRootTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void AggregateRoot_Account_ShouldHaveMetadata_FromCommand() - { - var id = Guid.NewGuid(); - var idString = id.ToString("N"); - var fullname = "Michael Mortensen"; - var email = "root@gimlichael.dev"; - var fakeMemberType = typeof(UpdateAccount); - - var command = new CreateAccount(id, fullname, email) - .SetCausationId(idString) - .SetCorrelationId(idString) - .SetMemberType(fakeMemberType); - - var sut = new Account(command.PlatformProviderId, command.FullName, command.EmailAddress).MergeMetadata(command); - - Assert.Collection(sut.Metadata, - pair => - { - Assert.Equal(pair.Key, MetadataDictionary.MemberType); - Assert.Equal(pair.Value, fakeMemberType.ToFullNameIncludingAssemblyName()); - }, - pair => - { - Assert.Equal(pair.Key, MetadataDictionary.CorrelationId); - Assert.Equal(pair.Value, idString); - }, - pair => - { - Assert.Equal(pair.Key, MetadataDictionary.CausationId); - Assert.Equal(pair.Value, idString); - }); - - Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); - } - - [Fact] - public void AggregateRoot_Account_ShouldHaveDefaultMetadata() - { - var fullname = "Michael Mortensen"; - var email = "root@gimlichael.dev"; - - var sut = new Account(Guid.NewGuid(), fullname, email); - - Assert.True(sut.Metadata.Count == 0, "sut.Metadata.Count == 0"); - } - - [Fact] - public void AggregateRoot_PlatformProvider_ShouldRaise_PlatformProviderInitiated_Event() - { - var name = "AmaZure"; - var thirdLvlDomainName = "amz"; - var description = "The next big thing in cloud providers!"; - - var sut = new PlatformProvider(name, thirdLvlDomainName, description); - - Assert.Equal(sut.Description, description); - Assert.Equal(sut.Name, name); - Assert.Equal(sut.ThirdLevelDomainName, thirdLvlDomainName); - Assert.Equal(sut.Policy, new PlatformProviderAccountPolicy()); - Assert.True(sut.Events.Count == 1, "sut.Events.Count == 1"); - Assert.Collection(sut.Events, e => Assert.IsType(e)); - } - - [Fact] - public void AggregateRoot_PlatformProvider_ShouldRaise_FourDifferent_Events() - { - var name = "AmaZure"; - var thirdLvlDomainName = "amz"; - var description = "The next big thing in cloud providers!"; - var newAccountPolicy = new PlatformProviderAccountPolicy(5, 0, TimeSpan.Zero, TimeSpan.Zero, 0, TimeSpan.Zero, TimeSpan.Zero, false); - var newDescription = "The next big thing in platform providers in the cloud!"; - var newName = "AwaZure"; - var newThirdLvlDomainName = "awz"; - - var sut = new PlatformProvider(name, thirdLvlDomainName, description); - sut.RemoveAllEvents(); - - Assert.Equal(sut.Description, description); - Assert.Equal(sut.Name, name); - Assert.Equal(sut.ThirdLevelDomainName, thirdLvlDomainName); - Assert.Equal(sut.Policy, new PlatformProviderAccountPolicy()); - Assert.True(sut.Events.Count == 0, "sut.Events.Count == 0"); - - sut.ChangeAccountPolicy(newAccountPolicy); - sut.ChangeDescription(newDescription); - sut.ChangeName(newName); - sut.ChangeThirdLevelDomainName(newThirdLvlDomainName); - - Assert.Equal(sut.Description, newDescription); - Assert.Equal(sut.Name, newName); - Assert.Equal(sut.ThirdLevelDomainName, newThirdLvlDomainName); - Assert.Equal(sut.Policy, newAccountPolicy); - Assert.True(sut.Events.Count == 4, "sut.Events.Count == 4"); - - Assert.Collection(sut.Events, - e => Assert.IsType(e), - e => Assert.IsType(e), - e => Assert.IsType(e), - e => Assert.IsType(e)); - } + var name = "AmaZure"; + var thirdLvlDomainName = "amz"; + var description = "The next big thing in cloud providers!"; + var newAccountPolicy = new PlatformProviderAccountPolicy(5, 0, TimeSpan.Zero, TimeSpan.Zero, 0, TimeSpan.Zero, TimeSpan.Zero, false); + var newDescription = "The next big thing in platform providers in the cloud!"; + var newName = "AwaZure"; + var newThirdLvlDomainName = "awz"; + + var sut = new PlatformProvider(name, thirdLvlDomainName, description); + sut.RemoveAllEvents(); + + Assert.Equal(sut.Description, description); + Assert.Equal(sut.Name, name); + Assert.Equal(sut.ThirdLevelDomainName, thirdLvlDomainName); + Assert.Equal(sut.Policy, new PlatformProviderAccountPolicy()); + Assert.True(sut.Events.Count == 0, "sut.Events.Count == 0"); + + sut.ChangeAccountPolicy(newAccountPolicy); + sut.ChangeDescription(newDescription); + sut.ChangeName(newName); + sut.ChangeThirdLevelDomainName(newThirdLvlDomainName); + + Assert.Equal(sut.Description, newDescription); + Assert.Equal(sut.Name, newName); + Assert.Equal(sut.ThirdLevelDomainName, newThirdLvlDomainName); + Assert.Equal(sut.Policy, newAccountPolicy); + Assert.True(sut.Events.Count == 4, "sut.Events.Count == 4"); + + Assert.Collection(sut.Events, + e => Assert.IsType(e), + e => Assert.IsType(e), + e => Assert.IsType(e), + e => Assert.IsType(e)); } } diff --git a/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs b/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs index aff7730b..be47f32c 100644 --- a/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs +++ b/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs @@ -3,51 +3,50 @@ using Savvyio.Assets.Domain.Events; using Savvyio.Handlers; -namespace Savvyio.Domain.Assets +namespace Savvyio.Domain.Assets; + +public class AccountHandlers : IDomainEventHandler { - public class AccountHandlers : IDomainEventHandler + private readonly ITestStore _domainEventStore; + private readonly IDomainEventDispatcher _domainEventDispatcher; + + public AccountHandlers(ITestStore domainEventStore = null, IDomainEventDispatcher domainEventDispatcher = null) { - private readonly ITestStore _domainEventStore; - private readonly IDomainEventDispatcher _domainEventDispatcher; + _domainEventStore = domainEventStore; + _domainEventDispatcher = domainEventDispatcher; + } - public AccountHandlers(ITestStore domainEventStore = null, IDomainEventDispatcher domainEventDispatcher = null) + IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(registry => + { + registry.Register(a => _domainEventStore.Add(a)); + registry.Register(a => _domainEventStore.Add(a)); + registry.Register(a => _domainEventStore.Add(a)); + registry.Register(a => _domainEventStore.Add(a)); + registry.Register(a => _domainEventStore.Add(a)); + registry.RegisterAsync(a => { - _domainEventStore = domainEventStore; - _domainEventDispatcher = domainEventDispatcher; - } - - IFireForgetActivator IFireForgetHandler.Delegates => HandlerFactory.CreateFireForget(registry => + _domainEventStore.Add(a); + return Task.CompletedTask; + }); + registry.RegisterAsync(a => { - registry.Register(a => _domainEventStore.Add(a)); - registry.Register(a => _domainEventStore.Add(a)); - registry.Register(a => _domainEventStore.Add(a)); - registry.Register(a => _domainEventStore.Add(a)); - registry.Register(a => _domainEventStore.Add(a)); - registry.RegisterAsync(a => - { - _domainEventStore.Add(a); - return Task.CompletedTask; - }); - registry.RegisterAsync(a => - { - _domainEventStore.Add(a); - return Task.CompletedTask; - }); - registry.RegisterAsync(a => - { - _domainEventStore.Add(a); - return Task.CompletedTask; - }); - registry.RegisterAsync(a => - { - _domainEventStore.Add(a); - return Task.CompletedTask; - }); - registry.RegisterAsync(a => - { - _domainEventStore.Add(a); - return Task.CompletedTask; - }); + _domainEventStore.Add(a); + return Task.CompletedTask; }); - } + registry.RegisterAsync(a => + { + _domainEventStore.Add(a); + return Task.CompletedTask; + }); + registry.RegisterAsync(a => + { + _domainEventStore.Add(a); + return Task.CompletedTask; + }); + registry.RegisterAsync(a => + { + _domainEventStore.Add(a); + return Task.CompletedTask; + }); + }); } diff --git a/test/Savvyio.Domain.Tests/Assets/Mixed.cs b/test/Savvyio.Domain.Tests/Assets/Mixed.cs index c7e5f088..673b4575 100644 --- a/test/Savvyio.Domain.Tests/Assets/Mixed.cs +++ b/test/Savvyio.Domain.Tests/Assets/Mixed.cs @@ -1,19 +1,18 @@ using System; using Savvyio.Assets.Domain; -namespace Savvyio.Domain.Assets +namespace Savvyio.Domain.Assets; + +public record Mixed : ValueObject { - public record Mixed : ValueObject + public Mixed() { - public Mixed() - { - } + } - public AccountId AccountId { get; set; } + public AccountId AccountId { get; set; } - public Money Money { get; set; } + public Money Money { get; set; } - public decimal SomeDecimal { get; set; } = Decimal.MaxValue; - } + public decimal SomeDecimal { get; set; } = Decimal.MaxValue; } diff --git a/test/Savvyio.Domain.Tests/Assets/Money.cs b/test/Savvyio.Domain.Tests/Assets/Money.cs index 6b7bfc55..22c0aab7 100644 --- a/test/Savvyio.Domain.Tests/Assets/Money.cs +++ b/test/Savvyio.Domain.Tests/Assets/Money.cs @@ -1,23 +1,22 @@ using System; -namespace Savvyio.Domain.Assets +namespace Savvyio.Domain.Assets; + +public enum Currency { - public enum Currency - { - USD, - MYR - } + USD, + MYR +} - public record Money : ValueObject - { - public Currency Currency { get; init; } - public decimal Amount { get; init; } +public record Money : ValueObject +{ + public Currency Currency { get; init; } + public decimal Amount { get; init; } - public Money(Currency currency, decimal amount) - { - if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount)); - Currency = currency; - Amount = amount; - } + public Money(Currency currency, decimal amount) + { + if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount)); + Currency = currency; + Amount = amount; } } diff --git a/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs b/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs index 647160f1..c66350cb 100644 --- a/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs +++ b/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs @@ -13,162 +13,161 @@ using Savvyio.Extensions.DependencyInjection; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class DomainEventDispatcherExtensionsTest : Test { - public class DomainEventDispatcherExtensionsTest : Test + public DomainEventDispatcherExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void RaiseMany_ShouldRaiseOneEventFromAggregate() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); + + var firstName = " Michael"; + var lastName = "Mortensen "; + var emailAddress = "root@gimlichael.dev"; + var providerId = Guid.NewGuid(); + + var sp = sc.BuildServiceProvider(); + var sut = new DomainEventDispatcher(sp.GetRequiredService()); + var ar = new Account(new PlatformProviderId(providerId), new FullName(firstName, lastName), new EmailAddress(emailAddress)); + + Assert.NotEmpty(ar.Events); + + sut.RaiseMany(ar); + + var des = sp.GetRequiredService>(); + + Assert.Empty(ar.Events); + Assert.Equal("Michael Mortensen", des.QueryFor().Single().FullName); + Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); + Assert.Equal(providerId, des.QueryFor().Single().PlatformProviderId); + } + + [Fact] + public void RaiseMany_ShouldRaiseManyEventsFromAggregate() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); + + var sp = sc.BuildServiceProvider(); + var sut = new DomainEventDispatcher(sp.GetRequiredService()); + var ar = new Account(new AccountId(100)); + + var fullName = "Michael Mortensen"; + var emailAddress = "root@gimlichael.dev"; + var providerId = Guid.NewGuid(); + var userName = "gimlichael"; + var password = "p@assw0rd"; + var salt = Generate.RandomString(32); + + // emulate orm + var properties = ar.GetType().GetProperties(new MemberReflection()); + properties.Single(pi => pi.Name == "FullName").SetValue(ar, "Michael Motrensen"); + properties.Single(pi => pi.Name == "EmailAddress").SetValue(ar, "root@gimlichael.ved"); + properties.Single(pi => pi.Name == "PlatformProviderId").SetValue(ar, providerId); + // done + + ar.ChangeFullName(new FullName(fullName)); + ar.ChangeEmailAddress(emailAddress); + ar.Promote(new Credentials(userName, password, salt)); + + Assert.NotEmpty(ar.Events); + + sut.RaiseMany(ar); + + var des = sp.GetRequiredService>(); + + Assert.Empty(ar.Events); + Assert.Equal(fullName, ar.FullName); + Assert.Equal(emailAddress, ar.EmailAddress); + Assert.Equal(providerId, ar.PlatformProviderId); + + Assert.Equal(fullName, des.QueryFor().Single().FullName); + Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); + Assert.Equal(userName, des.QueryFor().Single().UserName); + Assert.Equal(salt, des.QueryFor().Single().Salt); + Assert.Equal(KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(), des.QueryFor().Single().Hash); + } + + [Fact] + public async Task RaiseManyAsync_ShouldRaiseOneEventFromAggregateAsync() + { + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); + + var firstName = " Michael"; + var lastName = "Mortensen "; + var emailAddress = "root@gimlichael.dev"; + var providerId = Guid.NewGuid(); + + var sp = sc.BuildServiceProvider(); + var sut = new DomainEventDispatcher(sp.GetRequiredService()); + var ar = new Account(new PlatformProviderId(providerId), new FullName(firstName, lastName), new EmailAddress(emailAddress)); + + Assert.NotEmpty(ar.Events); + + await sut.RaiseManyAsync(ar); + + var des = sp.GetRequiredService>(); + + Assert.Empty(ar.Events); + Assert.Equal("Michael Mortensen", des.QueryFor().Single().FullName); + Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); + Assert.Equal(providerId, des.QueryFor().Single().PlatformProviderId); + } + + [Fact] + public async Task RaiseManyAsync_ShouldRaiseManyEventsFromAggregateAsync() { - public DomainEventDispatcherExtensionsTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void RaiseMany_ShouldRaiseOneEventFromAggregate() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); - - var firstName = " Michael"; - var lastName = "Mortensen "; - var emailAddress = "root@gimlichael.dev"; - var providerId = Guid.NewGuid(); - - var sp = sc.BuildServiceProvider(); - var sut = new DomainEventDispatcher(sp.GetRequiredService()); - var ar = new Account(new PlatformProviderId(providerId), new FullName(firstName, lastName), new EmailAddress(emailAddress)); - - Assert.NotEmpty(ar.Events); - - sut.RaiseMany(ar); - - var des = sp.GetRequiredService>(); - - Assert.Empty(ar.Events); - Assert.Equal("Michael Mortensen", des.QueryFor().Single().FullName); - Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); - Assert.Equal(providerId, des.QueryFor().Single().PlatformProviderId); - } - - [Fact] - public void RaiseMany_ShouldRaiseManyEventsFromAggregate() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); - - var sp = sc.BuildServiceProvider(); - var sut = new DomainEventDispatcher(sp.GetRequiredService()); - var ar = new Account(new AccountId(100)); - - var fullName = "Michael Mortensen"; - var emailAddress = "root@gimlichael.dev"; - var providerId = Guid.NewGuid(); - var userName = "gimlichael"; - var password = "p@assw0rd"; - var salt = Generate.RandomString(32); - - // emulate orm - var properties = ar.GetType().GetProperties(new MemberReflection()); - properties.Single(pi => pi.Name == "FullName").SetValue(ar, "Michael Motrensen"); - properties.Single(pi => pi.Name == "EmailAddress").SetValue(ar, "root@gimlichael.ved"); - properties.Single(pi => pi.Name == "PlatformProviderId").SetValue(ar, providerId); - // done - - ar.ChangeFullName(new FullName(fullName)); - ar.ChangeEmailAddress(emailAddress); - ar.Promote(new Credentials(userName, password, salt)); - - Assert.NotEmpty(ar.Events); - - sut.RaiseMany(ar); - - var des = sp.GetRequiredService>(); - - Assert.Empty(ar.Events); - Assert.Equal(fullName, ar.FullName); - Assert.Equal(emailAddress, ar.EmailAddress); - Assert.Equal(providerId, ar.PlatformProviderId); - - Assert.Equal(fullName, des.QueryFor().Single().FullName); - Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); - Assert.Equal(userName, des.QueryFor().Single().UserName); - Assert.Equal(salt, des.QueryFor().Single().Salt); - Assert.Equal(KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(), des.QueryFor().Single().Hash); - } - - [Fact] - public async Task RaiseManyAsync_ShouldRaiseOneEventFromAggregateAsync() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); - - var firstName = " Michael"; - var lastName = "Mortensen "; - var emailAddress = "root@gimlichael.dev"; - var providerId = Guid.NewGuid(); - - var sp = sc.BuildServiceProvider(); - var sut = new DomainEventDispatcher(sp.GetRequiredService()); - var ar = new Account(new PlatformProviderId(providerId), new FullName(firstName, lastName), new EmailAddress(emailAddress)); - - Assert.NotEmpty(ar.Events); - - await sut.RaiseManyAsync(ar); - - var des = sp.GetRequiredService>(); - - Assert.Empty(ar.Events); - Assert.Equal("Michael Mortensen", des.QueryFor().Single().FullName); - Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); - Assert.Equal(providerId, des.QueryFor().Single().PlatformProviderId); - } - - [Fact] - public async Task RaiseManyAsync_ShouldRaiseManyEventsFromAggregateAsync() - { - var sc = new ServiceCollection() - .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) - .AddScoped, InMemoryTestStore>(); - - var sp = sc.BuildServiceProvider(); - var sut = new DomainEventDispatcher(sp.GetRequiredService()); - var ar = new Account(new AccountId(100)); - - var fullName = "Michael Mortensen"; - var emailAddress = "root@gimlichael.dev"; - var providerId = Guid.NewGuid(); - var userName = "gimlichael"; - var password = "p@assw0rd"; - var salt = Generate.RandomString(32); - - // emulate orm - var properties = ar.GetType().GetProperties(new MemberReflection()); - properties.Single(pi => pi.Name == "FullName").SetValue(ar, "Michael Motrensen"); - properties.Single(pi => pi.Name == "EmailAddress").SetValue(ar, "root@gimlichael.ved"); - properties.Single(pi => pi.Name == "PlatformProviderId").SetValue(ar, providerId); - // done - - ar.ChangeFullName(new FullName(fullName)); - ar.ChangeEmailAddress(emailAddress); - ar.Promote(new Credentials(userName, password, salt)); - - Assert.NotEmpty(ar.Events); - - await sut.RaiseManyAsync(ar); - - var des = sp.GetRequiredService>(); - - Assert.Empty(ar.Events); - Assert.Equal(fullName, ar.FullName); - Assert.Equal(emailAddress, ar.EmailAddress); - Assert.Equal(providerId, ar.PlatformProviderId); - - Assert.Equal(fullName, des.QueryFor().Single().FullName); - Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); - Assert.Equal(userName, des.QueryFor().Single().UserName); - Assert.Equal(salt, des.QueryFor().Single().Salt); - Assert.Equal(KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(), des.QueryFor().Single().Hash); - } + var sc = new ServiceCollection() + .AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEventDispatcher).Assembly, typeof(DomainEventDispatcherExtensionsTest).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()) + .AddScoped, InMemoryTestStore>(); + + var sp = sc.BuildServiceProvider(); + var sut = new DomainEventDispatcher(sp.GetRequiredService()); + var ar = new Account(new AccountId(100)); + + var fullName = "Michael Mortensen"; + var emailAddress = "root@gimlichael.dev"; + var providerId = Guid.NewGuid(); + var userName = "gimlichael"; + var password = "p@assw0rd"; + var salt = Generate.RandomString(32); + + // emulate orm + var properties = ar.GetType().GetProperties(new MemberReflection()); + properties.Single(pi => pi.Name == "FullName").SetValue(ar, "Michael Motrensen"); + properties.Single(pi => pi.Name == "EmailAddress").SetValue(ar, "root@gimlichael.ved"); + properties.Single(pi => pi.Name == "PlatformProviderId").SetValue(ar, providerId); + // done + + ar.ChangeFullName(new FullName(fullName)); + ar.ChangeEmailAddress(emailAddress); + ar.Promote(new Credentials(userName, password, salt)); + + Assert.NotEmpty(ar.Events); + + await sut.RaiseManyAsync(ar); + + var des = sp.GetRequiredService>(); + + Assert.Empty(ar.Events); + Assert.Equal(fullName, ar.FullName); + Assert.Equal(emailAddress, ar.EmailAddress); + Assert.Equal(providerId, ar.PlatformProviderId); + + Assert.Equal(fullName, des.QueryFor().Single().FullName); + Assert.Equal(emailAddress, des.QueryFor().Single().EmailAddress); + Assert.Equal(userName, des.QueryFor().Single().UserName); + Assert.Equal(salt, des.QueryFor().Single().Salt); + Assert.Equal(KeyedHashFactory.CreateHmacCryptoSha256(salt.ToByteArray()).ComputeHash(password).ToHexadecimalString(), des.QueryFor().Single().Hash); } } diff --git a/test/Savvyio.Domain.Tests/DomainEventTest.cs b/test/Savvyio.Domain.Tests/DomainEventTest.cs index 11e1d638..cca56efd 100644 --- a/test/Savvyio.Domain.Tests/DomainEventTest.cs +++ b/test/Savvyio.Domain.Tests/DomainEventTest.cs @@ -4,63 +4,62 @@ using Savvyio.Assets.Domain.Events; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class DomainEventTest : Test { - public class DomainEventTest : Test + public DomainEventTest(ITestOutputHelper output) : base(output) { - public DomainEventTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DomainEvent_AccountInitiated_ShouldHaveDefaultMetadata() - { - var fullname = "Michael Mortensen"; - var email = "root@gimlichael.dev"; + [Fact] + public void DomainEvent_AccountInitiated_ShouldHaveDefaultMetadata() + { + var fullname = "Michael Mortensen"; + var email = "root@gimlichael.dev"; - var account = new Account(Guid.NewGuid(), fullname, email); - var sut = new AccountInitiated(account); - var ts = DateTime.UtcNow; + var account = new Account(Guid.NewGuid(), fullname, email); + var sut = new AccountInitiated(account); + var ts = DateTime.UtcNow; - Assert.Equal(account.EmailAddress, sut.EmailAddress); - Assert.Equal(account.FullName, sut.FullName); - Assert.Equal(account.PlatformProviderId, sut.PlatformProviderId); - Assert.Empty(account.Metadata); - Assert.Collection(sut.Metadata.Keys, - s => Assert.Equal(s, MetadataDictionary.MemberType), - s => Assert.Equal(s, MetadataDictionary.EventId), - s => Assert.Equal(s, MetadataDictionary.Timestamp)); - Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); - Assert.InRange(DateTime.UtcNow, sut.GetTimestamp(), ts.AddSeconds(1)); - } + Assert.Equal(account.EmailAddress, sut.EmailAddress); + Assert.Equal(account.FullName, sut.FullName); + Assert.Equal(account.PlatformProviderId, sut.PlatformProviderId); + Assert.Empty(account.Metadata); + Assert.Collection(sut.Metadata.Keys, + s => Assert.Equal(s, MetadataDictionary.MemberType), + s => Assert.Equal(s, MetadataDictionary.EventId), + s => Assert.Equal(s, MetadataDictionary.Timestamp)); + Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); + Assert.InRange(DateTime.UtcNow, sut.GetTimestamp(), ts.AddSeconds(1)); + } - [Fact] - public void DomainEvent_AccountInitiated_ShouldHaveAdditionalMetadata_CopiedFromAggregate() - { - var id = Guid.NewGuid(); - var fullname = "Michael Mortensen"; - var email = "root@gimlichael.dev"; + [Fact] + public void DomainEvent_AccountInitiated_ShouldHaveAdditionalMetadata_CopiedFromAggregate() + { + var id = Guid.NewGuid(); + var fullname = "Michael Mortensen"; + var email = "root@gimlichael.dev"; - var account = new Account(id, fullname, email) - .SaveMetadata("Key1", "Key1Value") - .SaveMetadata("Key2", "Key2Value") - .SaveMetadata("correlationid", "makingSureCorrelationIdIsWrittenPascalCase"); + var account = new Account(id, fullname, email) + .SaveMetadata("Key1", "Key1Value") + .SaveMetadata("Key2", "Key2Value") + .SaveMetadata("correlationid", "makingSureCorrelationIdIsWrittenPascalCase"); - var sut = new AccountInitiated(account).MergeMetadata(account); - var ts = DateTime.UtcNow; + var sut = new AccountInitiated(account).MergeMetadata(account); + var ts = DateTime.UtcNow; - Assert.Equal(account.EmailAddress, sut.EmailAddress); - Assert.Equal(account.FullName, sut.FullName); - Assert.Equal(account.PlatformProviderId, sut.PlatformProviderId); - Assert.Collection(sut.Metadata.Keys, - s => Assert.Equal(s, MetadataDictionary.MemberType), - s => Assert.Equal(s, MetadataDictionary.EventId), - s => Assert.Equal(s, MetadataDictionary.Timestamp), - s => Assert.Equal(s, "Key1"), - s => Assert.Equal(s, "Key2"), - s => Assert.Equal(s, MetadataDictionary.CorrelationId)); ; - Assert.True(sut.Metadata.Count == 6, "sut.Metadata.Count == 6"); - Assert.InRange(DateTime.UtcNow, sut.GetTimestamp(), ts.AddSeconds(1)); - } + Assert.Equal(account.EmailAddress, sut.EmailAddress); + Assert.Equal(account.FullName, sut.FullName); + Assert.Equal(account.PlatformProviderId, sut.PlatformProviderId); + Assert.Collection(sut.Metadata.Keys, + s => Assert.Equal(s, MetadataDictionary.MemberType), + s => Assert.Equal(s, MetadataDictionary.EventId), + s => Assert.Equal(s, MetadataDictionary.Timestamp), + s => Assert.Equal(s, "Key1"), + s => Assert.Equal(s, "Key2"), + s => Assert.Equal(s, MetadataDictionary.CorrelationId)); ; + Assert.True(sut.Metadata.Count == 6, "sut.Metadata.Count == 6"); + Assert.InRange(DateTime.UtcNow, sut.GetTimestamp(), ts.AddSeconds(1)); } } diff --git a/test/Savvyio.Domain.Tests/EntityTest.cs b/test/Savvyio.Domain.Tests/EntityTest.cs index 77dd3d7a..d28a3da3 100644 --- a/test/Savvyio.Domain.Tests/EntityTest.cs +++ b/test/Savvyio.Domain.Tests/EntityTest.cs @@ -3,32 +3,31 @@ using Savvyio.Assets.Domain; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class EntityTest : Test { - public class EntityTest : Test + public EntityTest(ITestOutputHelper output) : base(output) { - public EntityTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Entity_Account_ShouldBeTransient() - { - var sut = new Account(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + [Fact] + public void Entity_Account_ShouldBeTransient() + { + var sut = new Account(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - Assert.Equal(0, sut.Id); - Assert.True(sut.IsTransient); - Assert.IsType(sut.Id); - } + Assert.Equal(0, sut.Id); + Assert.True(sut.IsTransient); + Assert.IsType(sut.Id); + } - [Fact] - public void Entity_Account_ShouldBeNonTransient() - { - var sut = new Account(100); + [Fact] + public void Entity_Account_ShouldBeNonTransient() + { + var sut = new Account(100); - Assert.Equal(100, sut.Id); - Assert.False(sut.IsTransient); - Assert.IsType(sut.Id); - } + Assert.Equal(100, sut.Id); + Assert.False(sut.IsTransient); + Assert.IsType(sut.Id); } } diff --git a/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs index 57fa2fbe..1e54e66d 100644 --- a/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs @@ -2,42 +2,41 @@ using Savvyio.Assets.Domain.Handlers; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddHandlers(); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - } + [Fact] + public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddHandlers(); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + } - [Fact] - public void AddDomainEventHandler_ShouldAddDomainEventHandler() - { - var sut = new SavvyioOptions().AddDomainEventHandler(); + [Fact] + public void AddDomainEventHandler_ShouldAddDomainEventHandler() + { + var sut = new SavvyioOptions().AddDomainEventHandler(); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IDomainEventHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountDomainEventHandler), type)); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IDomainEventHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountDomainEventHandler), type)); + } - [Fact] - public void AddDomainEventDispatcher_ShouldAddDomainEventDispatcher() - { - var sut = new SavvyioOptions().AddDomainEventDispatcher(); + [Fact] + public void AddDomainEventDispatcher_ShouldAddDomainEventDispatcher() + { + var sut = new SavvyioOptions().AddDomainEventDispatcher(); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IDomainEventDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(DomainEventDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IDomainEventDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(DomainEventDispatcher), type)); } } diff --git a/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs b/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs index 4391cec3..3b56f0ad 100644 --- a/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs +++ b/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs @@ -3,47 +3,46 @@ using Savvyio.Assets.Domain; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class SingleValueObjectTest : Test { - public class SingleValueObjectTest : Test + public SingleValueObjectTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void SingleValueObject_PlatformProviderId_ShouldBeEqual() { - public SingleValueObjectTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void SingleValueObject_PlatformProviderId_ShouldBeEqual() - { - var id = Guid.NewGuid(); - var sut1 = new PlatformProviderId(id); - var sut2 = new PlatformProviderId(id); - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.Equal(sut1, sut2); - } - - [Fact] - public void SingleValueObject_PlatformProviderId_ShouldNotBeEqual() - { - var id1 = Guid.NewGuid(); - var id2 = Guid.NewGuid(); - var sut1 = new PlatformProviderId(id1); - var sut2 = new PlatformProviderId(id2); - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.NotEqual(sut1, sut2); - } - - [Fact] - public void SingleValueObject_EmailAddress_ShouldConvertBiderictional() - { - var email = "root@gimlichael.dev"; - var sut = new EmailAddress(email); - - Assert.Equal(email, sut); - Assert.Equal((EmailAddress)email, sut); - } + var id = Guid.NewGuid(); + var sut1 = new PlatformProviderId(id); + var sut2 = new PlatformProviderId(id); + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.Equal(sut1, sut2); + } + + [Fact] + public void SingleValueObject_PlatformProviderId_ShouldNotBeEqual() + { + var id1 = Guid.NewGuid(); + var id2 = Guid.NewGuid(); + var sut1 = new PlatformProviderId(id1); + var sut2 = new PlatformProviderId(id2); + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.NotEqual(sut1, sut2); + } + + [Fact] + public void SingleValueObject_EmailAddress_ShouldConvertBiderictional() + { + var email = "root@gimlichael.dev"; + var sut = new EmailAddress(email); + + Assert.Equal(email, sut); + Assert.Equal((EmailAddress)email, sut); } } diff --git a/test/Savvyio.Domain.Tests/ValueObjectTest.cs b/test/Savvyio.Domain.Tests/ValueObjectTest.cs index 62129d43..58851b58 100644 --- a/test/Savvyio.Domain.Tests/ValueObjectTest.cs +++ b/test/Savvyio.Domain.Tests/ValueObjectTest.cs @@ -4,77 +4,76 @@ using Savvyio.Domain.Assets; using Xunit; -namespace Savvyio.Domain +namespace Savvyio.Domain; + +public class ValueObjectTest : Test { - public class ValueObjectTest : Test + public ValueObjectTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void ValueObject_PlatformProviderAccountPolicy_ShouldBeEqual() + { + var sut1 = new PlatformProviderAccountPolicy(); + var sut2 = new PlatformProviderAccountPolicy(); + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.True(sut1 == sut2); + Assert.Equal(sut1, sut2); + Assert.Equal(sut1.GetHashCode(), sut2.GetHashCode()); + } + + [Fact] + public void ValueObject_PlatformProviderAccountPolicy_ShouldNotBeEqual() + { + var sut1 = new PlatformProviderAccountPolicy(); + var sut2 = new PlatformProviderAccountPolicy(1, 24, TimeSpan.Zero, TimeSpan.FromDays(1), 5, TimeSpan.FromHours(1), TimeSpan.FromMinutes(10), false); + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.True(sut1 != sut2); + Assert.NotEqual(sut1, sut2); + Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); + } + + [Fact] + public void ValueObject_Money_ShouldNotBeEqual() { - public ValueObjectTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void ValueObject_PlatformProviderAccountPolicy_ShouldBeEqual() - { - var sut1 = new PlatformProviderAccountPolicy(); - var sut2 = new PlatformProviderAccountPolicy(); - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.True(sut1 == sut2); - Assert.Equal(sut1, sut2); - Assert.Equal(sut1.GetHashCode(), sut2.GetHashCode()); - } - - [Fact] - public void ValueObject_PlatformProviderAccountPolicy_ShouldNotBeEqual() - { - var sut1 = new PlatformProviderAccountPolicy(); - var sut2 = new PlatformProviderAccountPolicy(1, 24, TimeSpan.Zero, TimeSpan.FromDays(1), 5, TimeSpan.FromHours(1), TimeSpan.FromMinutes(10), false); - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.True(sut1 != sut2); - Assert.NotEqual(sut1, sut2); - Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); - } - - [Fact] - public void ValueObject_Money_ShouldNotBeEqual() - { - var sut1 = new Money(Currency.MYR, 100); - var sut2 = new Money(Currency.USD, 101); - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.True(sut1 != sut2); - Assert.NotEqual(sut1, sut2); - Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); - } - - [Fact] - public void ValueObject_MixedSimpleAndValueObject_ShouldNotBeEqual() - { - var sut1 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; - var sut2 = new Mixed() { AccountId = 315551312, Money = new Money(Currency.MYR, 321) }; - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.True(sut1 != sut2); - Assert.NotEqual(sut1, sut2); - Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); - } - - [Fact] - public void ValueObject_MixedSimpleAndValueObject_ShouldBeEqual() - { - var sut1 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; - var sut2 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; - - TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); - - Assert.True(sut1 == sut2); - Assert.Equal(sut1, sut2); - Assert.Equal(sut1.GetHashCode(), sut2.GetHashCode()); - } + var sut1 = new Money(Currency.MYR, 100); + var sut2 = new Money(Currency.USD, 101); + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.True(sut1 != sut2); + Assert.NotEqual(sut1, sut2); + Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); + } + + [Fact] + public void ValueObject_MixedSimpleAndValueObject_ShouldNotBeEqual() + { + var sut1 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; + var sut2 = new Mixed() { AccountId = 315551312, Money = new Money(Currency.MYR, 321) }; + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.True(sut1 != sut2); + Assert.NotEqual(sut1, sut2); + Assert.NotEqual(sut1.GetHashCode(), sut2.GetHashCode()); + } + + [Fact] + public void ValueObject_MixedSimpleAndValueObject_ShouldBeEqual() + { + var sut1 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; + var sut2 = new Mixed() { AccountId = 2414214, Money = new Money(Currency.MYR, 123) }; + + TestOutput.WriteLines(sut1.ToString(), sut2.ToString()); + + Assert.True(sut1 == sut2); + Assert.Equal(sut1, sut2); + Assert.Equal(sut1.GetHashCode(), sut2.GetHashCode()); } } diff --git a/test/Savvyio.EventDriven.Tests/IntegrationEventDispatcherTest.cs b/test/Savvyio.EventDriven.Tests/IntegrationEventDispatcherTest.cs index af105b00..a42cf5bf 100644 --- a/test/Savvyio.EventDriven.Tests/IntegrationEventDispatcherTest.cs +++ b/test/Savvyio.EventDriven.Tests/IntegrationEventDispatcherTest.cs @@ -5,44 +5,43 @@ using Savvyio.Handlers; using Xunit; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +public class IntegrationEventDispatcherTest : Test { - public class IntegrationEventDispatcherTest : Test + public IntegrationEventDispatcherTest(ITestOutputHelper output) : base(output) { - public IntegrationEventDispatcherTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Publish_ShouldDispatchIntegrationEvent() - { - var services = new ServiceCollection() - .AddServiceLocator() - .AddSingleton, InMemoryTestStore>() - .AddTransient(); - var provider = services.BuildServiceProvider(); - var sut = new IntegrationEventDispatcher(provider.GetRequiredService()); + [Fact] + public void Publish_ShouldDispatchIntegrationEvent() + { + var services = new ServiceCollection() + .AddServiceLocator() + .AddSingleton, InMemoryTestStore>() + .AddTransient(); + var provider = services.BuildServiceProvider(); + var sut = new IntegrationEventDispatcher(provider.GetRequiredService()); - sut.Publish(new TestIntegrationEvent("published")); + sut.Publish(new TestIntegrationEvent("published")); - Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("published", item)); - } + Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("published", item)); + } - private sealed record TestIntegrationEvent(string Value) : IntegrationEvent; + private sealed record TestIntegrationEvent(string Value) : IntegrationEvent; - private sealed class TestIntegrationEventHandler : IntegrationEventHandler - { - private readonly ITestStore _store; + private sealed class TestIntegrationEventHandler : IntegrationEventHandler + { + private readonly ITestStore _store; - public TestIntegrationEventHandler(ITestStore store) - { - _store = store; - } + public TestIntegrationEventHandler(ITestStore store) + { + _store = store; + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(message => _store.Add(message.Value)); - } + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.Register(message => _store.Add(message.Value)); } } } diff --git a/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs b/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs index b2e40f8c..424543b3 100644 --- a/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs +++ b/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs @@ -4,59 +4,58 @@ using Savvyio.Assets.EventDriven; using Xunit; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +public class IntegrationEventTest : Test { - public class IntegrationEventTest : Test + public IntegrationEventTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void IntegrationEvent_AccountCreated_ShouldHaveMetadata_WithSpecifiedEventId() { - public IntegrationEventTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void IntegrationEvent_AccountCreated_ShouldHaveMetadata_WithSpecifiedEventId() - { - var eventId = Guid.NewGuid().ToString("N"); - var id = 100; - var fullname = "Michael Mortensen"; - var email = "root@gimlichael.dev"; - - var sut = new AccountCreated(100, fullname, email).SetEventId(eventId); - - Assert.Equal(email, sut.EmailAddress); - Assert.Equal(fullname, sut.FullName); - Assert.Equal(id, sut.Id); - - Assert.Collection(sut.Metadata, - kvp => - { - Assert.Equal(kvp.Key, MetadataDictionary.MemberType); - Assert.Equal(kvp.Value, sut.GetType().ToFullNameIncludingAssemblyName()); - }, - kvp => - { - Assert.Equal(kvp.Key, MetadataDictionary.EventId); - Assert.Equal(kvp.Value, eventId); - }, - kvp => - { - Assert.Equal(kvp.Key, MetadataDictionary.Timestamp); - Assert.Equal(kvp.Value, sut.GetTimestamp()); - }); - Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); - } - - [Fact] - public void IntegrationEvent_AccountCreated_ShouldExposeMetadataThroughExtensions() - { - var eventId = Guid.NewGuid().ToString("N"); - var timestamp = DateTime.UtcNow; - var sut = new AccountCreated(100, "Michael Mortensen", "root@gimlichael.dev") - .SetEventId(eventId) - .SetTimestamp(timestamp); - - Assert.Equal(eventId, sut.GetEventId()); - Assert.Equal(timestamp, sut.GetTimestamp()); - Assert.Equal(sut.GetType().ToFullNameIncludingAssemblyName(), sut.GetMemberType()); - } + var eventId = Guid.NewGuid().ToString("N"); + var id = 100; + var fullname = "Michael Mortensen"; + var email = "root@gimlichael.dev"; + + var sut = new AccountCreated(100, fullname, email).SetEventId(eventId); + + Assert.Equal(email, sut.EmailAddress); + Assert.Equal(fullname, sut.FullName); + Assert.Equal(id, sut.Id); + + Assert.Collection(sut.Metadata, + kvp => + { + Assert.Equal(kvp.Key, MetadataDictionary.MemberType); + Assert.Equal(kvp.Value, sut.GetType().ToFullNameIncludingAssemblyName()); + }, + kvp => + { + Assert.Equal(kvp.Key, MetadataDictionary.EventId); + Assert.Equal(kvp.Value, eventId); + }, + kvp => + { + Assert.Equal(kvp.Key, MetadataDictionary.Timestamp); + Assert.Equal(kvp.Value, sut.GetTimestamp()); + }); + Assert.True(sut.Metadata.Count == 3, "sut.Metadata.Count == 3"); + } + + [Fact] + public void IntegrationEvent_AccountCreated_ShouldExposeMetadataThroughExtensions() + { + var eventId = Guid.NewGuid().ToString("N"); + var timestamp = DateTime.UtcNow; + var sut = new AccountCreated(100, "Michael Mortensen", "root@gimlichael.dev") + .SetEventId(eventId) + .SetTimestamp(timestamp); + + Assert.Equal(eventId, sut.GetEventId()); + Assert.Equal(timestamp, sut.GetTimestamp()); + Assert.Equal(sut.GetType().ToFullNameIncludingAssemblyName(), sut.GetMemberType()); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/AcknowledgeableTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/AcknowledgeableTest.cs index 10140abc..eb44ffaa 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/AcknowledgeableTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/AcknowledgeableTest.cs @@ -4,31 +4,30 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class AcknowledgeableTest : Test { - public class AcknowledgeableTest : Test + public AcknowledgeableTest(ITestOutputHelper output) : base(output) { - public AcknowledgeableTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task AcknowledgeAsync_ShouldRaiseAcknowledgedEvent_WithMessageProperties() + [Fact] + public async Task AcknowledgeAsync_ShouldRaiseAcknowledgedEvent_WithMessageProperties() + { + var message = new Message("mid1", "urn:members:1".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("Jane", 21, "j@j.com")); + AcknowledgedEventArgs acknowledged = null; + message.Properties["messageId"] = message.Id; + message.Acknowledged += (_, e) => { - var message = new Message("mid1", "urn:members:1".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("Jane", 21, "j@j.com")); - AcknowledgedEventArgs acknowledged = null; - message.Properties["messageId"] = message.Id; - message.Acknowledged += (_, e) => - { - acknowledged = e; - return Task.CompletedTask; - }; + acknowledged = e; + return Task.CompletedTask; + }; - await message.AcknowledgeAsync(); + await message.AcknowledgeAsync(); - Assert.NotNull(acknowledged); - Assert.Same(message.Properties, acknowledged.Properties); - Assert.Equal(message.Id, acknowledged.Properties["messageId"]); - } + Assert.NotNull(acknowledged); + Assert.Same(message.Properties, acknowledged.Properties); + Assert.Equal(message.Id, acknowledged.Properties["messageId"]); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventDictionaryTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventDictionaryTest.cs index 799f646a..62a9bfb0 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventDictionaryTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventDictionaryTest.cs @@ -6,74 +6,73 @@ using Savvyio.Assets.EventDriven; using Xunit; -namespace Savvyio.EventDriven.Messaging.CloudEvents +namespace Savvyio.EventDriven.Messaging.CloudEvents; + +public class CloudEventDictionaryTest : Test { - public class CloudEventDictionaryTest : Test + public CloudEventDictionaryTest(ITestOutputHelper output) : base(output) { - public CloudEventDictionaryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void IDictionaryMembers_ShouldManageExtensionAttributes() - { - var sut = CreateCloudEvent(); - IDictionary dictionary = sut; - ICollection> collection = dictionary; + [Fact] + public void IDictionaryMembers_ShouldManageExtensionAttributes() + { + var sut = CreateCloudEvent(); + IDictionary dictionary = sut; + ICollection> collection = dictionary; - sut.Add("TenantId", 42); - sut["TraceId"] = "abc123"; + sut.Add("TenantId", 42); + sut["TraceId"] = "abc123"; - Assert.True(sut.ContainsKey("tenantid")); - Assert.True(sut.ContainsKey("traceid")); - Assert.Equal(42, sut["tenantid"]); - Assert.True(sut.TryGetValue("traceid", out var traceId)); - Assert.Equal("abc123", traceId); - Assert.Contains("tenantid", dictionary.Keys); - Assert.Contains("traceid", dictionary.Keys); - Assert.Contains(42, dictionary.Values); - Assert.Contains("abc123", dictionary.Values); - Assert.True(collection.Contains(new KeyValuePair("tenantid", 42))); - var copy = new KeyValuePair[collection.Count]; - collection.CopyTo(copy, 0); - Assert.Contains(copy, kvp => kvp.Key == "tenantid" && Equals(kvp.Value, 42)); - Assert.False(collection.IsReadOnly); - Assert.True(sut.Remove("traceid")); - Assert.False(sut.ContainsKey("traceid")); - } + Assert.True(sut.ContainsKey("tenantid")); + Assert.True(sut.ContainsKey("traceid")); + Assert.Equal(42, sut["tenantid"]); + Assert.True(sut.TryGetValue("traceid", out var traceId)); + Assert.Equal("abc123", traceId); + Assert.Contains("tenantid", dictionary.Keys); + Assert.Contains("traceid", dictionary.Keys); + Assert.Contains(42, dictionary.Values); + Assert.Contains("abc123", dictionary.Values); + Assert.True(collection.Contains(new KeyValuePair("tenantid", 42))); + var copy = new KeyValuePair[collection.Count]; + collection.CopyTo(copy, 0); + Assert.Contains(copy, kvp => kvp.Key == "tenantid" && Equals(kvp.Value, 42)); + Assert.False(collection.IsReadOnly); + Assert.True(sut.Remove("traceid")); + Assert.False(sut.ContainsKey("traceid")); + } - [Fact] - public void EnumeratorsAndClear_ShouldExposeAndResetExtensionAttributes() - { - var sut = CreateCloudEvent(); - IDictionary dictionary = sut; - ICollection> collection = dictionary; + [Fact] + public void EnumeratorsAndClear_ShouldExposeAndResetExtensionAttributes() + { + var sut = CreateCloudEvent(); + IDictionary dictionary = sut; + ICollection> collection = dictionary; - collection.Add(new KeyValuePair("CorrelationId", "corr-1")); - collection.Add(new KeyValuePair("TenantId", 7)); + collection.Add(new KeyValuePair("CorrelationId", "corr-1")); + collection.Add(new KeyValuePair("TenantId", 7)); - var genericItems = dictionary.ToList(); - var nongenericItems = ((IEnumerable)sut).Cast>().ToList(); + var genericItems = dictionary.ToList(); + var nongenericItems = ((IEnumerable)sut).Cast>().ToList(); - Assert.Equal(2, genericItems.Count); - Assert.Equal(genericItems, nongenericItems); - Assert.True(collection.Remove(new KeyValuePair("tenantid", 7))); - Assert.Single(dictionary); + Assert.Equal(2, genericItems.Count); + Assert.Equal(genericItems, nongenericItems); + Assert.True(collection.Remove(new KeyValuePair("tenantid", 7))); + Assert.Single(dictionary); - sut.Clear(); + sut.Clear(); - Assert.Empty(dictionary); - } + Assert.Empty(dictionary); + } - private static CloudEvent CreateCloudEvent() + private static CloudEvent CreateCloudEvent() + { + var message = new MemberCreated("Jane Doe", "jd@office.com").ToMessage("https://savvyio.net/members".ToUri(), nameof(MemberCreated), o => { - var message = new MemberCreated("Jane Doe", "jd@office.com").ToMessage("https://savvyio.net/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "message-id"; - o.Time = new System.DateTime(2024, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); - }); + o.MessageId = "message-id"; + o.Time = new System.DateTime(2024, 1, 1, 0, 0, 0, System.DateTimeKind.Utc); + }); - return (CloudEvent)message.ToCloudEvent(); - } + return (CloudEvent)message.ToCloudEvent(); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs index 67c08451..1b9458d4 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs @@ -4,34 +4,33 @@ using Savvyio.Assets.EventDriven; using Xunit; -namespace Savvyio.EventDriven.Messaging.CloudEvents +namespace Savvyio.EventDriven.Messaging.CloudEvents; + +public class CloudEventTest : Test { - public class CloudEventTest : Test + public CloudEventTest(ITestOutputHelper output) : base(output) { - public CloudEventTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CloudEventsMessage_Initialization_Success() - { - // Arrange - var source = "https://savvyio.net/members".ToUri(); - var data = new AccountCreated(123347285, "John Doe", "jd@savvyio.net"); - var type = "net.savvyio.members.account-created"; - var time = DateTime.UtcNow; - var message = data.ToMessage(source, type); + [Fact] + public void CloudEventsMessage_Initialization_Success() + { + // Arrange + var source = "https://savvyio.net/members".ToUri(); + var data = new AccountCreated(123347285, "John Doe", "jd@savvyio.net"); + var type = "net.savvyio.members.account-created"; + var time = DateTime.UtcNow; + var message = data.ToMessage(source, type); - // Act - var cloudEventsMessage = message.ToCloudEvent(); + // Act + var cloudEventsMessage = message.ToCloudEvent(); - // Assert - Assert.Equal(message.Id, cloudEventsMessage.Id); - Assert.Equal(source.OriginalString, cloudEventsMessage.Source); - Assert.Equal(type, cloudEventsMessage.Type); - Assert.InRange(cloudEventsMessage.Time!.Value, time, time.AddSeconds(1)); - Assert.Equal(data, cloudEventsMessage.Data); - Assert.Equal("1.0", cloudEventsMessage.Specversion); - } + // Assert + Assert.Equal(message.Id, cloudEventsMessage.Id); + Assert.Equal(source.OriginalString, cloudEventsMessage.Source); + Assert.Equal(type, cloudEventsMessage.Type); + Assert.InRange(cloudEventsMessage.Time!.Value, time, time.AddSeconds(1)); + Assert.Equal(data, cloudEventsMessage.Data); + Assert.Equal("1.0", cloudEventsMessage.Specversion); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/Cryptography/CloudEventExtensionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/Cryptography/CloudEventExtensionsTest.cs index 9a368080..54e3cb7f 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/Cryptography/CloudEventExtensionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/Cryptography/CloudEventExtensionsTest.cs @@ -5,57 +5,56 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; + +public class CloudEventExtensionsTest : Test { - public class CloudEventExtensionsTest : Test + public CloudEventExtensionsTest(ITestOutputHelper output) : base(output) { - public CloudEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void SignCloudEvent_ShouldCreateSignedCloudEvent_WithVerifiableSignature() - { - var marshaller = new JsonMarshaller(); - var cloudEvent = CreateCloudEvent(); + [Fact] + public void SignCloudEvent_ShouldCreateSignedCloudEvent_WithVerifiableSignature() + { + var marshaller = new JsonMarshaller(); + var cloudEvent = CreateCloudEvent(); - var signed = cloudEvent.SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var signed = cloudEvent.SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - Assert.Equal(cloudEvent.Id, signed.Id); - Assert.Equal(cloudEvent.Source, signed.Source); - Assert.Equal(cloudEvent.Type, signed.Type); - Assert.Equal(cloudEvent.Time, signed.Time); - Assert.Equal(cloudEvent.Data, signed.Data); - Assert.Equal(cloudEvent.Specversion, signed.Specversion); - Assert.False(string.IsNullOrWhiteSpace(signed.Signature)); + Assert.Equal(cloudEvent.Id, signed.Id); + Assert.Equal(cloudEvent.Source, signed.Source); + Assert.Equal(cloudEvent.Type, signed.Type); + Assert.Equal(cloudEvent.Time, signed.Time); + Assert.Equal(cloudEvent.Data, signed.Data); + Assert.Equal(cloudEvent.Specversion, signed.Specversion); + Assert.False(string.IsNullOrWhiteSpace(signed.Signature)); - signed.CheckCloudEventSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - } + signed.CheckCloudEventSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + } - [Fact] - public void CheckCloudEventSignature_ShouldThrow_WhenSecretDoesNotMatch() - { - var marshaller = new JsonMarshaller(); - var signed = CreateCloudEvent().SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + [Fact] + public void CheckCloudEventSignature_ShouldThrow_WhenSecretDoesNotMatch() + { + var marshaller = new JsonMarshaller(); + var signed = CreateCloudEvent().SignCloudEvent(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var exception = Assert.Throws(() => signed.CheckCloudEventSignature(marshaller, o => o.SignatureSecret = new byte[] { 3, 2, 1 })); + var exception = Assert.Throws(() => signed.CheckCloudEventSignature(marshaller, o => o.SignatureSecret = new byte[] { 3, 2, 1 })); - Assert.Equal(signed.Signature, exception.ActualValue); - } + Assert.Equal(signed.Signature, exception.ActualValue); + } - private static CloudEvent CreateCloudEvent() + private static CloudEvent CreateCloudEvent() + { + var utc = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc); + var @event = new MemberCreated("Jane Doe", "jd@office.com") + .SetEventId("event-123") + .SetTimestamp(utc); + var message = @event.ToMessage("https://api.example.com/members".ToUri(), nameof(MemberCreated), o => { - var utc = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc); - var @event = new MemberCreated("Jane Doe", "jd@office.com") - .SetEventId("event-123") - .SetTimestamp(utc); - var message = @event.ToMessage("https://api.example.com/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "message-123"; - o.Time = utc; - }); - - return (CloudEvent)message.ToCloudEvent(); - } + o.MessageId = "message-123"; + o.Time = utc; + }); + + return (CloudEvent)message.ToCloudEvent(); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs index bd0db700..1f5f1eaf 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs @@ -2,36 +2,35 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +public class SignedMessageOptionsTest : Test { - public class SignedMessageOptionsTest : Test + public SignedMessageOptionsTest(ITestOutputHelper output) : base(output) { - public SignedMessageOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenSignatureSecretIsNull() - { - var options = new SignedMessageOptions(); + [Fact] + public void ValidateOptions_ShouldThrow_WhenSignatureSecretIsNull() + { + var options = new SignedMessageOptions(); - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenSignatureSecretIsEmpty() - { - var options = new SignedMessageOptions { SignatureSecret = Array.Empty() }; + [Fact] + public void ValidateOptions_ShouldThrow_WhenSignatureSecretIsEmpty() + { + var options = new SignedMessageOptions { SignatureSecret = Array.Empty() }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldSucceed_WhenSignatureSecretIsSet() - { - var options = new SignedMessageOptions { SignatureSecret = new byte[] { 1, 2, 3 } }; + [Fact] + public void ValidateOptions_ShouldSucceed_WhenSignatureSecretIsSet() + { + var options = new SignedMessageOptions { SignatureSecret = new byte[] { 1, 2, 3 } }; - options.ValidateOptions(); - } + options.ValidateOptions(); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageTest.cs index 5741b74b..25cd4cd9 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/Cryptography/SignedMessageTest.cs @@ -5,54 +5,53 @@ using Savvyio.Commands.Messaging; using Xunit; -namespace Savvyio.Messaging.Cryptography +namespace Savvyio.Messaging.Cryptography; + +public class SignedMessageTest : Test { - public class SignedMessageTest : Test + public SignedMessageTest(ITestOutputHelper output) : base(output) { - public SignedMessageTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_ShouldThrowArgumentNullException_WhenMessageIsNull() - { - Assert.Throws(() => new SignedMessage(null, "sig")); - } + [Fact] + public void Ctor_ShouldThrowArgumentNullException_WhenMessageIsNull() + { + Assert.Throws(() => new SignedMessage(null, "sig")); + } - [Fact] - public void Ctor_ShouldThrowArgumentNullException_WhenSignatureIsNull() - { - var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test"); + [Fact] + public void Ctor_ShouldThrowArgumentNullException_WhenSignatureIsNull() + { + var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test"); - Assert.Throws(() => new SignedMessage(message, null)); - } + Assert.Throws(() => new SignedMessage(message, null)); + } - [Fact] - public void Ctor_ShouldThrowArgumentException_WhenSignatureIsEmpty() - { - var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test"); + [Fact] + public void Ctor_ShouldThrowArgumentException_WhenSignatureIsEmpty() + { + var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test"); - Assert.Throws(() => new SignedMessage(message, string.Empty)); - } + Assert.Throws(() => new SignedMessage(message, string.Empty)); + } - [Fact] - public void Ctor_ShouldCopyMessageProperties() + [Fact] + public void Ctor_ShouldCopyMessageProperties() + { + var utc = DateTime.UtcNow; + var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test", o => { - var utc = DateTime.UtcNow; - var message = new CreateMemberCommand("Jane", 21, "j@j.com").ToMessage("https://api.example.com".ToUri(), "test", o => - { - o.MessageId = "abc123"; - o.Time = utc; - }); - - var signed = new SignedMessage(message, "mysig"); - - Assert.Equal(message.Id, signed.Id); - Assert.Equal(message.Source, signed.Source); - Assert.Equal(message.Type, signed.Type); - Assert.Equal(message.Time, signed.Time); - Assert.Equal(message.Data, signed.Data); - Assert.Equal("mysig", signed.Signature); - } + o.MessageId = "abc123"; + o.Time = utc; + }); + + var signed = new SignedMessage(message, "mysig"); + + Assert.Equal(message.Id, signed.Id); + Assert.Equal(message.Source, signed.Source); + Assert.Equal(message.Type, signed.Type); + Assert.Equal(message.Time, signed.Time); + Assert.Equal(message.Data, signed.Data); + Assert.Equal("mysig", signed.Signature); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs index fea300be..a28244dc 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs @@ -12,83 +12,82 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.EventDriven.Messaging +namespace Savvyio.EventDriven.Messaging; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class InMemoryEventBusTest : Test { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class InMemoryEventBusTest : Test + private static readonly InMemoryEventBus Bus = new(); + private static readonly InMemoryTestStore> Comparer = new(); + + public InMemoryEventBusTest(ITestOutputHelper output) : base(output) { - private static readonly InMemoryEventBus Bus = new(); - private static readonly InMemoryTestStore> Comparer = new(); + } - public InMemoryEventBusTest(ITestOutputHelper output) : base(output) - { - } + [Fact, Priority(0)] + public async Task PublishAsync_MemberCreated_OneTime() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events:1".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(MemberCreated)); - [Fact, Priority(0)] - public async Task PublishAsync_MemberCreated_OneTime() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events:1".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(MemberCreated)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); + Comparer.Add(sut3); - Comparer.Add(sut3); + await Bus.PublishAsync(sut3); + } - await Bus.PublishAsync(sut3); - } + [Fact, Priority(1)] + public async Task SubscribeAsync_MemberCreated_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "urn:member-events:1").Single(); + Bus.SubscribeAsync((sut2, _) => + { + Assert.Equal(sut1.Data, sut2.Data); + Assert.Equal(sut1.Time, sut2.Time); + Assert.Equal(sut1.Source, sut2.Source); + Assert.Equal(sut1.Id, sut2.Id); + Assert.Equal(sut1.Type, sut2.Type); + return Task.CompletedTask; + }); + } - [Fact, Priority(1)] - public async Task SubscribeAsync_MemberCreated_OneTime() + [Fact, Priority(2)] + public async Task PublishAsync_MemberCreated_ThousandTimes() + { + var messages = Generate.RangeOf(1000, i => { - var sut1 = Comparer.Query(message => message.Source == "urn:member-events:1").Single(); - Bus.SubscribeAsync((sut2, _) => - { - Assert.Equal(sut1.Data, sut2.Data); - Assert.Equal(sut1.Time, sut2.Time); - Assert.Equal(sut1.Source, sut2.Source); - Assert.Equal(sut1.Id, sut2.Id); - Assert.Equal(sut1.Type, sut2.Type); - return Task.CompletedTask; - }); - } + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage($"urn:member-events-many:{i}".ToUri(), nameof(MemberCreated)); + }); - [Fact, Priority(2)] - public async Task PublishAsync_MemberCreated_ThousandTimes() + await ParallelFactory.ForEachAsync(messages, (message, token) => { - var messages = Generate.RangeOf(1000, i => - { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new MemberCreated(Generate.RandomString(10), email).ToMessage($"urn:member-events-many:{i}".ToUri(), nameof(MemberCreated)); - }); + Comparer.Add(message); + return Bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + } - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return Bus.PublishAsync(message, o => o.CancellationToken = token); - }).ConfigureAwait(false); - } + [Fact, Priority(3)] + public async Task SubscribeAsync_MemberCreated_All() + { + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn:member-events-many")).ToList(); + var sut2 = new List>(); + var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(5)); - [Fact, Priority(3)] - public async Task SubscribeAsync_MemberCreated_All() + await Bus.SubscribeAsync((message, _) => { - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn:member-events-many")).ToList(); - var sut2 = new List>(); - var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(5)); - - await Bus.SubscribeAsync((message, _) => - { - sut2.Add(message); - return Task.CompletedTask; - }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + sut2.Add(message); + return Task.CompletedTask; + }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); - TestOutput.WriteLine(sut2.Count.ToString()); - TestOutput.WriteLines(sut2.Take(10)); + TestOutput.WriteLine(sut2.Count.ToString()); + TestOutput.WriteLines(sut2.Take(10)); - Assert.Equal(sut1.Count, sut2.Count); - Assert.Equal(sut1, sut2); - Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + Assert.Equal(sut1.Count, sut2.Count); + Assert.Equal(sut1, sut2); + Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs index 9eec3339..0783645a 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs @@ -4,28 +4,27 @@ using Savvyio.Assets.EventDriven; using Xunit; -namespace Savvyio.EventDriven.Messaging +namespace Savvyio.EventDriven.Messaging; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EncloseToMessage_CreateMemberCommand_ShouldBeWrappedInMessage() - { - var sut1 = new MemberCreated("Jane Doe", "jd@office.com"); - var sut2 = "urn:member-events:1".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(MemberCreated)); + [Fact] + public void EncloseToMessage_CreateMemberCommand_ShouldBeWrappedInMessage() + { + var sut1 = new MemberCreated("Jane Doe", "jd@office.com"); + var sut2 = "urn:member-events:1".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(MemberCreated)); - Assert.Equal(sut1.EmailAddress, sut3.Data.EmailAddress); - Assert.Equal(sut1.Name, sut3.Data.Name); - Assert.NotNull(sut3.Id); - Assert.NotNull(sut3.Time); - Assert.Equal(sut1.GetType().ToFullNameIncludingAssemblyName(), sut3.Data.GetMemberType()); - Assert.Equal(nameof(MemberCreated), sut3.Type); - Assert.Equal(sut2.OriginalString, sut3.Source); - } + Assert.Equal(sut1.EmailAddress, sut3.Data.EmailAddress); + Assert.Equal(sut1.Name, sut3.Data.Name); + Assert.NotNull(sut3.Id); + Assert.NotNull(sut3.Time); + Assert.Equal(sut1.GetType().ToFullNameIncludingAssemblyName(), sut3.Data.GetMemberType()); + Assert.Equal(nameof(MemberCreated), sut3.Type); + Assert.Equal(sut2.OriginalString, sut3.Source); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableOptionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableOptionsTest.cs index fc7fb3a0..7362893c 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableOptionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableOptionsTest.cs @@ -6,55 +6,54 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class MessageAsyncEnumerableOptionsTest : Test { - public class MessageAsyncEnumerableOptionsTest : Test + public MessageAsyncEnumerableOptionsTest(ITestOutputHelper output) : base(output) { - public MessageAsyncEnumerableOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_ShouldInitializeAcknowledgedProperties() - { - var options = new MessageAsyncEnumerableOptions(); + [Fact] + public void Ctor_ShouldInitializeAcknowledgedProperties() + { + var options = new MessageAsyncEnumerableOptions(); - Assert.IsType>>(options.AcknowledgedProperties); - } + Assert.IsType>>(options.AcknowledgedProperties); + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenAcknowledgedPropertiesIsNull() + [Fact] + public void ValidateOptions_ShouldThrow_WhenAcknowledgedPropertiesIsNull() + { + var options = new MessageAsyncEnumerableOptions { - var options = new MessageAsyncEnumerableOptions - { - AcknowledgedProperties = null, - MessageCallback = _ => Task.CompletedTask - }; + AcknowledgedProperties = null, + MessageCallback = _ => Task.CompletedTask + }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenMessageCallbackIsNull() + [Fact] + public void ValidateOptions_ShouldThrow_WhenMessageCallbackIsNull() + { + var options = new MessageAsyncEnumerableOptions { - var options = new MessageAsyncEnumerableOptions - { - AcknowledgedProperties = new ConcurrentBag>() - }; + AcknowledgedProperties = new ConcurrentBag>() + }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldSucceed_WhenRequiredPropertiesAreSet() + [Fact] + public void ValidateOptions_ShouldSucceed_WhenRequiredPropertiesAreSet() + { + var options = new MessageAsyncEnumerableOptions { - var options = new MessageAsyncEnumerableOptions - { - AcknowledgedProperties = new ConcurrentBag>(), - MessageCallback = _ => Task.CompletedTask - }; - - options.ValidateOptions(); - } + AcknowledgedProperties = new ConcurrentBag>(), + MessageCallback = _ => Task.CompletedTask + }; + + options.ValidateOptions(); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableTest.cs index 4ef826e1..3c398137 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/MessageAsyncEnumerableTest.cs @@ -7,55 +7,54 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class MessageAsyncEnumerableTest : Test { - public class MessageAsyncEnumerableTest : Test + public MessageAsyncEnumerableTest(ITestOutputHelper output) : base(output) { - public MessageAsyncEnumerableTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_ShouldThrowArgumentNullException_WhenSourceIsNull() - { - Assert.Throws(() => new MessageAsyncEnumerable((IAsyncEnumerable>)null)); - } + [Fact] + public void Ctor_ShouldThrowArgumentNullException_WhenSourceIsNull() + { + Assert.Throws(() => new MessageAsyncEnumerable((IAsyncEnumerable>)null)); + } - [Fact] - public async Task GetAsyncEnumerator_ShouldInvokeCallbacks_AndCollectAcknowledgedProperties() + [Fact] + public async Task GetAsyncEnumerator_ShouldInvokeCallbacks_AndCollectAcknowledgedProperties() + { + var callbacks = new List(); + List> acknowledged = null; + var utc = DateTime.UtcNow; + var source = new IMessage[] + { + new Message("mid1", "urn:members:1".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("Jane", 21, "jane@example.com"), utc), + new Message("mid2", "urn:members:2".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("John", 22, "john@example.com"), utc) + }; + var sut = new MessageAsyncEnumerable(source, o => { - var callbacks = new List(); - List> acknowledged = null; - var utc = DateTime.UtcNow; - var source = new IMessage[] + o.MessageCallback = async message => { - new Message("mid1", "urn:members:1".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("Jane", 21, "jane@example.com"), utc), - new Message("mid2", "urn:members:2".ToUri(), nameof(CreateMemberCommand), new CreateMemberCommand("John", 22, "john@example.com"), utc) + callbacks.Add(message.Id); + message.Properties["messageId"] = message.Id; + await message.AcknowledgeAsync(); }; - var sut = new MessageAsyncEnumerable(source, o => - { - o.MessageCallback = async message => - { - callbacks.Add(message.Id); - message.Properties["messageId"] = message.Id; - await message.AcknowledgeAsync(); - }; - o.AcknowledgedPropertiesCallback = properties => - { - acknowledged = properties.ToList(); - return Task.CompletedTask; - }; - }); - - await foreach (var message in sut) + o.AcknowledgedPropertiesCallback = properties => { - Assert.NotNull(message); - } + acknowledged = properties.ToList(); + return Task.CompletedTask; + }; + }); - Assert.Equal(new[] { "mid1", "mid2" }, callbacks); - Assert.NotNull(acknowledged); - Assert.Equal(2, acknowledged.Count); - Assert.Equal(new[] { "mid1", "mid2" }, acknowledged.Select(p => p["messageId"]).Cast().OrderBy(id => id).ToArray()); + await foreach (var message in sut) + { + Assert.NotNull(message); } + + Assert.Equal(new[] { "mid1", "mid2" }, callbacks); + Assert.NotNull(acknowledged); + Assert.Equal(2, acknowledged.Count); + Assert.Equal(new[] { "mid1", "mid2" }, acknowledged.Select(p => p["messageId"]).Cast().OrderBy(id => id).ToArray()); } } diff --git a/test/Savvyio.EventDriven.Tests/Messaging/MessageOptionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/MessageOptionsTest.cs index 6f5c04e4..301b4cf3 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/MessageOptionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/MessageOptionsTest.cs @@ -2,36 +2,35 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Messaging +namespace Savvyio.Messaging; + +public class MessageOptionsTest : Test { - public class MessageOptionsTest : Test + public MessageOptionsTest(ITestOutputHelper output) : base(output) { - public MessageOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenMessageIdIsNull() - { - var options = new MessageOptions { MessageId = null }; + [Fact] + public void ValidateOptions_ShouldThrow_WhenMessageIdIsNull() + { + var options = new MessageOptions { MessageId = null }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldThrow_WhenTimeIsNotUtc() - { - var options = new MessageOptions { Time = DateTime.Now }; + [Fact] + public void ValidateOptions_ShouldThrow_WhenTimeIsNotUtc() + { + var options = new MessageOptions { Time = DateTime.Now }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_ShouldSucceed_WhenValid() - { - var options = new MessageOptions { MessageId = "abc", Time = DateTime.UtcNow }; + [Fact] + public void ValidateOptions_ShouldSucceed_WhenValid() + { + var options = new MessageOptions { MessageId = "abc", Time = DateTime.UtcNow }; - options.ValidateOptions(); - } + options.ValidateOptions(); } } diff --git a/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs index b080cc66..729bf22a 100644 --- a/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs @@ -2,42 +2,41 @@ using Savvyio.Assets; using Xunit; -namespace Savvyio.EventDriven +namespace Savvyio.EventDriven; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddHandlers(); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - } + [Fact] + public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddHandlers(); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + } - [Fact] - public void AddIntegrationEventHandler_ShouldAddDomainEventHandler() - { - var sut = new SavvyioOptions().AddIntegrationEventHandler(); + [Fact] + public void AddIntegrationEventHandler_ShouldAddDomainEventHandler() + { + var sut = new SavvyioOptions().AddIntegrationEventHandler(); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IIntegrationEventHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountEventHandler), type)); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IIntegrationEventHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountEventHandler), type)); + } - [Fact] - public void AddIntegrationEventDispatcher_ShouldAddDomainEventDispatcher() - { - var sut = new SavvyioOptions().AddIntegrationEventDispatcher(); + [Fact] + public void AddIntegrationEventDispatcher_ShouldAddDomainEventDispatcher() + { + var sut = new SavvyioOptions().AddIntegrationEventDispatcher(); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IIntegrationEventDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(IntegrationEventDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IIntegrationEventDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(IntegrationEventDispatcher), type)); } } diff --git a/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs b/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs index 5e971740..94cf183f 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs @@ -6,38 +6,37 @@ using Dapper; using Savvyio.Assets.Domain; -namespace Savvyio.Extensions.Dapper.Assets +namespace Savvyio.Extensions.Dapper.Assets; + +public class AccountData : DapperDataStore { - public class AccountData : DapperDataStore + public AccountData(IDapperDataSource source) : base(source) { - public AccountData(IDapperDataSource source) : base(source) - { - } + } - public override Task CreateAsync(Account dto, Action setup = null) - { - return Source.ExecuteAsync("INSERT INTO AccountProjection (FullName, EmailAddress) VALUES (@FullName, @EmailAddress)", dto); - } + public override Task CreateAsync(Account dto, Action setup = null) + { + return Source.ExecuteAsync("INSERT INTO AccountProjection (FullName, EmailAddress) VALUES (@FullName, @EmailAddress)", dto); + } - public override Task UpdateAsync(Account dto, Action setup = null) - { - return Source.ExecuteAsync("UPDATE AccountProjection SET FullName = @FullName WHERE Id = @Id", dto); - } + public override Task UpdateAsync(Account dto, Action setup = null) + { + return Source.ExecuteAsync("UPDATE AccountProjection SET FullName = @FullName WHERE Id = @Id", dto); + } - public override Task GetByIdAsync(object id, Action setup) - { - return Source.QuerySingleOrDefaultAsync("SELECT * FROM AccountProjection WHERE Id = @Id", id); - } + public override Task GetByIdAsync(object id, Action setup) + { + return Source.QuerySingleOrDefaultAsync("SELECT * FROM AccountProjection WHERE Id = @Id", id); + } - public override async Task> FindAllAsync(Action setup = null) - { - var cd = setup.Configure(); - return setup == null ? await Source.QueryAsync("SELECT * FROM AccountProjection").ConfigureAwait(false) : await Source.QueryAsync(cd).ConfigureAwait(false); - } + public override async Task> FindAllAsync(Action setup = null) + { + var cd = setup.Configure(); + return setup == null ? await Source.QueryAsync("SELECT * FROM AccountProjection").ConfigureAwait(false) : await Source.QueryAsync(cd).ConfigureAwait(false); + } - public override Task DeleteAsync(Account dto, Action setup = null) - { - return Source.ExecuteAsync("DELETE FROM AccountProjection WHERE Id = @Id", dto); - } + public override Task DeleteAsync(Account dto, Action setup = null) + { + return Source.ExecuteAsync("DELETE FROM AccountProjection WHERE Id = @Id", dto); } } diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs index c105b4bd..8c63f48b 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs @@ -2,33 +2,32 @@ using Microsoft.Data.Sqlite; using Xunit; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +public class DapperDataSourceOptionsTest : Test { - public class DapperDataSourceOptionsTest : Test + public DapperDataSourceOptionsTest(ITestOutputHelper output) : base(output) { - public DapperDataSourceOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DapperDataSourceOptions_Ensure_Initialization_Defaults() - { - var sut = new DapperDataSourceOptions(); + [Fact] + public void DapperDataSourceOptions_Ensure_Initialization_Defaults() + { + var sut = new DapperDataSourceOptions(); - Assert.Null(sut.ConnectionFactory); - } + Assert.Null(sut.ConnectionFactory); + } - [Fact] - public void DapperDataSourceOptions_ValidateOptions_ShouldPassWhenConnectionFactoryIsSet() + [Fact] + public void DapperDataSourceOptions_ValidateOptions_ShouldPassWhenConnectionFactoryIsSet() + { + var sut = new DapperDataSourceOptions { - var sut = new DapperDataSourceOptions - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") - }; + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") + }; - var exception = Record.Exception(sut.ValidateOptions); + var exception = Record.Exception(sut.ValidateOptions); - Assert.Null(exception); - } + Assert.Null(exception); } } diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs index 2dc4c21a..9f1e13db 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs @@ -5,119 +5,118 @@ using Microsoft.Data.Sqlite; using Xunit; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +public class DapperDataSourceTest : Test { - public class DapperDataSourceTest : Test + public DapperDataSourceTest(ITestOutputHelper output) : base(output) { - public DapperDataSourceTest(ITestOutputHelper output) : base(output) - { - } + } - [Theory] - [MemberData(nameof(GetDapperDataSourceOptions))] - public void DapperDataSource_ShouldFailWithArgumentNullException(DapperDataSourceOptions options) - { - var sut = options == null - ? Assert.Throws(() => new DapperDataSource(options)) - : Assert.Throws(() => new DapperDataSource(options)); - TestOutput.WriteLine(sut.ToString()); - } + [Theory] + [MemberData(nameof(GetDapperDataSourceOptions))] + public void DapperDataSource_ShouldFailWithArgumentNullException(DapperDataSourceOptions options) + { + var sut = options == null + ? Assert.Throws(() => new DapperDataSource(options)) + : Assert.Throws(() => new DapperDataSource(options)); + TestOutput.WriteLine(sut.ToString()); + } - private static IEnumerable GetDapperDataSourceOptions() + private static IEnumerable GetDapperDataSourceOptions() + { + return new List { - return new List - { - new object[] { null }, - new object[] { new DapperDataSourceOptions() } - }; - } + new object[] { null }, + new object[] { new DapperDataSourceOptions() } + }; + } - [Fact] - public void DapperDataSource_ShouldFailWithInvalidOperationException() + [Fact] + public void DapperDataSource_ShouldFailWithInvalidOperationException() + { + var options = new DapperDataSourceOptions() { - var options = new DapperDataSourceOptions() + ConnectionFactory = () => { - ConnectionFactory = () => - { - var cnn = new SqliteConnection("Data Source=:memory:"); - cnn.Open(); - return cnn; - } - }; - var sut = new DapperDataSource(options); - sut.Dispose(); - - Assert.Throws(() => sut.BeginTransaction()); - Assert.True(sut.Disposed); - } + var cnn = new SqliteConnection("Data Source=:memory:"); + cnn.Open(); + return cnn; + } + }; + var sut = new DapperDataSource(options); + sut.Dispose(); - [Fact] - public void DapperDataSource_ShouldExposeConnectionMembers() + Assert.Throws(() => sut.BeginTransaction()); + Assert.True(sut.Disposed); + } + + [Fact] + public void DapperDataSource_ShouldExposeConnectionMembers() + { + var sut = new DapperDataSource(new DapperDataSourceOptions { - var sut = new DapperDataSource(new DapperDataSourceOptions - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") - }); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") + }); - Assert.Equal(ConnectionState.Open, sut.State); - Assert.NotNull(sut.CreateCommand()); - Assert.Equal("Data Source=:memory:", sut.ConnectionString); + Assert.Equal(ConnectionState.Open, sut.State); + Assert.NotNull(sut.CreateCommand()); + Assert.Equal("Data Source=:memory:", sut.ConnectionString); - using (var transaction = sut.BeginTransaction()) - { - Assert.NotNull(transaction); - transaction.Rollback(); - } + using (var transaction = sut.BeginTransaction()) + { + Assert.NotNull(transaction); + transaction.Rollback(); + } - Assert.Throws(() => sut.ChangeDatabase("main")); - Assert.Equal("main", sut.Database); + Assert.Throws(() => sut.ChangeDatabase("main")); + Assert.Equal("main", sut.Database); - sut.Close(); - Assert.Equal(ConnectionState.Closed, sut.State); + sut.Close(); + Assert.Equal(ConnectionState.Closed, sut.State); - sut.Open(); - Assert.Equal(ConnectionState.Open, sut.State); - } + sut.Open(); + Assert.Equal(ConnectionState.Open, sut.State); + } - [Fact] - public void DapperDataSource_ShouldSupportBeginTransactionWithIsolationLevel() + [Fact] + public void DapperDataSource_ShouldSupportBeginTransactionWithIsolationLevel() + { + var sut = new DapperDataSource(new DapperDataSourceOptions { - var sut = new DapperDataSource(new DapperDataSourceOptions - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") - }); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") + }); - using var transaction = sut.BeginTransaction(IsolationLevel.ReadCommitted); + using var transaction = sut.BeginTransaction(IsolationLevel.ReadCommitted); - Assert.NotNull(transaction); - } + Assert.NotNull(transaction); + } - [Fact] - public void DapperDataSource_ShouldExposeConnectionTimeout() + [Fact] + public void DapperDataSource_ShouldExposeConnectionTimeout() + { + var sut = new DapperDataSource(new DapperDataSourceOptions { - var sut = new DapperDataSource(new DapperDataSourceOptions - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") - }); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") + }); - var timeout = sut.ConnectionTimeout; + var timeout = sut.ConnectionTimeout; - Assert.True(timeout >= 0); - TestOutput.WriteLine($"ConnectionTimeout: {timeout}"); - } + Assert.True(timeout >= 0); + TestOutput.WriteLine($"ConnectionTimeout: {timeout}"); + } - [Fact] - public void DapperDataSource_ShouldSupportConnectionStringSetter() + [Fact] + public void DapperDataSource_ShouldSupportConnectionStringSetter() + { + var sut = new DapperDataSource(new DapperDataSourceOptions { - var sut = new DapperDataSource(new DapperDataSourceOptions - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") - }); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:") + }); - sut.Close(); - sut.ConnectionString = "Data Source=:memory:"; + sut.Close(); + sut.ConnectionString = "Data Source=:memory:"; - Assert.Equal("Data Source=:memory:", sut.ConnectionString); - } + Assert.Equal("Data Source=:memory:", sut.ConnectionString); } } diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperDataStoreTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperDataStoreTest.cs index a3ddc3cc..672c7a46 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperDataStoreTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperDataStoreTest.cs @@ -7,109 +7,108 @@ using Savvyio.Extensions.Dapper.Assets; using Xunit; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +public class DapperDataStoreTest : Test { - public class DapperDataStoreTest : Test + public DapperDataStoreTest(ITestOutputHelper output) : base(output) { - public DapperDataStoreTest(ITestOutputHelper output) : base(output) - { - } + } + + [Fact] + public async Task DapperDataAccessObject_ShouldCreateObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; - [Fact] - public async Task DapperDataAccessObject_ShouldCreateObject() + var options = new DapperDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }; - var options = new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }; + var sut1 = new DapperDataSource(options); - var sut1 = new DapperDataSource(options); + var sut2 = new AccountData(sut1); + await sut2.CreateAsync(new Account(id, name, email)); - var sut2 = new AccountData(sut1); - await sut2.CreateAsync(new Account(id, name, email)); + var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); + sut2.Dispose(); - sut2.Dispose(); + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.Equal(name, sut3.FullName); + Assert.Equal(email, sut3.EmailAddress); + } - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.Equal(name, sut3.FullName); - Assert.Equal(email, sut3.EmailAddress); - } + [Fact] + public async Task DapperDataAccessObject_ShouldRemoveObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; + var dto = new Account(id, name, email); - [Fact] - public async Task DapperDataAccessObject_ShouldRemoveObject() + var options = new DapperDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; - var dto = new Account(id, name, email); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }; - var options = new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }; + var sut1 = new DapperDataSource(options); - var sut1 = new DapperDataSource(options); + var sut2 = new AccountData(sut1); + await sut2.CreateAsync(dto); - var sut2 = new AccountData(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); + await sut2.DeleteAsync(sut3); - await sut2.DeleteAsync(sut3); + var sut4 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection"); - var sut4 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection"); + sut2.Dispose(); - sut2.Dispose(); + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.NotNull(sut3); + Assert.Empty(sut4); + } - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.NotNull(sut3); - Assert.Empty(sut4); - } + [Fact] + public async Task DapperDataAccessObject_ShouldUpdateObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var newName = "Unit Test"; + var email = "test@unit.test"; + var dto = new Account(id, name, email); - [Fact] - public async Task DapperDataAccessObject_ShouldUpdateObject() + var sut1 = new DapperDataSource(new DapperDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var newName = "Unit Test"; - var email = "test@unit.test"; - var dto = new Account(id, name, email); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }); - var sut1 = new DapperDataSource(new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }); + var sut2 = new AccountData(sut1); + await sut2.CreateAsync(dto); - var sut2 = new AccountData(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.CommandText = "SELECT * FROM AccountProjection WHERE Id = 1").SingleOrDefaultAsync(); + sut3.ChangeFullName(newName); - sut3.ChangeFullName(newName); + await sut2.UpdateAsync(sut3); - await sut2.UpdateAsync(sut3); - - var sut4 = await sut2.FindAllAsync(o => - { - o.Parameters = new { sut3.Id }; - o.CommandText = "SELECT * FROM AccountProjection WHERE Id = @Id"; - }).SingleOrDefaultAsync(); + var sut4 = await sut2.FindAllAsync(o => + { + o.Parameters = new { sut3.Id }; + o.CommandText = "SELECT * FROM AccountProjection WHERE Id = @Id"; + }).SingleOrDefaultAsync(); - sut2.Dispose(); + sut2.Dispose(); - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.NotEqual(name, sut3.FullName); - Assert.Equal(newName, sut4.FullName); - } + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.NotEqual(name, sut3.FullName); + Assert.Equal(newName, sut4.FullName); } } diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs index 73cb373f..4ead7c84 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs @@ -7,65 +7,64 @@ using Microsoft.Data.Sqlite; using Xunit; -namespace Savvyio.Extensions.Dapper +namespace Savvyio.Extensions.Dapper; + +public class DapperQueryOptionsTest : Test { - public class DapperQueryOptionsTest : Test + public DapperQueryOptionsTest(ITestOutputHelper output) : base(output) { - public DapperQueryOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DapperOptions_Ensure_Initialization_Defaults() - { - var sut = new DapperQueryOptions(); + [Fact] + public void DapperOptions_Ensure_Initialization_Defaults() + { + var sut = new DapperQueryOptions(); - var cd = (CommandDefinition)sut; + var cd = (CommandDefinition)sut; - Assert.Null(sut.CommandText); - Assert.Equal(CommandFlags.Buffered, sut.CommandFlags); - Assert.Equal(TimeSpan.FromSeconds(30), sut.CommandTimeout); - Assert.Equal(CommandType.Text, sut.CommandType); - Assert.Null(sut.Parameters); - Assert.Null(sut.Transaction); - Assert.Equal(default(CancellationToken), sut.CancellationToken); - Assert.Equal(sut.CommandText, cd.CommandText); - Assert.Equal(sut.CommandFlags, cd.Flags); - Assert.Equal(sut.CommandTimeout.TotalSeconds.As(), cd.CommandTimeout); - Assert.Equal(sut.CommandType, cd.CommandType); - Assert.Equal(sut.Parameters, cd.Parameters); - Assert.Equal(sut.Transaction, cd.Transaction); + Assert.Null(sut.CommandText); + Assert.Equal(CommandFlags.Buffered, sut.CommandFlags); + Assert.Equal(TimeSpan.FromSeconds(30), sut.CommandTimeout); + Assert.Equal(CommandType.Text, sut.CommandType); + Assert.Null(sut.Parameters); + Assert.Null(sut.Transaction); + Assert.Equal(default(CancellationToken), sut.CancellationToken); + Assert.Equal(sut.CommandText, cd.CommandText); + Assert.Equal(sut.CommandFlags, cd.Flags); + Assert.Equal(sut.CommandTimeout.TotalSeconds.As(), cd.CommandTimeout); + Assert.Equal(sut.CommandType, cd.CommandType); + Assert.Equal(sut.Parameters, cd.Parameters); + Assert.Equal(sut.Transaction, cd.Transaction); - } + } - [Fact] - public void DapperOptions_ShouldPreserveCustomValuesInImplicitConversion() + [Fact] + public void DapperOptions_ShouldPreserveCustomValuesInImplicitConversion() + { + using var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + using var transaction = connection.BeginTransaction(); + using var cts = new CancellationTokenSource(); + var parameters = new { Id = 42 }; + var sut = new DapperQueryOptions { - using var connection = new SqliteConnection("Data Source=:memory:"); - connection.Open(); - using var transaction = connection.BeginTransaction(); - using var cts = new CancellationTokenSource(); - var parameters = new { Id = 42 }; - var sut = new DapperQueryOptions - { - CommandText = "SELECT 1", - CommandFlags = CommandFlags.NoCache, - CommandTimeout = TimeSpan.FromSeconds(12), - CommandType = CommandType.StoredProcedure, - Parameters = parameters, - Transaction = transaction, - CancellationToken = cts.Token - }; + CommandText = "SELECT 1", + CommandFlags = CommandFlags.NoCache, + CommandTimeout = TimeSpan.FromSeconds(12), + CommandType = CommandType.StoredProcedure, + Parameters = parameters, + Transaction = transaction, + CancellationToken = cts.Token + }; - var cd = (CommandDefinition)sut; + var cd = (CommandDefinition)sut; - Assert.Equal("SELECT 1", cd.CommandText); - Assert.Equal(CommandFlags.NoCache, cd.Flags); - Assert.Equal(12, cd.CommandTimeout); - Assert.Equal(CommandType.StoredProcedure, cd.CommandType); - Assert.Equal(parameters, cd.Parameters); - Assert.Equal(transaction, cd.Transaction); - Assert.Equal(cts.Token, cd.CancellationToken); - } + Assert.Equal("SELECT 1", cd.CommandText); + Assert.Equal(CommandFlags.NoCache, cd.Flags); + Assert.Equal(12, cd.CommandTimeout); + Assert.Equal(CommandType.StoredProcedure, cd.CommandType); + Assert.Equal(parameters, cd.Parameters); + Assert.Equal(transaction, cd.Transaction); + Assert.Equal(cts.Token, cd.CancellationToken); } } diff --git a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsDataStoreTest.cs b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsDataStoreTest.cs index 54693b71..4da1769d 100644 --- a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsDataStoreTest.cs +++ b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsDataStoreTest.cs @@ -8,107 +8,106 @@ using Savvyio.Extensions.Dapper; using Xunit; -namespace Savvyio.Extensions.DapperExtensions +namespace Savvyio.Extensions.DapperExtensions; + +public class DapperExtensionsDataStoreTest : Test { - public class DapperExtensionsDataStoreTest : Test + public DapperExtensionsDataStoreTest(ITestOutputHelper output) : base(output) { - public DapperExtensionsDataStoreTest(ITestOutputHelper output) : base(output) - { - DapperAsyncExtensions.SqlDialect = new SqliteDialect(); - } + DapperAsyncExtensions.SqlDialect = new SqliteDialect(); + } - [Fact] - public async Task DataStore_ShouldCreateObject() + [Fact] + public async Task DataStore_ShouldCreateObject() + { + var name = "Test"; + var email = "test@unit.test"; + + var options = new DapperDataSourceOptions() { - var name = "Test"; - var email = "test@unit.test"; + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }; - var options = new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }; + var sut1 = new DapperDataSource(options); - var sut1 = new DapperDataSource(options); + var sut2 = new DapperExtensionsDataStore(sut1); + await sut2.CreateAsync(new AccountProjection(name, email)); - var sut2 = new DapperExtensionsDataStore(sut1); - await sut2.CreateAsync(new AccountProjection(name, email)); + var sut3 = await sut2.GetByIdAsync(1); - var sut3 = await sut2.GetByIdAsync(1); + sut2.Dispose(); - sut2.Dispose(); + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.Equal(name, sut3.FullName); + Assert.Equal(email, sut3.EmailAddress); + } - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.Equal(name, sut3.FullName); - Assert.Equal(email, sut3.EmailAddress); - } + [Fact] + public async Task DataStore_ShouldRemoveObject() + { + var name = "Test"; + var email = "test@unit.test"; + var dto = new AccountProjection(name, email); - [Fact] - public async Task DataStore_ShouldRemoveObject() + var sut1 = new DapperDataSource(new DapperDataSourceOptions() { - var name = "Test"; - var email = "test@unit.test"; - var dto = new AccountProjection(name, email); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }); - var sut1 = new DapperDataSource(new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }); + var sut2 = new DapperExtensionsDataStore(sut1); + await sut2.CreateAsync(dto); - var sut2 = new DapperExtensionsDataStore(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.GetByIdAsync(1); - var sut3 = await sut2.GetByIdAsync(1); + await sut2.DeleteAsync(sut3); - await sut2.DeleteAsync(sut3); + var sut4 = await sut2.FindAllAsync(); - var sut4 = await sut2.FindAllAsync(); + var sut5 = await sut2.GetByIdAsync(1); - var sut5 = await sut2.GetByIdAsync(1); + sut2.Dispose(); - sut2.Dispose(); + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.NotNull(sut3); + Assert.Empty(sut4); + Assert.Null(sut5); + } - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.NotNull(sut3); - Assert.Empty(sut4); - Assert.Null(sut5); - } + [Fact] + public async Task DataStore_ShouldUpdateObject() + { + var name = "Test"; + var newName = "Unit Test"; + var email = "test@unit.test"; + var dto = new AccountProjection(name, email); - [Fact] - public async Task DataStore_ShouldUpdateObject() + var sut1 = new DapperDataSource(new DapperDataSourceOptions() { - var name = "Test"; - var newName = "Unit Test"; - var email = "test@unit.test"; - var dto = new AccountProjection(name, email); + ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() + }); - var sut1 = new DapperDataSource(new DapperDataSourceOptions() - { - ConnectionFactory = () => new SqliteConnection("Data Source=:memory:").SetDefaults().AddAccountTable() - }); + var sut2 = new DapperExtensionsDataStore(sut1); + await sut2.CreateAsync(dto); - var sut2 = new DapperExtensionsDataStore(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.GetByIdAsync(1); - var sut3 = await sut2.GetByIdAsync(1); + sut3.FullName = newName; - sut3.FullName = newName; + await sut2.UpdateAsync(sut3); - await sut2.UpdateAsync(sut3); - - var sut4 = await sut2.FindAllAsync(o => - { - o.Predicate = a => a.Id; - o.Value = sut3.Id; - }).SingleOrDefaultAsync(); + var sut4 = await sut2.FindAllAsync(o => + { + o.Predicate = a => a.Id; + o.Value = sut3.Id; + }).SingleOrDefaultAsync(); - sut2.Dispose(); + sut2.Dispose(); - Assert.True(sut1.Disposed, "sut1.Disposed"); - Assert.True(sut2.Disposed, "sut2.Disposed"); - Assert.NotEqual(name, sut3.FullName); - Assert.Equal(newName, sut4.FullName); - } + Assert.True(sut1.Disposed, "sut1.Disposed"); + Assert.True(sut2.Disposed, "sut2.Disposed"); + Assert.NotEqual(name, sut3.FullName); + Assert.Equal(newName, sut4.FullName); } } diff --git a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs index 5aeaf0b8..cbbb2e15 100644 --- a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs +++ b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs @@ -3,28 +3,27 @@ using Savvyio.Assets.Queries; using Xunit; -namespace Savvyio.Extensions.DapperExtensions +namespace Savvyio.Extensions.DapperExtensions; + +public class DapperExtensionsQueryOptionsTest : Test { - public class DapperExtensionsQueryOptionsTest : Test + public DapperExtensionsQueryOptionsTest(ITestOutputHelper output) : base(output) { - public DapperExtensionsQueryOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DapperOptions_Ensure_Initialization_Defaults() - { - var sut = new DapperExtensionsQueryOptions(); + [Fact] + public void DapperOptions_Ensure_Initialization_Defaults() + { + var sut = new DapperExtensionsQueryOptions(); - Assert.Null(sut.Value); - Assert.Equal(Operator.Eq, sut.Op); - Assert.Equal(DatabaseFunction.None, sut.Function); - Assert.Null(sut.FunctionParameters); - Assert.Null(sut.Predicate); - Assert.Equal(default, sut.CancellationToken); - Assert.False(sut.Not); - Assert.True(sut.UseColumnPrefix); + Assert.Null(sut.Value); + Assert.Equal(Operator.Eq, sut.Op); + Assert.Equal(DatabaseFunction.None, sut.Function); + Assert.Null(sut.FunctionParameters); + Assert.Null(sut.Predicate); + Assert.Equal(default, sut.CancellationToken); + Assert.False(sut.Not); + Assert.True(sut.UseColumnPrefix); - } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs index e7647157..083277ba 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs @@ -5,38 +5,37 @@ using Savvyio.Extensions.Dapper; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddDapperDataSource_ShouldAddDefaultImplementation() - { - var sut1 = new ServiceCollection(); - sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + [Fact] + public void AddDapperDataSource_ShouldAddDefaultImplementation() + { + var sut1 = new ServiceCollection(); + sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - Assert.IsType(sut2.GetRequiredService()); - Assert.IsType(sut2.GetRequiredService()); - Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + Assert.IsType(sut2.GetRequiredService()); + Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); + } - [Fact] - public void AddDapperDataSource_ShouldAddDefaultImplementationWithMarker() - { - var sut1 = new ServiceCollection(); - sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); + [Fact] + public void AddDapperDataSource_ShouldAddDefaultImplementationWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.Same(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.Same(sut2.GetRequiredService>(), sut2.GetRequiredService>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionRegistrationTest.cs b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionRegistrationTest.cs index 06c22814..32b92fc4 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionRegistrationTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionRegistrationTest.cs @@ -8,59 +8,58 @@ using Savvyio.Extensions.Dapper; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.Dapper +namespace Savvyio.Extensions.DependencyInjection.Dapper; + +public class ServiceCollectionRegistrationTest : Test { - public class ServiceCollectionRegistrationTest : Test + public ServiceCollectionRegistrationTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddDapperDataStore_ShouldTypeForwardPersistentDataStore() + { + var services = new ServiceCollection(); + services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + services.AddDapperDataStore(); + var provider = services.BuildServiceProvider(); + + Assert.IsType(provider.GetRequiredService>()); + } + + private sealed class FakeRecord { - public ServiceCollectionRegistrationTest(ITestOutputHelper output) : base(output) + } + + private sealed class FakeDapperDataStore : DapperDataStore + { + public FakeDapperDataStore(Savvyio.Extensions.Dapper.IDapperDataSource source) : base(source) { } - [Fact] - public void AddDapperDataStore_ShouldTypeForwardPersistentDataStore() + public override Task CreateAsync(FakeRecord dto, Action setup = null) { - var services = new ServiceCollection(); - services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - services.AddDapperDataStore(); - var provider = services.BuildServiceProvider(); - - Assert.IsType(provider.GetRequiredService>()); + return Task.CompletedTask; } - private sealed class FakeRecord + public override Task UpdateAsync(FakeRecord dto, Action setup = null) { + return Task.CompletedTask; } - private sealed class FakeDapperDataStore : DapperDataStore + public override Task GetByIdAsync(object id, Action setup = null) { - public FakeDapperDataStore(Savvyio.Extensions.Dapper.IDapperDataSource source) : base(source) - { - } - - public override Task CreateAsync(FakeRecord dto, Action setup = null) - { - return Task.CompletedTask; - } - - public override Task UpdateAsync(FakeRecord dto, Action setup = null) - { - return Task.CompletedTask; - } - - public override Task GetByIdAsync(object id, Action setup = null) - { - return Task.FromResult(null); - } + return Task.FromResult(null); + } - public override Task> FindAllAsync(Action setup = null) - { - return Task.FromResult>(Array.Empty()); - } + public override Task> FindAllAsync(Action setup = null) + { + return Task.FromResult>(Array.Empty()); + } - public override Task DeleteAsync(FakeRecord dto, Action setup = null) - { - return Task.CompletedTask; - } + public override Task DeleteAsync(FakeRecord dto, Action setup = null) + { + return Task.CompletedTask; } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs index e900ec99..94bd012b 100644 --- a/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs @@ -9,45 +9,44 @@ using Savvyio.Extensions.DependencyInjection.Data; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.DapperExtensions +namespace Savvyio.Extensions.DependencyInjection.DapperExtensions; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddDapperExtensionsDataStore_ShouldAddManyImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - sut1.AddDapperExtensionsDataStore(); - sut1.AddDapperExtensionsDataStore(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddDapperExtensionsDataStore_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + sut1.AddDapperExtensionsDataStore(); + sut1.AddDapperExtensionsDataStore(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService>>()); - Assert.IsType>(sut2.GetRequiredService>>()); - } + Assert.IsType>(sut2.GetRequiredService>>()); + Assert.IsType>(sut2.GetRequiredService>>()); + } - [Fact] - public void AddDapperExtensionsDataStore_ShouldAddManyImplementationsWithMarkers() - { - var sut1 = new ServiceCollection(); - sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - sut1.AddDapperExtensionsDataStore(); - sut1.AddDapperExtensionsDataStore(); - sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); - sut1.AddDapperExtensionsDataStore(); - sut1.AddDapperExtensionsDataStore(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddDapperExtensionsDataStore_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + sut1.AddDapperExtensionsDataStore(); + sut1.AddDapperExtensionsDataStore(); + sut1.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection("Data Source=:memory:")); + sut1.AddDapperExtensionsDataStore(); + sut1.AddDapperExtensionsDataStore(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - } + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs index c8d3a775..a5da28bc 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs @@ -13,40 +13,39 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddEfCoreTracedAggregateRepository_ShouldHaveTypeForwardedImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreTracedAggregateRepository(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddEfCoreTracedAggregateRepository_ShouldHaveTypeForwardedImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreTracedAggregateRepository(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } - [Fact] - public void AddEfCoreTracedAggregateRepository_ShouldHaveTypeForwardedImplementationsWithMarker() - { - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreTracedAggregateRepository(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddEfCoreTracedAggregateRepository_ShouldHaveTypeForwardedImplementationsWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreTracedAggregateRepository(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/AggregateDataSourceRegistrationTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/AggregateDataSourceRegistrationTest.cs index 0c7c451b..fb83e85a 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/AggregateDataSourceRegistrationTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/AggregateDataSourceRegistrationTest.cs @@ -11,50 +11,49 @@ using Savvyio.Extensions.EFCore.Domain; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain; + +public class AggregateDataSourceRegistrationTest : Test { - public class AggregateDataSourceRegistrationTest : Test + public AggregateDataSourceRegistrationTest(ITestOutputHelper output) : base(output) { - public AggregateDataSourceRegistrationTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddEfCoreAggregateDataSource_ShouldTypeForwardDefaultImplementation() - { - var services = new ServiceCollection(); - services.AddSingleton(); - services.AddEfCoreAggregateDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-" + Guid.NewGuid())); - var provider = services.BuildServiceProvider(); - - Assert.IsType(provider.GetRequiredService()); - Assert.IsType(provider.GetRequiredService()); - Assert.IsType(provider.GetRequiredService()); - } + [Fact] + public void AddEfCoreAggregateDataSource_ShouldTypeForwardDefaultImplementation() + { + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddEfCoreAggregateDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-" + Guid.NewGuid())); + var provider = services.BuildServiceProvider(); - [Fact] - public void AddEfCoreAggregateDataSource_ShouldTypeForwardMarkedImplementation() + Assert.IsType(provider.GetRequiredService()); + Assert.IsType(provider.GetRequiredService()); + Assert.IsType(provider.GetRequiredService()); + } + + [Fact] + public void AddEfCoreAggregateDataSource_ShouldTypeForwardMarkedImplementation() + { + var services = new ServiceCollection(); + services.AddSingleton(); + services.AddEfCoreAggregateDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-marker-" + Guid.NewGuid())); + var provider = services.BuildServiceProvider(); + + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + } + + private sealed class SilentDomainEventDispatcher : IDomainEventDispatcher + { + public void Raise(IDomainEvent request) { - var services = new ServiceCollection(); - services.AddSingleton(); - services.AddEfCoreAggregateDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-marker-" + Guid.NewGuid())); - var provider = services.BuildServiceProvider(); - - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); } - private sealed class SilentDomainEventDispatcher : IDomainEventDispatcher + public Task RaiseAsync(IDomainEvent request, Action setup = null) { - public void Raise(IDomainEvent request) - { - } - - public Task RaiseAsync(IDomainEvent request, Action setup = null) - { - return Task.CompletedTask; - } + return Task.CompletedTask; } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs index 71e237b2..5ac65f16 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs @@ -8,44 +8,43 @@ using Savvyio.Extensions.EFCore.Domain; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain +namespace Savvyio.Extensions.DependencyInjection.EFCore.Domain; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddEfCoreAggregateRepository_ShouldHaveTypeForwardedImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreAggregateRepository(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddEfCoreAggregateRepository_ShouldHaveTypeForwardedImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreAggregateRepository(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } - [Fact] - public void AddEfCoreAggregateRepository_ShouldHaveTypeForwardedImplementationsWithMarker() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreAggregateRepository(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddEfCoreAggregateRepository_ShouldHaveTypeForwardedImplementationsWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreAggregateRepository(); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs index 5013f750..ab24810e 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs @@ -11,112 +11,111 @@ using Savvyio.Extensions.EFCore; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.EFCore +namespace Savvyio.Extensions.DependencyInjection.EFCore; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddEfCoreDataSource_ShouldAddDefaultImplementation() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + [Fact] + public void AddEfCoreDataSource_ShouldAddDefaultImplementation() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - Assert.IsType(sut2.GetRequiredService()); - Assert.IsType(sut2.GetRequiredService()); - Assert.IsType(sut2.GetRequiredService()); - Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + Assert.IsType(sut2.GetRequiredService()); + Assert.IsType(sut2.GetRequiredService()); + Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); + } - [Fact] - public void AddEfCoreDataSource_ShouldAddDefaultImplementationWithMarker() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); + [Fact] + public void AddEfCoreDataSource_ShouldAddDefaultImplementationWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.Same(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.Same(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + } - [Fact] - public void AddEfCoreRepository_ShouldAddManyImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + [Fact] + public void AddEfCoreRepository_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } - [Fact] - public void AddEfCoreRepository_ShouldAddManyImplementationsWithMarkers() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(DbMarker))); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); + [Fact] + public void AddEfCoreRepository_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(DbMarker))); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + } - [Fact] - public void AddEfCoreDataAccessObject_ShouldAddManyImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + [Fact] + public void AddEfCoreDataAccessObject_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase("fake")); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - TestOutput.WriteLine(sut2.GetRequiredService>>().GetType().FullName); + TestOutput.WriteLine(sut2.GetRequiredService>>().GetType().FullName); - Assert.IsType>(sut2.GetRequiredService>>()); - Assert.IsType>(sut2.GetRequiredService>>()); - } + Assert.IsType>(sut2.GetRequiredService>>()); + Assert.IsType>(sut2.GetRequiredService>>()); + } - [Fact] - public void AddEfCoreDataAccessObject_ShouldAddManyImplementationsWithMarkers() - { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(DbMarker))); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); + [Fact] + public void AddEfCoreDataAccessObject_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(DbMarker))); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataSource(o => o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(AnotherDbMarker))); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - } + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs index 2ce1a04d..789937a6 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.NATS.Assets +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; + +public struct BusMarker { - 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 index 0c0bfe7e..8c6a4051 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.NATS.Assets +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; + +public struct QueueMarker { - public struct QueueMarker - { - } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs index 5884406f..7478cdac 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs @@ -12,129 +12,128 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.NATS +namespace Savvyio.Extensions.DependencyInjection.NATS; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddNatsCommandQueue_ShouldRegisterNatsCommandQueueAndConfigureOptions() + [Fact] + public void AddNatsCommandQueue_ShouldRegisterNatsCommandQueueAndConfigureOptions() + { + // Arrange + var services = new ServiceCollection(); + bool natsSetupCalled = false; + + // Act + services.AddMarshaller(); + services.AddNatsCommandQueue(options => { - // 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(); - ConfiguredOptionsAssertions.Verify(provider); - 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() + natsSetupCalled = true; + options.StreamName = "stream"; + options.ConsumerName = "consumer"; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + 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 => { - // 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(); - ConfiguredOptionsAssertions.Verify>(provider); - var queue = provider.GetService>(); - - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - - Assert.NotNull(queue); - } - - [Fact] - public void AddNatsEventBus_ShouldRegisterNatsEventBusAndConfigureOptions() + natsSetupCalled = true; + options.StreamName = "stream"; + options.ConsumerName = "consumer"; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(provider); + 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 => { - // 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(); - ConfiguredOptionsAssertions.Verify(provider); - 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() + natsSetupCalled = true; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + 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 => { - // 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(); - ConfiguredOptionsAssertions.Verify>(provider); - var bus = provider.GetService>(); - - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - - Assert.NotNull(bus); - } + natsSetupCalled = true; + options.Subject = "subject"; + }); + + // Assert + Assert.True(natsSetupCalled); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(provider); + 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.DependencyInjection.Newtonsoft.Json.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.Tests/ServiceCollectionExtensionsTest.cs index a21c5a10..550c25ba 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.Tests/ServiceCollectionExtensionsTest.cs @@ -8,83 +8,82 @@ using Savvyio.Extensions.Newtonsoft.Json; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.Tests +namespace Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.Tests; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + [Fact] + public void AddNewtonsoftJsonMarshaller_ShouldThrowOnNullServices() { - [Fact] - public void AddNewtonsoftJsonMarshaller_ShouldThrowOnNullServices() - { - // Arrange - IServiceCollection services = null; + // Arrange + IServiceCollection services = null; - // Act & Assert - Assert.Throws(() => - ServiceCollectionExtensions.AddNewtonsoftJsonMarshaller(services)); - } + // Act & Assert + Assert.Throws(() => + ServiceCollectionExtensions.AddNewtonsoftJsonMarshaller(services)); + } - [Fact] - public void AddNewtonsoftJsonMarshaller_ShouldRegisterNewtonsoftJsonMarshallerWithDefaultOptions() - { - // Arrange - var services = new ServiceCollection(); + [Fact] + public void AddNewtonsoftJsonMarshaller_ShouldRegisterNewtonsoftJsonMarshallerWithDefaultOptions() + { + // Arrange + var services = new ServiceCollection(); - // Act - services.AddNewtonsoftJsonMarshaller(); + // Act + services.AddNewtonsoftJsonMarshaller(); - // Assert - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - var marshaller = provider.GetService(); - Assert.NotNull(marshaller); + // Assert + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + var marshaller = provider.GetService(); + Assert.NotNull(marshaller); - // Check that options are registered and default formatting is None - var options = provider.GetService(); - Assert.NotNull(options); - Assert.Equal(Formatting.None, options.Settings.Formatting); - } + // Check that options are registered and default formatting is None + var options = provider.GetService(); + Assert.NotNull(options); + Assert.Equal(Formatting.None, options.Settings.Formatting); + } - [Fact] - public void AddNewtonsoftJsonMarshaller_ShouldApplyCustomJsonSetup() + [Fact] + public void AddNewtonsoftJsonMarshaller_ShouldApplyCustomJsonSetup() + { + // Arrange + var services = new ServiceCollection(); + var called = false; + + // Act + services.AddNewtonsoftJsonMarshaller(o => { - // Arrange - var services = new ServiceCollection(); - var called = false; + o.Settings.Formatting = Formatting.Indented; + called = true; + }); - // Act - services.AddNewtonsoftJsonMarshaller(o => - { - o.Settings.Formatting = Formatting.Indented; - called = true; - }); + // Assert + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + var options = provider.GetService(); + Assert.NotNull(options); + Assert.True(called); + Assert.Equal(Formatting.Indented, options.Settings.Formatting); + } - // Assert - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - var options = provider.GetService(); - Assert.NotNull(options); - Assert.True(called); - Assert.Equal(Formatting.Indented, options.Settings.Formatting); - } + [Fact] + public void AddNewtonsoftJsonMarshaller_ShouldApplyCustomServiceSetup() + { + // Arrange + var services = new ServiceCollection(); + ServiceLifetime? lifetime = null; - [Fact] - public void AddNewtonsoftJsonMarshaller_ShouldApplyCustomServiceSetup() + // Act + services.AddNewtonsoftJsonMarshaller(null, o => { - // Arrange - var services = new ServiceCollection(); - ServiceLifetime? lifetime = null; - - // Act - services.AddNewtonsoftJsonMarshaller(null, o => - { - o.Lifetime = ServiceLifetime.Scoped; - lifetime = o.Lifetime; - }); + o.Lifetime = ServiceLifetime.Scoped; + lifetime = o.Lifetime; + }); - // Assert - var descriptor = Assert.Single(services, d => d.ServiceType == typeof(NewtonsoftJsonMarshaller)); - Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); - Assert.Equal(ServiceLifetime.Scoped, lifetime); - } + // Assert + var descriptor = Assert.Single(services, d => d.ServiceType == typeof(NewtonsoftJsonMarshaller)); + Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); + Assert.Equal(ServiceLifetime.Scoped, lifetime); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/BusMarker.cs index 150b9c6c..d4212758 100644 --- a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/BusMarker.cs @@ -1,6 +1,5 @@ -namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Assets +namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Assets; + +public struct BusMarker { - public struct BusMarker - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/QueueMarker.cs index afb2514e..e2520bce 100644 --- a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/Assets/QueueMarker.cs @@ -1,6 +1,5 @@ -namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Assets +namespace Savvyio.Extensions.DependencyInjection.QueueStorage.Assets; + +public struct QueueMarker { - public struct QueueMarker - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/ServiceCollectionExtensionsTest.cs index cc3fea59..c0d42751 100644 --- a/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.QueueStorage.Tests/ServiceCollectionExtensionsTest.cs @@ -18,178 +18,177 @@ using Xunit; using Xunit.Sdk; -namespace Savvyio.Extensions.DependencyInjection.QueueStorage +namespace Savvyio.Extensions.DependencyInjection.QueueStorage; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddAzureCommandQueue_ShouldAddDefaultImplementation() { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + Action azureSetup = o => { - } + o.StorageAccountName = "account"; + o.QueueName = "queue"; + o.SasCredential = new AzureSasCredential("sas"); + }; + + var services = new ServiceCollection(); + services.AddMarshaller(); + services.AddAzureCommandQueue(azureSetup); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + + var opt1 = new AzureQueueOptions(); + var opt2 = new AzureQueueOptions(); + var opt3 = new AzureQueueOptions(); - [Fact] - public void AddAzureCommandQueue_ShouldAddDefaultImplementation() + azureSetup(opt1); + provider.GetRequiredService>()(opt2); + + Assert.Equivalent(azureSetup, provider.GetRequiredService>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } + + [Fact] + public void AddAzureCommandQueue_ShouldAddDefaultImplementationWithMarker() + { + Action> azureSetup = o => { - Action azureSetup = o => - { - o.StorageAccountName = "account"; - o.QueueName = "queue"; - o.SasCredential = new AzureSasCredential("sas"); - }; - - var services = new ServiceCollection(); - services.AddMarshaller(); - services.AddAzureCommandQueue(azureSetup); - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - - Assert.IsType(provider.GetRequiredService>()); - Assert.IsType(provider.GetRequiredService>()); - Assert.IsType(provider.GetRequiredService>()); - - var opt1 = new AzureQueueOptions(); - var opt2 = new AzureQueueOptions(); - var opt3 = new AzureQueueOptions(); - - azureSetup(opt1); - provider.GetRequiredService>()(opt2); - - Assert.Equivalent(azureSetup, provider.GetRequiredService>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } - - [Fact] - public void AddAzureCommandQueue_ShouldAddDefaultImplementationWithMarker() + o.StorageAccountName = "account"; + o.QueueName = "queue"; + o.SasCredential = new AzureSasCredential("sas"); + }; + + var services = new ServiceCollection(); + services.AddMarshaller(); + services.AddAzureCommandQueue(azureSetup); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(provider); + + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + + var opt1 = new AzureQueueOptions(); + var opt2 = new AzureQueueOptions(); + var opt3 = new AzureQueueOptions(); + + azureSetup(opt1); + provider.GetRequiredService>>()(opt2); + + Assert.Equivalent(azureSetup, provider.GetRequiredService>>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } + + [Fact] + public void AddAzureEventBus_ShouldAddDefaultImplementation() + { + Action azureQueueSetup = o => + { + o.StorageAccountName = "account"; + o.QueueName = "queue"; + o.SasCredential = new AzureSasCredential("sas"); + }; + Action azureEventBusSetup = o => { - Action> azureSetup = o => - { - o.StorageAccountName = "account"; - o.QueueName = "queue"; - o.SasCredential = new AzureSasCredential("sas"); - }; - - var services = new ServiceCollection(); - services.AddMarshaller(); - services.AddAzureCommandQueue(azureSetup); - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(provider); - - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - - var opt1 = new AzureQueueOptions(); - var opt2 = new AzureQueueOptions(); - var opt3 = new AzureQueueOptions(); - - azureSetup(opt1); - provider.GetRequiredService>>()(opt2); - - Assert.Equivalent(azureSetup, provider.GetRequiredService>>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } - - [Fact] - public void AddAzureEventBus_ShouldAddDefaultImplementation() + o.TopicEndpoint = new Uri("https://example.com"); + o.SasCredential = new AzureSasCredential("sas"); + }; + + var services = new ServiceCollection(); + services.AddMarshaller(); + services.AddAzureEventBus(azureQueueSetup, azureEventBusSetup); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + ConfiguredOptionsAssertions.Verify(provider); + + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + Assert.IsType(provider.GetRequiredService>()); + + var q1 = new AzureQueueOptions(); + var q2 = new AzureQueueOptions(); + var q3 = new AzureQueueOptions(); + var b1 = new CoreEvent.AzureEventBusOptions(); + var b2 = new CoreEvent.AzureEventBusOptions(); + var b3 = new CoreEvent.AzureEventBusOptions(); + + azureQueueSetup(q1); + provider.GetRequiredService>()(q2); + azureEventBusSetup(b1); + provider.GetRequiredService>()(b2); + + Assert.Equivalent(azureQueueSetup, provider.GetRequiredService>()); + Assert.Equivalent(azureEventBusSetup, provider.GetRequiredService>()); + Assert.Equivalent(q1, q2); + Assert.Equivalent(b1, b2); + + Assert.Throws(() => Assert.Equivalent(q1, q3)); + Assert.Throws(() => Assert.Equivalent(q2, q3)); + Assert.Throws(() => Assert.Equivalent(b1, b3)); + Assert.Throws(() => Assert.Equivalent(b2, b3)); + } + + [Fact] + public void AddAzureEventBus_ShouldAddDefaultImplementationWithMarker() + { + Action> azureQueueSetup = o => { - Action azureQueueSetup = o => - { - o.StorageAccountName = "account"; - o.QueueName = "queue"; - o.SasCredential = new AzureSasCredential("sas"); - }; - Action azureEventBusSetup = o => - { - o.TopicEndpoint = new Uri("https://example.com"); - o.SasCredential = new AzureSasCredential("sas"); - }; - - var services = new ServiceCollection(); - services.AddMarshaller(); - services.AddAzureEventBus(azureQueueSetup, azureEventBusSetup); - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - ConfiguredOptionsAssertions.Verify(provider); - - Assert.IsType(provider.GetRequiredService>()); - Assert.IsType(provider.GetRequiredService>()); - Assert.IsType(provider.GetRequiredService>()); - - var q1 = new AzureQueueOptions(); - var q2 = new AzureQueueOptions(); - var q3 = new AzureQueueOptions(); - var b1 = new CoreEvent.AzureEventBusOptions(); - var b2 = new CoreEvent.AzureEventBusOptions(); - var b3 = new CoreEvent.AzureEventBusOptions(); - - azureQueueSetup(q1); - provider.GetRequiredService>()(q2); - azureEventBusSetup(b1); - provider.GetRequiredService>()(b2); - - Assert.Equivalent(azureQueueSetup, provider.GetRequiredService>()); - Assert.Equivalent(azureEventBusSetup, provider.GetRequiredService>()); - Assert.Equivalent(q1, q2); - Assert.Equivalent(b1, b2); - - Assert.Throws(() => Assert.Equivalent(q1, q3)); - Assert.Throws(() => Assert.Equivalent(q2, q3)); - Assert.Throws(() => Assert.Equivalent(b1, b3)); - Assert.Throws(() => Assert.Equivalent(b2, b3)); - } - - [Fact] - public void AddAzureEventBus_ShouldAddDefaultImplementationWithMarker() + o.StorageAccountName = "account"; + o.QueueName = "queue"; + o.SasCredential = new AzureSasCredential("sas"); + }; + Action> azureEventBusSetup = o => { - Action> azureQueueSetup = o => - { - o.StorageAccountName = "account"; - o.QueueName = "queue"; - o.SasCredential = new AzureSasCredential("sas"); - }; - Action> azureEventBusSetup = o => - { - o.TopicEndpoint = new Uri("https://example.com"); - o.SasCredential = new AzureSasCredential("sas"); - }; - - var services = new ServiceCollection(); - services.AddMarshaller(); - services.AddAzureEventBus(azureQueueSetup, azureEventBusSetup); - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(provider); - ConfiguredOptionsAssertions.Verify>(provider); - - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - Assert.IsType>(provider.GetRequiredService>()); - - var q1 = new AzureQueueOptions(); - var q2 = new AzureQueueOptions(); - var q3 = new AzureQueueOptions(); - var b1 = new DIEvent.AzureEventBusOptions(); - var b2 = new DIEvent.AzureEventBusOptions(); - var b3 = new DIEvent.AzureEventBusOptions(); - - azureQueueSetup(q1); - provider.GetRequiredService>>()(q2); - azureEventBusSetup(b1); - provider.GetRequiredService>>()(b2); - - Assert.Equivalent(azureQueueSetup, provider.GetRequiredService>>()); - Assert.Equivalent(azureEventBusSetup, provider.GetRequiredService>>()); - Assert.Equivalent(q1, q2); - Assert.Equivalent(b1, b2); - - Assert.Throws(() => Assert.Equivalent(q1, q3)); - Assert.Throws(() => Assert.Equivalent(q2, q3)); - Assert.Throws(() => Assert.Equivalent(b1, b3)); - Assert.Throws(() => Assert.Equivalent(b2, b3)); - } + o.TopicEndpoint = new Uri("https://example.com"); + o.SasCredential = new AzureSasCredential("sas"); + }; + + var services = new ServiceCollection(); + services.AddMarshaller(); + services.AddAzureEventBus(azureQueueSetup, azureEventBusSetup); + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(provider); + ConfiguredOptionsAssertions.Verify>(provider); + + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + Assert.IsType>(provider.GetRequiredService>()); + + var q1 = new AzureQueueOptions(); + var q2 = new AzureQueueOptions(); + var q3 = new AzureQueueOptions(); + var b1 = new DIEvent.AzureEventBusOptions(); + var b2 = new DIEvent.AzureEventBusOptions(); + var b3 = new DIEvent.AzureEventBusOptions(); + + azureQueueSetup(q1); + provider.GetRequiredService>>()(q2); + azureEventBusSetup(b1); + provider.GetRequiredService>>()(b2); + + Assert.Equivalent(azureQueueSetup, provider.GetRequiredService>>()); + Assert.Equivalent(azureEventBusSetup, provider.GetRequiredService>>()); + Assert.Equivalent(q1, q2); + Assert.Equivalent(b1, b2); + + Assert.Throws(() => Assert.Equivalent(q1, q3)); + Assert.Throws(() => Assert.Equivalent(q2, q3)); + Assert.Throws(() => Assert.Equivalent(b1, b3)); + Assert.Throws(() => Assert.Equivalent(b2, b3)); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs index dbbc5afd..2972a79c 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; + +public struct BusMarker { - public struct BusMarker - { - } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs index 06d36897..e18a6595 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; + +public struct QueueMarker { - public struct QueueMarker - { - } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs index 586fd5fd..06374502 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs @@ -15,140 +15,139 @@ using Xunit; using Xunit.Sdk; -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddRabbitMqCommandQueue_ShouldAddDefaultImplementation() - { - Action rabbitMqSetup = o => - { - o.QueueName = "urn:queue"; - }; + [Fact] + public void AddRabbitMqCommandQueue_ShouldAddDefaultImplementation() + { + Action rabbitMqSetup = o => + { + o.QueueName = "urn:queue"; + }; - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddRabbitMqCommandQueue(rabbitMqSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddRabbitMqCommandQueue(rabbitMqSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); - var opt1 = new RabbitMqCommandQueueOptions(); - var opt2 = new RabbitMqCommandQueueOptions(); - var opt3 = new RabbitMqCommandQueueOptions(); + var opt1 = new RabbitMqCommandQueueOptions(); + var opt2 = new RabbitMqCommandQueueOptions(); + var opt3 = new RabbitMqCommandQueueOptions(); - rabbitMqSetup.Invoke(opt1); - sut2.GetRequiredService>().Invoke(opt2); + rabbitMqSetup.Invoke(opt1); + sut2.GetRequiredService>().Invoke(opt2); - Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>()); - Assert.Equivalent(opt1, opt2); + Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>()); + Assert.Equivalent(opt1, opt2); - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } - [Fact] - public void AddRabbitMqCommandQueue_ShouldAddDefaultImplementationWithMarker() + [Fact] + public void AddRabbitMqCommandQueue_ShouldAddDefaultImplementationWithMarker() + { + Action> rabbitMqSetup = o => { - Action> rabbitMqSetup = o => - { - o.QueueName = "urn:queue"; - }; + o.QueueName = "urn:queue"; + }; - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddRabbitMqCommandQueue(rabbitMqSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddRabbitMqCommandQueue(rabbitMqSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); - var opt1 = new RabbitMqCommandQueueOptions(); - var opt2 = new RabbitMqCommandQueueOptions(); - var opt3 = new RabbitMqCommandQueueOptions(); + var opt1 = new RabbitMqCommandQueueOptions(); + var opt2 = new RabbitMqCommandQueueOptions(); + var opt3 = new RabbitMqCommandQueueOptions(); - rabbitMqSetup.Invoke(opt1); - sut2.GetRequiredService>>().Invoke(opt2); + rabbitMqSetup.Invoke(opt1); + sut2.GetRequiredService>>().Invoke(opt2); - Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>>()); - Assert.Equivalent(opt1, opt2); + Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>>()); + Assert.Equivalent(opt1, opt2); - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } - [Fact] - public void AddRabbitMqEventBus_ShouldAddDefaultImplementation() + [Fact] + public void AddRabbitMqEventBus_ShouldAddDefaultImplementation() + { + Action rabbitMqSetup = o => { - Action rabbitMqSetup = o => - { - o.ExchangeName = "urn:bus"; - }; + o.ExchangeName = "urn:bus"; + }; - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddRabbitMqEventBus(rabbitMqSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddRabbitMqEventBus(rabbitMqSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); - var opt1 = new RabbitMqEventBusOptions(); - var opt2 = new RabbitMqEventBusOptions(); - var opt3 = new RabbitMqEventBusOptions(); + var opt1 = new RabbitMqEventBusOptions(); + var opt2 = new RabbitMqEventBusOptions(); + var opt3 = new RabbitMqEventBusOptions(); - rabbitMqSetup.Invoke(opt1); - sut2.GetRequiredService>().Invoke(opt2); + rabbitMqSetup.Invoke(opt1); + sut2.GetRequiredService>().Invoke(opt2); - Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>()); - Assert.Equivalent(opt1, opt2); + Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>()); + Assert.Equivalent(opt1, opt2); - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } - [Fact] - public void AddRabbitMqEventBus_ShouldAddDefaultImplementationWithMarker() + [Fact] + public void AddRabbitMqEventBus_ShouldAddDefaultImplementationWithMarker() + { + Action> rabbitMqSetup = o => { - Action> rabbitMqSetup = o => - { - o.ExchangeName = "urn:bus"; - }; - - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddRabbitMqEventBus(rabbitMqSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - - var opt1 = new RabbitMqEventBusOptions(); - var opt2 = new RabbitMqEventBusOptions(); - var opt3 = new RabbitMqEventBusOptions(); - - rabbitMqSetup.Invoke(opt1); - sut2.GetRequiredService>>().Invoke(opt2); - - Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } + o.ExchangeName = "urn:bus"; + }; + + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddRabbitMqEventBus(rabbitMqSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + + var opt1 = new RabbitMqEventBusOptions(); + var opt2 = new RabbitMqEventBusOptions(); + var opt3 = new RabbitMqEventBusOptions(); + + rabbitMqSetup.Invoke(opt1); + sut2.GetRequiredService>>().Invoke(opt2); + + Assert.Equivalent(rabbitMqSetup, sut2.GetRequiredService>>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs index b1aa3deb..49beae81 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; + +public struct BusMarker { - public struct BusMarker - { - } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs index 1cae328b..50ef7cb2 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs @@ -1,7 +1,6 @@ -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; + +public struct QueueMarker { - public struct QueueMarker - { - } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs index 9c0ce9fd..dd0c1ab9 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs @@ -17,148 +17,147 @@ using Xunit; using Xunit.Sdk; -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddAmazonCommandQueue_ShouldAddDefaultImplementation() + [Fact] + public void AddAmazonCommandQueue_ShouldAddDefaultImplementation() + { + Action awsSetup = o => { - Action awsSetup = o => - { - o.Credentials = new AnonymousAWSCredentials(); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri("urn:queue"); - }; - - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddAmazonCommandQueue(awsSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); - - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - - var opt1 = new AmazonCommandQueueOptions(); - var opt2 = new AmazonCommandQueueOptions(); - var opt3 = new AmazonCommandQueueOptions(); - - awsSetup.Invoke(opt1); - sut2.GetRequiredService>().Invoke(opt2); - - Assert.Equivalent(awsSetup, sut2.GetRequiredService>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } - - [Fact] - public void AddAmazonCommandQueue_ShouldAddDefaultImplementationWithMarker() + o.Credentials = new AnonymousAWSCredentials(); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri("urn:queue"); + }; + + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddAmazonCommandQueue(awsSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); + + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + + var opt1 = new AmazonCommandQueueOptions(); + var opt2 = new AmazonCommandQueueOptions(); + var opt3 = new AmazonCommandQueueOptions(); + + awsSetup.Invoke(opt1); + sut2.GetRequiredService>().Invoke(opt2); + + Assert.Equivalent(awsSetup, sut2.GetRequiredService>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } + + [Fact] + public void AddAmazonCommandQueue_ShouldAddDefaultImplementationWithMarker() + { + Action> awsSetup = o => { - Action> awsSetup = o => - { - o.Credentials = new AnonymousAWSCredentials(); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri("urn:queue"); - }; - - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddAmazonCommandQueue(awsSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - - var opt1 = new AmazonCommandQueueOptions(); - var opt2 = new AmazonCommandQueueOptions(); - var opt3 = new AmazonCommandQueueOptions(); - - awsSetup.Invoke(opt1); - sut2.GetRequiredService>>().Invoke(opt2); - - Assert.Equivalent(awsSetup, sut2.GetRequiredService>>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } - - [Fact] - public void AddAmazonEventBus_ShouldAddDefaultImplementation() + o.Credentials = new AnonymousAWSCredentials(); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri("urn:queue"); + }; + + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddAmazonCommandQueue(awsSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + + var opt1 = new AmazonCommandQueueOptions(); + var opt2 = new AmazonCommandQueueOptions(); + var opt3 = new AmazonCommandQueueOptions(); + + awsSetup.Invoke(opt1); + sut2.GetRequiredService>>().Invoke(opt2); + + Assert.Equivalent(awsSetup, sut2.GetRequiredService>>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } + + [Fact] + public void AddAmazonEventBus_ShouldAddDefaultImplementation() + { + Action awsSetup = o => { - Action awsSetup = o => - { - o.Credentials = new AnonymousAWSCredentials(); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri("urn:bus"); - }; - - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddAmazonEventBus(awsSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(sut2); - - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - Assert.IsType(sut2.GetRequiredService>()); - - var opt1 = new AmazonEventBusOptions(); - var opt2 = new AmazonEventBusOptions(); - var opt3 = new AmazonEventBusOptions(); - - awsSetup.Invoke(opt1); - sut2.GetRequiredService>().Invoke(opt2); - - Assert.Equivalent(awsSetup, sut2.GetRequiredService>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } - - [Fact] - public void AddAmazonEventBus_ShouldAddDefaultImplementationWithMarker() + o.Credentials = new AnonymousAWSCredentials(); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri("urn:bus"); + }; + + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddAmazonEventBus(awsSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(sut2); + + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + Assert.IsType(sut2.GetRequiredService>()); + + var opt1 = new AmazonEventBusOptions(); + var opt2 = new AmazonEventBusOptions(); + var opt3 = new AmazonEventBusOptions(); + + awsSetup.Invoke(opt1); + sut2.GetRequiredService>().Invoke(opt2); + + Assert.Equivalent(awsSetup, sut2.GetRequiredService>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); + } + + [Fact] + public void AddAmazonEventBus_ShouldAddDefaultImplementationWithMarker() + { + Action> awsSetup = o => { - Action> awsSetup = o => - { - o.Credentials = new AnonymousAWSCredentials(); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri("urn:bus"); - }; - - var sut1 = new ServiceCollection(); - sut1.AddMarshaller(); - sut1.AddAmazonEventBus(awsSetup); - var sut2 = sut1.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify>(sut2); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - - var opt1 = new AmazonEventBusOptions(); - var opt2 = new AmazonEventBusOptions(); - var opt3 = new AmazonEventBusOptions(); - - awsSetup.Invoke(opt1); - sut2.GetRequiredService>>().Invoke(opt2); - - Assert.Equivalent(awsSetup, sut2.GetRequiredService>>()); - Assert.Equivalent(opt1, opt2); - - Assert.Throws(() => Assert.Equivalent(opt1, opt3)); - Assert.Throws(() => Assert.Equivalent(opt2, opt3)); - } + o.Credentials = new AnonymousAWSCredentials(); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri("urn:bus"); + }; + + var sut1 = new ServiceCollection(); + sut1.AddMarshaller(); + sut1.AddAmazonEventBus(awsSetup); + var sut2 = sut1.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify>(sut2); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + + var opt1 = new AmazonEventBusOptions(); + var opt2 = new AmazonEventBusOptions(); + var opt3 = new AmazonEventBusOptions(); + + awsSetup.Invoke(opt1); + sut2.GetRequiredService>>().Invoke(opt2); + + Assert.Equivalent(awsSetup, sut2.GetRequiredService>>()); + Assert.Equivalent(opt1, opt2); + + Assert.Throws(() => Assert.Equivalent(opt1, opt3)); + Assert.Throws(() => Assert.Equivalent(opt2, opt3)); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs index 6e5749fe..7fdd01a0 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs @@ -1,10 +1,9 @@ -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public class FakeDataSource : IDataSource { - public class FakeDataSource : IDataSource - { - } +} - public class FakeDataSource : FakeDataSource, IDataSource - { - } +public class FakeDataSource : FakeDataSource, IDataSource +{ } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs index 3ec4e1db..b3110ecd 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs @@ -5,50 +5,49 @@ using Savvyio.Data; using Savvyio.Extensions.DependencyInjection.Data; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public class FakeDataStore : IPersistentDataStore where T : class { - public class FakeDataStore : IPersistentDataStore where T : class + public FakeDataStore(IDataSource ds) { - public FakeDataStore(IDataSource ds) - { - } + } - public Task CreateAsync(T dto, Action setup = null) - { - throw new NotImplementedException(); - } + public Task CreateAsync(T dto, Action setup = null) + { + throw new NotImplementedException(); + } - public Task DeleteAsync(T dto, Action setup = null) - { - throw new NotImplementedException(); - } + public Task DeleteAsync(T dto, Action setup = null) + { + throw new NotImplementedException(); + } - public Task> FindAllAsync(Action setup = null) - { - throw new NotImplementedException(); - } + public Task> FindAllAsync(Action setup = null) + { + throw new NotImplementedException(); + } - public Task FindAsync(Action setup = null) - { - throw new NotImplementedException(); - } + public Task FindAsync(Action setup = null) + { + throw new NotImplementedException(); + } - public Task UpdateAsync(T dto, Action setup = null) - { - throw new NotImplementedException(); - } + public Task UpdateAsync(T dto, Action setup = null) + { + throw new NotImplementedException(); + } - public Task GetByIdAsync(object id, Action setup) - { - throw new NotImplementedException(); - } + public Task GetByIdAsync(object id, Action setup) + { + throw new NotImplementedException(); } +} - public class FakeDataStore : FakeDataStore, IPersistentDataStore where T : class +public class FakeDataStore : FakeDataStore, IPersistentDataStore where T : class +{ + public FakeDataStore(IDataSource ds) : base(ds) { - public FakeDataStore(IDataSource ds) : base(ds) - { - } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs index 66d7e4bb..8d27a326 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs @@ -6,56 +6,55 @@ using Savvyio.Domain; using Savvyio.Extensions.DependencyInjection.Domain; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public class FakeRepository : IPersistentRepository where TEntity : class, IIdentity { - public class FakeRepository : IPersistentRepository where TEntity : class, IIdentity + public FakeRepository(IDataSource ds) { - public FakeRepository(IDataSource ds) - { - } + } - public void Add(TEntity entity) - { - throw new NotImplementedException(); - } + public void Add(TEntity entity) + { + throw new NotImplementedException(); + } - public void AddRange(IEnumerable entities) - { - throw new NotImplementedException(); - } + public void AddRange(IEnumerable entities) + { + throw new NotImplementedException(); + } - public Task> FindAllAsync(Expression> predicate = null, Action setup = null) - { - throw new NotImplementedException(); - } + public Task> FindAllAsync(Expression> predicate = null, Action setup = null) + { + throw new NotImplementedException(); + } - public Task FindAsync(Expression> predicate, Action setup = null) - { - throw new NotImplementedException(); - } + public Task FindAsync(Expression> predicate, Action setup = null) + { + throw new NotImplementedException(); + } - public Task GetByIdAsync(TKey id, Action setup = null) - { - throw new NotImplementedException(); - } + public Task GetByIdAsync(TKey id, Action setup = null) + { + throw new NotImplementedException(); + } - public void Remove(TEntity entity) - { - throw new NotImplementedException(); - } + public void Remove(TEntity entity) + { + throw new NotImplementedException(); + } - public void RemoveRange(IEnumerable entities) - { - throw new NotImplementedException(); - } + public void RemoveRange(IEnumerable entities) + { + throw new NotImplementedException(); } +} - public class FakeRepository : FakeRepository, IPersistentRepository where TEntity : class, IIdentity +public class FakeRepository : FakeRepository, IPersistentRepository where TEntity : class, IIdentity +{ + public FakeRepository(IDataSource ds) : base(ds) { - public FakeRepository(IDataSource ds) : base(ds) - { - } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs index 3f7a7182..a01fb87a 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs @@ -1,8 +1,7 @@ using Savvyio.Commands; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public record TestCommand : Command { - public record TestCommand : Command - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs index 5cde07c4..35c1d152 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs @@ -2,17 +2,16 @@ using Savvyio.Commands; using Savvyio.Handlers; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public class TestCommandHandler : CommandHandler { - public class TestCommandHandler : CommandHandler + public TestCommandHandler() { - public TestCommandHandler() - { - } + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(_ => throw new NotImplementedException()); - } + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.Register(_ => throw new NotImplementedException()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs index 87ca338c..b5cdb48b 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs @@ -1,8 +1,7 @@ using Savvyio.Domain; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public record TestDomainEvent : DomainEvent { - public record TestDomainEvent : DomainEvent - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs index 4fc8e546..692c40e9 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs @@ -1,13 +1,12 @@ using Savvyio.Domain; using Savvyio.Handlers; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +public class TestDomainEventHandler : DomainEventHandler { - public class TestDomainEventHandler : DomainEventHandler + protected override void RegisterDelegates(IFireForgetRegistry handlers) { - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(delegate (TestDomainEvent _) { }); - } + handlers.Register(delegate (TestDomainEvent _) { }); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs index a847ef77..9e844383 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs @@ -1,8 +1,7 @@ using Savvyio.EventDriven; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +internal record TestIntegrationEvent : IntegrationEvent { - internal record TestIntegrationEvent : IntegrationEvent - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs index 9f851196..d332ead2 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs @@ -2,18 +2,17 @@ using Savvyio.EventDriven; using Savvyio.Handlers; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +internal class TestIntegrationEventHandler : IntegrationEventHandler { - internal class TestIntegrationEventHandler : IntegrationEventHandler + protected override void RegisterDelegates(IFireForgetRegistry handlers) { - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(Handler); - } + handlers.Register(Handler); + } - private void Handler(TestIntegrationEvent obj) - { - throw new NotImplementedException(); - } + private void Handler(TestIntegrationEvent obj) + { + throw new NotImplementedException(); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs index 5abb1fcd..16606d0a 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs @@ -1,9 +1,8 @@ using System; using Savvyio.Queries; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +internal record TestQuery : Query { - internal record TestQuery : Query - { - } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs index 79d75907..a8b2dde0 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs @@ -2,18 +2,17 @@ using Savvyio.Handlers; using Savvyio.Queries; -namespace Savvyio.Extensions.DependencyInjection.Assets +namespace Savvyio.Extensions.DependencyInjection.Assets; + +internal class TestQueryHandler : QueryHandler { - internal class TestQueryHandler : QueryHandler + protected override void RegisterDelegates(IRequestReplyRegistry handlers) { - protected override void RegisterDelegates(IRequestReplyRegistry handlers) - { - handlers.Register(Handler); - } + handlers.Register(Handler); + } - private Guid Handler(TestQuery arg) - { - throw new NotImplementedException(); - } + private Guid Handler(TestQuery arg) + { + throw new NotImplementedException(); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs index 969d9e92..673030ac 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs @@ -10,118 +10,117 @@ using Savvyio.Extensions.DependencyInjection.Domain; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.Data +namespace Savvyio.Extensions.DependencyInjection.Data; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddDataStore_ShouldAddDefaultImplementation() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddDataStore_ShouldAddDefaultImplementation_Implicit() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddDataStore_ShouldAddDefaultImplementationWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + } + + [Fact] + public void AddDataStore_ShouldAddDefaultImplementationWithMarker_Implicit() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + } + + [Fact] + public void AddRepository_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource(); + sut1.AddRepository, Account, long>(); + sut1.AddRepository, PlatformProvider, Guid>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } + + [Fact] + public void AddRepository_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource>(); + sut1.AddRepository, Account, long>(); + sut1.AddRepository, PlatformProvider, Guid>(); + sut1.AddDataSource>(); + sut1.AddRepository, Account, long>(); + sut1.AddRepository, PlatformProvider, Guid>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + } + + [Fact] + public void AddDataAccessObject_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource(); + sut1.AddDataStore, Account>(); + sut1.AddDataStore, PlatformProvider>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } + + [Fact] + public void AddDataAccessObject_ShouldAddManyImplementationsWithMarkers() { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void AddDataStore_ShouldAddDefaultImplementation() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType(sut2.GetRequiredService()); - } - - [Fact] - public void AddDataStore_ShouldAddDefaultImplementation_Implicit() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType(sut2.GetRequiredService()); - } - - [Fact] - public void AddDataStore_ShouldAddDefaultImplementationWithMarker() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - } - - [Fact] - public void AddDataStore_ShouldAddDefaultImplementationWithMarker_Implicit() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - } - - [Fact] - public void AddRepository_ShouldAddManyImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource(); - sut1.AddRepository, Account, long>(); - sut1.AddRepository, PlatformProvider, Guid>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } - - [Fact] - public void AddRepository_ShouldAddManyImplementationsWithMarkers() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource>(); - sut1.AddRepository, Account, long>(); - sut1.AddRepository, PlatformProvider, Guid>(); - sut1.AddDataSource>(); - sut1.AddRepository, Account, long>(); - sut1.AddRepository, PlatformProvider, Guid>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } - - [Fact] - public void AddDataAccessObject_ShouldAddManyImplementations() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource(); - sut1.AddDataStore, Account>(); - sut1.AddDataStore, PlatformProvider>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } - - [Fact] - public void AddDataAccessObject_ShouldAddManyImplementationsWithMarkers() - { - var sut1 = new ServiceCollection(); - sut1.AddDataSource>(); - sut1.AddDataStore, Account>(); - sut1.AddDataStore, PlatformProvider>(); - sut1.AddDataSource>(); - sut1.AddDataStore, Account>(); - sut1.AddDataStore, PlatformProvider>(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } + var sut1 = new ServiceCollection(); + sut1.AddDataSource>(); + sut1.AddDataStore, Account>(); + sut1.AddDataStore, PlatformProvider>(); + sut1.AddDataSource>(); + sut1.AddDataStore, Account>(); + sut1.AddDataStore, PlatformProvider>(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs index 9554aae9..64758e55 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs @@ -2,30 +2,29 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +public class SavvyioDependencyInjectionOptionsTest : Test { - public class SavvyioDependencyInjectionOptionsTest : Test + public SavvyioDependencyInjectionOptionsTest(ITestOutputHelper output) : base(output) { - public SavvyioDependencyInjectionOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void SavvyioDependencyInjectionOptions_Ensure_Initialization_Defaults() - { - var sut = new SavvyioDependencyInjectionOptions(); + [Fact] + public void SavvyioDependencyInjectionOptions_Ensure_Initialization_Defaults() + { + var sut = new SavvyioDependencyInjectionOptions(); - Assert.False(sut.AllowDispatcherDiscovery); - Assert.False(sut.AllowHandlerDiscovery); - Assert.False(sut.IncludeHandlerServicesDescriptor); - Assert.Equal(ServiceLifetime.Transient, sut.ServiceLocatorLifetime); - Assert.Equal(ServiceLifetime.Transient, sut.HandlerServicesLifetime); - Assert.Equal(ServiceLifetime.Transient, sut.DispatcherServicesLifetime); - Assert.Empty(sut.DispatcherImplementationTypes); - Assert.Empty(sut.DispatcherServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.AssembliesToScan); - } + Assert.False(sut.AllowDispatcherDiscovery); + Assert.False(sut.AllowHandlerDiscovery); + Assert.False(sut.IncludeHandlerServicesDescriptor); + Assert.Equal(ServiceLifetime.Transient, sut.ServiceLocatorLifetime); + Assert.Equal(ServiceLifetime.Transient, sut.HandlerServicesLifetime); + Assert.Equal(ServiceLifetime.Transient, sut.DispatcherServicesLifetime); + Assert.Empty(sut.DispatcherImplementationTypes); + Assert.Empty(sut.DispatcherServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.AssembliesToScan); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs index d5d0311b..f3bff142 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs @@ -8,48 +8,48 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddSavvyIO_ShouldIncludeHandlerServicesDescriptor() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.EnableHandlerServicesDescriptor()); - sut1.AddHandlerServicesDescriptor(); - var sut2 = sut1.BuildServiceProvider(); - var sut3 = sut2.GetRequiredService(); - Assert.NotNull(sut3); - } - - [Fact] - public void AddSavvyIO_ShouldIncludeServiceFactory() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(); - var sut2 = sut1.BuildServiceProvider(); - var sut3 = sut2.GetRequiredService(); - Assert.NotNull(sut3); - } - - [Fact] - public void AddSavvyIO_ShouldIncludeCommandHandlerFromLambda() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(Command).Assembly, typeof(TestCommand).Assembly).EnableHandlerServicesDescriptor().EnableDispatcherDiscovery().EnableHandlerDiscovery()); - sut1.AddHandlerServicesDescriptor(); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddSavvyIO_ShouldIncludeHandlerServicesDescriptor() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.EnableHandlerServicesDescriptor()); + sut1.AddHandlerServicesDescriptor(); + var sut2 = sut1.BuildServiceProvider(); + var sut3 = sut2.GetRequiredService(); + Assert.NotNull(sut3); + } - var plainText = sut2.GetRequiredService().ToString(); + [Fact] + public void AddSavvyIO_ShouldIncludeServiceFactory() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(); + var sut2 = sut1.BuildServiceProvider(); + var sut3 = sut2.GetRequiredService(); + Assert.NotNull(sut3); + } + + [Fact] + public void AddSavvyIO_ShouldIncludeCommandHandlerFromLambda() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(Command).Assembly, typeof(TestCommand).Assembly).EnableHandlerServicesDescriptor().EnableDispatcherDiscovery().EnableHandlerDiscovery()); + sut1.AddHandlerServicesDescriptor(); + var sut2 = sut1.BuildServiceProvider(); + + var plainText = sut2.GetRequiredService().ToString(); - TestOutput.WriteLine(plainText); + TestOutput.WriteLine(plainText); - Assert.True(Match(""" + Assert.True(Match(""" Discovered 1 ICommandHandler implementation covering a total of 1 ICommand method Assembly: Savvyio.Extensions.DependencyInjection.Tests @@ -91,58 +91,58 @@ Discovered 1 IQueryHandler implementation covering a total of 1 IQuery method ----------------------------------------------------------------------------- """.ReplaceLineEndings(), plainText, o => o.ThrowOnNoMatch = true)); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + } - [Fact] - public void AddSavvyIO_ShouldIncludeCommandDispatchers() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(Command).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddSavvyIO_ShouldIncludeCommandDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(Command).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + } - [Fact] - public void AddSavvyIO_ShouldNotIncludeCommandDispatchers() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyToScan(typeof(Command).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldNotIncludeCommandHandlerFromLamda() + [Fact] + public void AddSavvyIO_ShouldNotIncludeCommandDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyRangeToScan(typeof(Command).Assembly, typeof(TestCommand).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldIncludeDomainEventHandlerFromDelegate() + o.AddAssemblyToScan(typeof(Command).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.Null(sut2.GetService()); + } + + [Fact] + public void AddSavvyIO_ShouldNotIncludeCommandHandlerFromLamda() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEvent).Assembly, typeof(TestDomainEvent).Assembly).EnableHandlerServicesDescriptor().EnableDispatcherDiscovery().EnableHandlerDiscovery()); - sut1.AddHandlerServicesDescriptor(); - var sut2 = sut1.BuildServiceProvider(); + o.AddAssemblyRangeToScan(typeof(Command).Assembly, typeof(TestCommand).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.Null(sut2.GetService()); + } - var plainText = sut2.GetRequiredService().ToString(); + [Fact] + public void AddSavvyIO_ShouldIncludeDomainEventHandlerFromDelegate() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(DomainEvent).Assembly, typeof(TestDomainEvent).Assembly).EnableHandlerServicesDescriptor().EnableDispatcherDiscovery().EnableHandlerDiscovery()); + sut1.AddHandlerServicesDescriptor(); + var sut2 = sut1.BuildServiceProvider(); - TestOutput.WriteLine(plainText); + var plainText = sut2.GetRequiredService().ToString(); - Assert.True(Match(""" + TestOutput.WriteLine(plainText); + + Assert.True(Match(""" Discovered 1 ICommandHandler implementation covering a total of 1 ICommand method Assembly: Savvyio.Extensions.DependencyInjection.Tests @@ -184,163 +184,162 @@ Discovered 1 IQueryHandler implementation covering a total of 1 IQuery method ----------------------------------------------------------------------------- """.ReplaceLineEndings(), plainText, o => o.ThrowOnNoMatch = true)); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + } - [Fact] - public void AddSavvyIO_ShouldIncludeDomainEventDispatchers() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(DomainEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + [Fact] + public void AddSavvyIO_ShouldIncludeDomainEventDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(DomainEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.IsType(sut2.GetRequiredService()); + } - [Fact] - public void AddSavvyIO_ShouldNotIncludeDomainEventDispatchers() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyToScan(typeof(DomainEvent).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldNotIncludeDomainEventHandlerFromDelegate() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyRangeToScan(typeof(DomainEvent).Assembly, typeof(TestDomainEvent).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldIncludeIntegrationEventHandlerFromDeclaredMethod() + [Fact] + public void AddSavvyIO_ShouldNotIncludeDomainEventDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(IntegrationEvent).Assembly, typeof(TestIntegrationEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + o.AddAssemblyToScan(typeof(DomainEvent).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.Null(sut2.GetService()); + } - [Fact] - public void AddSavvyIO_ShouldIncludeIntegrationEventDispatchers() + [Fact] + public void AddSavvyIO_ShouldNotIncludeDomainEventHandlerFromDelegate() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(IntegrationEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + o.AddAssemblyRangeToScan(typeof(DomainEvent).Assembly, typeof(TestDomainEvent).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.Null(sut2.GetService()); + } - [Fact] - public void AddSavvyIO_ShouldNotIncludeIntegrationEventDispatchers() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyToScan(typeof(IntegrationEvent).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldNotIncludeIntegrationEventHandlerFromDeclaredMethod() - { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyRangeToScan(typeof(IntegrationEvent).Assembly, typeof(TestIntegrationEvent).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldIncludeQueryHandlerFromDeclaredMethod() + [Fact] + public void AddSavvyIO_ShouldIncludeIntegrationEventHandlerFromDeclaredMethod() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(IntegrationEvent).Assembly, typeof(TestIntegrationEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddSavvyIO_ShouldIncludeIntegrationEventDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(IntegrationEvent).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddSavvyIO_ShouldNotIncludeIntegrationEventDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(Query<>).Assembly, typeof(TestQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + o.AddAssemblyToScan(typeof(IntegrationEvent).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); - Assert.IsType(sut2.GetRequiredService()); - } + Assert.Null(sut2.GetService()); + } - [Fact] - public void AddSavvyIO_ShouldIncludeQueryDispatchers() + [Fact] + public void AddSavvyIO_ShouldNotIncludeIntegrationEventHandlerFromDeclaredMethod() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(Query<>).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); - var sut2 = sut1.BuildServiceProvider(); + o.AddAssemblyRangeToScan(typeof(IntegrationEvent).Assembly, typeof(TestIntegrationEvent).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.Null(sut2.GetService()); + } - Assert.IsType(sut2.GetRequiredService()); - } + [Fact] + public void AddSavvyIO_ShouldIncludeQueryHandlerFromDeclaredMethod() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyRangeToScan(typeof(Query<>).Assembly, typeof(TestQuery).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); - [Fact] - public void AddSavvyIO_ShouldNotIncludeQueryDispatchers() + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddSavvyIO_ShouldIncludeQueryDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => o.AddAssemblyToScan(typeof(Query<>).Assembly).EnableDispatcherDiscovery().EnableHandlerDiscovery()); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + } + + [Fact] + public void AddSavvyIO_ShouldNotIncludeQueryDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyToScan(typeof(Query<>).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldNotIncludeQueryHandlerFromDeclaredMethod() + o.AddAssemblyToScan(typeof(Query<>).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.Null(sut2.GetService()); + } + + [Fact] + public void AddSavvyIO_ShouldNotIncludeQueryHandlerFromDeclaredMethod() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddAssemblyRangeToScan(typeof(Query<>).Assembly, typeof(TestQuery).Assembly); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.Null(sut2.GetService()); - } - - [Fact] - public void AddSavvyIO_ShouldHaveAllManuallyAddedHandlersAndDispatchers() + o.AddAssemblyRangeToScan(typeof(Query<>).Assembly, typeof(TestQuery).Assembly); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.Null(sut2.GetService()); + } + + [Fact] + public void AddSavvyIO_ShouldHaveAllManuallyAddedHandlersAndDispatchers() + { + var sut1 = new ServiceCollection(); + sut1.AddSavvyIO(o => { - var sut1 = new ServiceCollection(); - sut1.AddSavvyIO(o => - { - o.AddCommandDispatcher() - .AddDomainEventDispatcher() - .AddIntegrationEventDispatcher() - .AddQueryDispatcher(); - o.AddCommandHandler() - .AddDomainEventHandler() - .AddIntegrationEventHandler() - .AddQueryHandler(); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - Assert.NotNull(sut2.GetService()); - } + o.AddCommandDispatcher() + .AddDomainEventDispatcher() + .AddIntegrationEventDispatcher() + .AddQueryDispatcher(); + o.AddCommandHandler() + .AddDomainEventHandler() + .AddIntegrationEventHandler() + .AddQueryHandler(); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); + + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); + Assert.NotNull(sut2.GetService()); } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs index 57a980e8..ea9a95b2 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs @@ -8,98 +8,97 @@ using Savvyio.Dispatchers; using Xunit; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +public class ServiceCollectionRegistrationTest : Test { - public class ServiceCollectionRegistrationTest : Test + public ServiceCollectionRegistrationTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionRegistrationTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddConfiguredOptions_ShouldRegisterAllSupportedRepresentations() - { - var services = new ServiceCollection(); - services.AddConfiguredOptions(o => o.Name = "Configured"); - var provider = services.BuildServiceProvider(); - var action = provider.GetRequiredService>(); - var target = new TestOptions(); + [Fact] + public void AddConfiguredOptions_ShouldRegisterAllSupportedRepresentations() + { + var services = new ServiceCollection(); + services.AddConfiguredOptions(o => o.Name = "Configured"); + var provider = services.BuildServiceProvider(); + var action = provider.GetRequiredService>(); + var target = new TestOptions(); - action(target); + action(target); - Assert.Equal("Configured", provider.GetRequiredService>().Value.Name); - Assert.Equal("Configured", provider.GetRequiredService().Name); - Assert.Equal("Configured", target.Name); - } + Assert.Equal("Configured", provider.GetRequiredService>().Value.Name); + Assert.Equal("Configured", provider.GetRequiredService().Name); + Assert.Equal("Configured", target.Name); + } + + [Fact] + public void AddMarshaller_ShouldRegisterFactoryImplementation() + { + var services = new ServiceCollection(); + services.AddMarshaller(_ => new FakeMarshaller(), o => o.Lifetime = ServiceLifetime.Singleton); + var provider = services.BuildServiceProvider(); + + var sut1 = provider.GetRequiredService(); + var sut2 = provider.GetRequiredService(); + + Assert.IsType(sut1); + Assert.Same(sut1, sut2); + } - [Fact] - public void AddMarshaller_ShouldRegisterFactoryImplementation() + [Fact] + public void AddServiceLocator_ShouldRespectCustomFactoryAndLifetime() + { + var services = new ServiceCollection(); + services.AddServiceLocator(o => { - var services = new ServiceCollection(); - services.AddMarshaller(_ => new FakeMarshaller(), o => o.Lifetime = ServiceLifetime.Singleton); - var provider = services.BuildServiceProvider(); + o.Lifetime = ServiceLifetime.Singleton; + o.ImplementationFactory = _ => new ServiceLocator(_ => Array.Empty()); + }); + var provider = services.BuildServiceProvider(); - var sut1 = provider.GetRequiredService(); - var sut2 = provider.GetRequiredService(); + var sut1 = provider.GetRequiredService(); + var sut2 = provider.GetRequiredService(); - Assert.IsType(sut1); - Assert.Same(sut1, sut2); - } + Assert.Same(sut1, sut2); + Assert.Empty(sut1.GetServices(typeof(string))); + } + + [Fact] + public void AddHandlerServicesDescriptor_ShouldDoNothingWhenDescriptorIsMissing() + { + var services = new ServiceCollection(); + services.AddHandlerServicesDescriptor(); + var provider = services.BuildServiceProvider(); + + Assert.Null(provider.GetService()); + } + + private sealed class TestOptions : IParameterObject + { + public string Name { get; set; } + } - [Fact] - public void AddServiceLocator_ShouldRespectCustomFactoryAndLifetime() + private sealed class FakeMarshaller : IMarshaller + { + public Stream Serialize(TValue value) { - var services = new ServiceCollection(); - services.AddServiceLocator(o => - { - o.Lifetime = ServiceLifetime.Singleton; - o.ImplementationFactory = _ => new ServiceLocator(_ => Array.Empty()); - }); - var provider = services.BuildServiceProvider(); - - var sut1 = provider.GetRequiredService(); - var sut2 = provider.GetRequiredService(); - - Assert.Same(sut1, sut2); - Assert.Empty(sut1.GetServices(typeof(string))); + return new MemoryStream(new byte[] { 1, 2, 3 }); } - [Fact] - public void AddHandlerServicesDescriptor_ShouldDoNothingWhenDescriptorIsMissing() + public Stream Serialize(object value, Type inputType) { - var services = new ServiceCollection(); - services.AddHandlerServicesDescriptor(); - var provider = services.BuildServiceProvider(); - - Assert.Null(provider.GetService()); + return new MemoryStream(new byte[] { 1, 2, 3 }); } - private sealed class TestOptions : IParameterObject + public TValue Deserialize(Stream data) { - public string Name { get; set; } + return default; } - private sealed class FakeMarshaller : IMarshaller + public object Deserialize(Stream data, Type returnType) { - public Stream Serialize(TValue value) - { - return new MemoryStream(new byte[] { 1, 2, 3 }); - } - - public Stream Serialize(object value, Type inputType) - { - return new MemoryStream(new byte[] { 1, 2, 3 }); - } - - public TValue Deserialize(Stream data) - { - return default; - } - - public object Deserialize(Stream data, Type returnType) - { - return null; - } + return null; } } } diff --git a/test/Savvyio.Extensions.DependencyInjection.Text.Json.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Text.Json.Tests/ServiceCollectionExtensionsTest.cs index 549e9a5a..05bb2cce 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Text.Json.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Text.Json.Tests/ServiceCollectionExtensionsTest.cs @@ -6,83 +6,82 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.Extensions.DependencyInjection.Text.Json.Tests +namespace Savvyio.Extensions.DependencyInjection.Text.Json.Tests; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + [Fact] + public void AddJsonMarshaller_ShouldThrowOnNullServices() { - [Fact] - public void AddJsonMarshaller_ShouldThrowOnNullServices() - { - // Arrange - IServiceCollection services = null; + // Arrange + IServiceCollection services = null; - // Act & Assert - Assert.Throws(() => - ServiceCollectionExtensions.AddJsonMarshaller(services)); - } + // Act & Assert + Assert.Throws(() => + ServiceCollectionExtensions.AddJsonMarshaller(services)); + } - [Fact] - public void AddJsonMarshaller_ShouldRegisterJsonMarshallerWithDefaultOptions() - { - // Arrange - var services = new ServiceCollection(); + [Fact] + public void AddJsonMarshaller_ShouldRegisterJsonMarshallerWithDefaultOptions() + { + // Arrange + var services = new ServiceCollection(); - // Act - services.AddJsonMarshaller(); + // Act + services.AddJsonMarshaller(); - // Assert - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - var marshaller = provider.GetService(); - Assert.NotNull(marshaller); + // Assert + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + var marshaller = provider.GetService(); + Assert.NotNull(marshaller); - // Check that options are registered and default WriteIndented is false - var options = provider.GetService(); - Assert.NotNull(options); - Assert.False(options.Settings.WriteIndented); - } + // Check that options are registered and default WriteIndented is false + var options = provider.GetService(); + Assert.NotNull(options); + Assert.False(options.Settings.WriteIndented); + } - [Fact] - public void AddJsonMarshaller_ShouldApplyCustomJsonSetup() + [Fact] + public void AddJsonMarshaller_ShouldApplyCustomJsonSetup() + { + // Arrange + var services = new ServiceCollection(); + var called = false; + + // Act + services.AddJsonMarshaller(o => { - // Arrange - var services = new ServiceCollection(); - var called = false; + o.Settings.WriteIndented = true; + called = true; + }); - // Act - services.AddJsonMarshaller(o => - { - o.Settings.WriteIndented = true; - called = true; - }); + // Assert + var provider = services.BuildServiceProvider(); + ConfiguredOptionsAssertions.Verify(provider); + var options = provider.GetService(); + Assert.NotNull(options); + Assert.True(called); + Assert.True(options.Settings.WriteIndented); + } - // Assert - var provider = services.BuildServiceProvider(); - ConfiguredOptionsAssertions.Verify(provider); - var options = provider.GetService(); - Assert.NotNull(options); - Assert.True(called); - Assert.True(options.Settings.WriteIndented); - } + [Fact] + public void AddJsonMarshaller_ShouldApplyCustomServiceSetup() + { + // Arrange + var services = new ServiceCollection(); + ServiceLifetime? lifetime = null; - [Fact] - public void AddJsonMarshaller_ShouldApplyCustomServiceSetup() + // Act + services.AddJsonMarshaller(null, o => { - // Arrange - var services = new ServiceCollection(); - ServiceLifetime? lifetime = null; - - // Act - services.AddJsonMarshaller(null, o => - { - o.Lifetime = ServiceLifetime.Scoped; - lifetime = o.Lifetime; - }); + o.Lifetime = ServiceLifetime.Scoped; + lifetime = o.Lifetime; + }); - // Assert - var descriptor = Assert.Single(services, d => d.ServiceType == typeof(JsonMarshaller)); - Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); - Assert.Equal(ServiceLifetime.Scoped, lifetime); - } + // Assert + var descriptor = Assert.Single(services, d => d.ServiceType == typeof(JsonMarshaller)); + Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime); + Assert.Equal(ServiceLifetime.Scoped, lifetime); } } diff --git a/test/Savvyio.Extensions.Dispatchers.Tests/MediatorSyncTest.cs b/test/Savvyio.Extensions.Dispatchers.Tests/MediatorSyncTest.cs index a9634f1b..647a856e 100644 --- a/test/Savvyio.Extensions.Dispatchers.Tests/MediatorSyncTest.cs +++ b/test/Savvyio.Extensions.Dispatchers.Tests/MediatorSyncTest.cs @@ -9,127 +9,126 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio.Extensions +namespace Savvyio.Extensions; + +public class MediatorSyncTest : Test { - public class MediatorSyncTest : Test + public MediatorSyncTest(ITestOutputHelper output) : base(output) { - public MediatorSyncTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Commit_ShouldDispatchCommandSynchronously() - { - var provider = CreateServiceProvider(services => services.AddTransient()); - var sut = new Mediator(provider.GetRequiredService()); + [Fact] + public void Commit_ShouldDispatchCommandSynchronously() + { + var provider = CreateServiceProvider(services => services.AddTransient()); + var sut = new Mediator(provider.GetRequiredService()); - sut.Commit(new TestMediatorCommand()); + sut.Commit(new TestMediatorCommand()); - Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("command", item)); - } + Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("command", item)); + } - [Fact] - public void Raise_ShouldDispatchDomainEventSynchronously() - { - var provider = CreateServiceProvider(services => services.AddTransient()); - var sut = new Mediator(provider.GetRequiredService()); + [Fact] + public void Raise_ShouldDispatchDomainEventSynchronously() + { + var provider = CreateServiceProvider(services => services.AddTransient()); + var sut = new Mediator(provider.GetRequiredService()); - sut.Raise(new TestMediatorDomainEvent()); + sut.Raise(new TestMediatorDomainEvent()); - Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("domain-event", item)); - } - - [Fact] - public void Publish_ShouldDispatchIntegrationEventSynchronously() - { - var provider = CreateServiceProvider(services => services.AddTransient()); - var sut = new Mediator(provider.GetRequiredService()); + Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("domain-event", item)); + } - sut.Publish(new TestMediatorIntegrationEvent()); + [Fact] + public void Publish_ShouldDispatchIntegrationEventSynchronously() + { + var provider = CreateServiceProvider(services => services.AddTransient()); + var sut = new Mediator(provider.GetRequiredService()); - Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("integration-event", item)); - } + sut.Publish(new TestMediatorIntegrationEvent()); - [Fact] - public void Query_ShouldDispatchQuerySynchronously() - { - var provider = CreateServiceProvider(services => services.AddTransient()); - var sut = new Mediator(provider.GetRequiredService()); + Assert.Collection(provider.GetRequiredService>().Query(), item => Assert.Equal("integration-event", item)); + } - var result = sut.Query(new TestMediatorQuery()); + [Fact] + public void Query_ShouldDispatchQuerySynchronously() + { + var provider = CreateServiceProvider(services => services.AddTransient()); + var sut = new Mediator(provider.GetRequiredService()); - Assert.Equal("query", result); - } + var result = sut.Query(new TestMediatorQuery()); - private static ServiceProvider CreateServiceProvider(System.Action setup) - { - var services = new ServiceCollection() - .AddServiceLocator() - .AddSingleton, InMemoryTestStore>(); + Assert.Equal("query", result); + } - setup(services); - return services.BuildServiceProvider(); - } + private static ServiceProvider CreateServiceProvider(System.Action setup) + { + var services = new ServiceCollection() + .AddServiceLocator() + .AddSingleton, InMemoryTestStore>(); - private sealed record TestMediatorCommand : Command; + setup(services); + return services.BuildServiceProvider(); + } - private sealed record TestMediatorDomainEvent : DomainEvent; + private sealed record TestMediatorCommand : Command; - private sealed record TestMediatorIntegrationEvent : IntegrationEvent; + private sealed record TestMediatorDomainEvent : DomainEvent; - private sealed record TestMediatorQuery : Query; + private sealed record TestMediatorIntegrationEvent : IntegrationEvent; - private sealed class TestMediatorCommandHandler : CommandHandler - { - private readonly ITestStore _store; + private sealed record TestMediatorQuery : Query; - public TestMediatorCommandHandler(ITestStore store) - { - _store = store; - } + private sealed class TestMediatorCommandHandler : CommandHandler + { + private readonly ITestStore _store; - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(_ => _store.Add("command")); - } + public TestMediatorCommandHandler(ITestStore store) + { + _store = store; } - private sealed class TestMediatorDomainEventHandler : DomainEventHandler + protected override void RegisterDelegates(IFireForgetRegistry handlers) { - private readonly ITestStore _store; + handlers.Register(_ => _store.Add("command")); + } + } - public TestMediatorDomainEventHandler(ITestStore store) - { - _store = store; - } + private sealed class TestMediatorDomainEventHandler : DomainEventHandler + { + private readonly ITestStore _store; - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(_ => _store.Add("domain-event")); - } + public TestMediatorDomainEventHandler(ITestStore store) + { + _store = store; } - private sealed class TestMediatorIntegrationEventHandler : IntegrationEventHandler + protected override void RegisterDelegates(IFireForgetRegistry handlers) { - private readonly ITestStore _store; + handlers.Register(_ => _store.Add("domain-event")); + } + } + + private sealed class TestMediatorIntegrationEventHandler : IntegrationEventHandler + { + private readonly ITestStore _store; - public TestMediatorIntegrationEventHandler(ITestStore store) - { - _store = store; - } + public TestMediatorIntegrationEventHandler(ITestStore store) + { + _store = store; + } - protected override void RegisterDelegates(IFireForgetRegistry handlers) - { - handlers.Register(_ => _store.Add("integration-event")); - } + protected override void RegisterDelegates(IFireForgetRegistry handlers) + { + handlers.Register(_ => _store.Add("integration-event")); } + } - private sealed class TestMediatorQueryHandler : QueryHandler + private sealed class TestMediatorQueryHandler : QueryHandler + { + protected override void RegisterDelegates(IRequestReplyRegistry handlers) { - protected override void RegisterDelegates(IRequestReplyRegistry handlers) - { - handlers.Register(_ => "query"); - } + handlers.Register(_ => "query"); } } } diff --git a/test/Savvyio.Extensions.Dispatchers.Tests/MediatorTest.cs b/test/Savvyio.Extensions.Dispatchers.Tests/MediatorTest.cs index 8d0fdd76..779495e6 100644 --- a/test/Savvyio.Extensions.Dispatchers.Tests/MediatorTest.cs +++ b/test/Savvyio.Extensions.Dispatchers.Tests/MediatorTest.cs @@ -21,155 +21,154 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio.Extensions.Dispatchers +namespace Savvyio.Extensions.Dispatchers; + +public class MediatorTest : Test { - public class MediatorTest : Test + public MediatorTest(ITestOutputHelper output) : base(output) { - public MediatorTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Host_MediatorShouldBeRegistered_UsingDefaultOptions() + [Fact] + public void Host_MediatorShouldBeRegistered_UsingDefaultOptions() + { + using (var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator()))) { - using (var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator()))) - { - var mediator = test.Host.Services.GetRequiredService(); + var mediator = test.Host.Services.GetRequiredService(); - Assert.IsType(mediator); - } + Assert.IsType(mediator); } + } - [Fact] - public void Host_MediatorDescriptorShouldNotBeRegistered_UsingDefaultOptions() - { - using var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator())); - Assert.Throws(() => test.Host.Services.GetRequiredService()); - } + [Fact] + public void Host_MediatorDescriptorShouldNotBeRegistered_UsingDefaultOptions() + { + using var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator())); + Assert.Throws(() => test.Host.Services.GetRequiredService()); + } - [Fact] - public void Host_MediatorDescriptorShouldBeRegistered() - { - using var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator().EnableHandlerServicesDescriptor()).AddHandlerServicesDescriptor()); - var descriptor = test.Host.Services.GetRequiredService(); + [Fact] + public void Host_MediatorDescriptorShouldBeRegistered() + { + using var test = HostTestFactory.Create(services => services.AddSavvyIO(registry => registry.AddMediator().EnableHandlerServicesDescriptor()).AddHandlerServicesDescriptor()); + var descriptor = test.Host.Services.GetRequiredService(); - Assert.IsType(descriptor); + Assert.IsType(descriptor); - TestOutput.WriteLine(descriptor.ToString()); - } + TestOutput.WriteLine(descriptor.ToString()); + } - [Fact] - public async Task Mediator_ShouldInvoke_CreateAccountAsync_OnInProcAccountCreated_OnOutProcAccountCreated() + [Fact] + public async Task Mediator_ShouldInvoke_CreateAccountAsync_OnInProcAccountCreated_OnOutProcAccountCreated() + { + await using var test = HostTestFactory.Create(services => { - await using var test = HostTestFactory.Create(services => + services.AddSingleton(TestOutput); + services.AddEfCoreRepository(); + services.AddEfCoreDataStore(); + services.AddDataSource() + .AddUnitOfWork(); + services.AddEfCoreDataSource(o => { - services.AddSingleton(TestOutput); - services.AddEfCoreRepository(); - services.AddEfCoreDataStore(); - services.AddDataSource() - .AddUnitOfWork(); - services.AddEfCoreDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddPlatformProvider(); - }); - services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator()); - services.AddHandlerServicesDescriptor(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); + o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddPlatformProvider(); }); - using var scope = test.Host.Services.CreateScope(); - var mediator = scope.ServiceProvider.GetRequiredService(); - var descriptor = scope.ServiceProvider.GetRequiredService(); - var deStore = scope.ServiceProvider.GetRequiredService>(); - var ieStore = scope.ServiceProvider.GetRequiredService>(); - - TestOutput.WriteLine(descriptor.ToString()); - - var id = Guid.NewGuid(); - var clientProvidedCorrelationId = Guid.NewGuid().ToString("N"); - - await mediator.CommitAsync(new CreateAccount(id, "Michael Mortensen", "root@gimlichael.dev") - .SetCorrelationId(clientProvidedCorrelationId) - .SetCausationId(clientProvidedCorrelationId)); - - Assert.Equal(id, deStore.QueryFor().Single().PlatformProviderId); - Assert.InRange(ieStore.QueryFor().Single().Id, 1, 100000); - } + services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator()); + services.AddHandlerServicesDescriptor(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + }); + using var scope = test.Host.Services.CreateScope(); + var mediator = scope.ServiceProvider.GetRequiredService(); + var descriptor = scope.ServiceProvider.GetRequiredService(); + var deStore = scope.ServiceProvider.GetRequiredService>(); + var ieStore = scope.ServiceProvider.GetRequiredService>(); + + TestOutput.WriteLine(descriptor.ToString()); + + var id = Guid.NewGuid(); + var clientProvidedCorrelationId = Guid.NewGuid().ToString("N"); + + await mediator.CommitAsync(new CreateAccount(id, "Michael Mortensen", "root@gimlichael.dev") + .SetCorrelationId(clientProvidedCorrelationId) + .SetCausationId(clientProvidedCorrelationId)); + + Assert.Equal(id, deStore.QueryFor().Single().PlatformProviderId); + Assert.InRange(ieStore.QueryFor().Single().Id, 1, 100000); + } - [Fact] - public async Task Mediator_ShouldInvoke_CreatePlatformProviderAsyncLambda_OnInProcPlatformProviderInitiated_OnOutProcPlatformProviderCreated() + [Fact] + public async Task Mediator_ShouldInvoke_CreatePlatformProviderAsyncLambda_OnInProcPlatformProviderInitiated_OnOutProcPlatformProviderCreated() + { + await using var test = HostTestFactory.Create(services => { - await using var test = HostTestFactory.Create(services => + services.AddSingleton(TestOutput); + services.AddEfCoreRepository(); + services.AddEfCoreDataStore(); + services.AddDataSource() + .AddUnitOfWork(); + services.AddEfCoreAggregateDataSource(o => { - services.AddSingleton(TestOutput); - services.AddEfCoreRepository(); - services.AddEfCoreDataStore(); - services.AddDataSource() - .AddUnitOfWork(); - services.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddPlatformProvider(); - }); - services.AddSavvyIO(o => - { - o.AddMediator().EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true); - }); - services.AddHandlerServicesDescriptor(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); + o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddPlatformProvider(); }); - var scope = test.Host.Services.CreateScope(); - var mediator = scope.ServiceProvider.GetRequiredService(); - var descriptor = scope.ServiceProvider.GetRequiredService(); - var deStore = scope.ServiceProvider.GetRequiredService>(); - var ieStore = scope.ServiceProvider.GetRequiredService>(); - - TestOutput.WriteLine(descriptor.ToString()); - - var createPlatformProvider = new CreatePlatformProvider("Whitelabel Inc.", "wl", "An example of a whitelabel platform provider."); - var clientProvidedCorrelationId = Guid.NewGuid().ToString("N"); - - await mediator.CommitAsync(createPlatformProvider - .SetCorrelationId(clientProvidedCorrelationId) - .SetCausationId(clientProvidedCorrelationId)); - - Assert.NotEqual(Guid.Empty, deStore.QueryFor().Single().Id); - Assert.Equal(deStore.QueryFor().Single().Id, ieStore.QueryFor().Single().Id); - } - - [Fact] - public async Task QueryTest() - { - await using var test = HostTestFactory.Create(services => + services.AddSavvyIO(o => { - services.AddSingleton(TestOutput); - services.AddSingleton, EfCoreRepository>(); - services.AddSingleton, EfCoreRepository>(); - services.AddEfCoreDataSource(o => o.ModelConstructor = builder => builder.AddAccount()); - services.AddEfCoreDataSource(o => o.ModelConstructor = builder => builder.AddPlatformProvider()); - services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); - services.AddHandlerServicesDescriptor(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); - services.AddSingleton, InMemoryTestStore>(); + o.AddMediator().EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true); }); - using var scope = test.Host.Services.CreateScope(); - var mediator = scope.ServiceProvider.GetRequiredService(); - var descriptor = scope.ServiceProvider.GetRequiredService(); - var deStore = scope.ServiceProvider.GetRequiredService>(); - var ieStore = scope.ServiceProvider.GetRequiredService>(); - - TestOutput.WriteLine(descriptor.ToString()); - - var result = await mediator.QueryAsync(new GetFakeAccount(10)); - - TestOutput.WriteLine(JsonConvert.SerializeObject(result)); + services.AddHandlerServicesDescriptor(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + }); + var scope = test.Host.Services.CreateScope(); + var mediator = scope.ServiceProvider.GetRequiredService(); + var descriptor = scope.ServiceProvider.GetRequiredService(); + var deStore = scope.ServiceProvider.GetRequiredService>(); + var ieStore = scope.ServiceProvider.GetRequiredService>(); + + TestOutput.WriteLine(descriptor.ToString()); + + var createPlatformProvider = new CreatePlatformProvider("Whitelabel Inc.", "wl", "An example of a whitelabel platform provider."); + var clientProvidedCorrelationId = Guid.NewGuid().ToString("N"); + + await mediator.CommitAsync(createPlatformProvider + .SetCorrelationId(clientProvidedCorrelationId) + .SetCausationId(clientProvidedCorrelationId)); + + Assert.NotEqual(Guid.Empty, deStore.QueryFor().Single().Id); + Assert.Equal(deStore.QueryFor().Single().Id, ieStore.QueryFor().Single().Id); + } - Assert.Equal(10, result.Id); - } + [Fact] + public async Task QueryTest() + { + await using var test = HostTestFactory.Create(services => + { + services.AddSingleton(TestOutput); + services.AddSingleton, EfCoreRepository>(); + services.AddSingleton, EfCoreRepository>(); + services.AddEfCoreDataSource(o => o.ModelConstructor = builder => builder.AddAccount()); + services.AddEfCoreDataSource(o => o.ModelConstructor = builder => builder.AddPlatformProvider()); + services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); + services.AddHandlerServicesDescriptor(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + services.AddSingleton, InMemoryTestStore>(); + }); + using var scope = test.Host.Services.CreateScope(); + var mediator = scope.ServiceProvider.GetRequiredService(); + var descriptor = scope.ServiceProvider.GetRequiredService(); + var deStore = scope.ServiceProvider.GetRequiredService>(); + var ieStore = scope.ServiceProvider.GetRequiredService>(); + + TestOutput.WriteLine(descriptor.ToString()); + + var result = await mediator.QueryAsync(new GetFakeAccount(10)); + + TestOutput.WriteLine(JsonConvert.SerializeObject(result)); + + Assert.Equal(10, result.Id); } } diff --git a/test/Savvyio.Extensions.Dispatchers.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Extensions.Dispatchers.Tests/SavvyioOptionsExtensionsTest.cs index b8e9c899..237d78bf 100644 --- a/test/Savvyio.Extensions.Dispatchers.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Extensions.Dispatchers.Tests/SavvyioOptionsExtensionsTest.cs @@ -6,73 +6,72 @@ using Savvyio.Queries; using Xunit; -namespace Savvyio.Extensions +namespace Savvyio.Extensions; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void UseAutomaticDispatcherDiscovery_ShouldDiscoverAcrossCurrentDomain() - { - var options = new SavvyioOptions(); + [Fact] + public void UseAutomaticDispatcherDiscovery_ShouldDiscoverAcrossCurrentDomain() + { + var options = new SavvyioOptions(); - Assert.Same(options, options.UseAutomaticDispatcherDiscovery(true)); + Assert.Same(options, options.UseAutomaticDispatcherDiscovery(true)); - Assert.Contains(typeof(ICommandDispatcher), options.DispatcherServiceTypes); - Assert.Contains(typeof(IDomainEventDispatcher), options.DispatcherServiceTypes); - Assert.Contains(typeof(IIntegrationEventDispatcher), options.DispatcherServiceTypes); - Assert.Contains(typeof(IQueryDispatcher), options.DispatcherServiceTypes); - Assert.Contains(typeof(CommandDispatcher), options.DispatcherImplementationTypes); - Assert.Contains(typeof(DomainEventDispatcher), options.DispatcherImplementationTypes); - Assert.Contains(typeof(IntegrationEventDispatcher), options.DispatcherImplementationTypes); - Assert.Contains(typeof(QueryDispatcher), options.DispatcherImplementationTypes); - } + Assert.Contains(typeof(ICommandDispatcher), options.DispatcherServiceTypes); + Assert.Contains(typeof(IDomainEventDispatcher), options.DispatcherServiceTypes); + Assert.Contains(typeof(IIntegrationEventDispatcher), options.DispatcherServiceTypes); + Assert.Contains(typeof(IQueryDispatcher), options.DispatcherServiceTypes); + Assert.Contains(typeof(CommandDispatcher), options.DispatcherImplementationTypes); + Assert.Contains(typeof(DomainEventDispatcher), options.DispatcherImplementationTypes); + Assert.Contains(typeof(IntegrationEventDispatcher), options.DispatcherImplementationTypes); + Assert.Contains(typeof(QueryDispatcher), options.DispatcherImplementationTypes); + } - [Fact] - public void UseAutomaticHandlerDiscovery_ShouldDiscoverAcrossCurrentDomainWithoutDuplicates() - { - var options = new SavvyioOptions(); + [Fact] + public void UseAutomaticHandlerDiscovery_ShouldDiscoverAcrossCurrentDomainWithoutDuplicates() + { + var options = new SavvyioOptions(); - Assert.Same(options, options.UseAutomaticHandlerDiscovery(true)); - options.UseAutomaticHandlerDiscovery(true); + Assert.Same(options, options.UseAutomaticHandlerDiscovery(true)); + options.UseAutomaticHandlerDiscovery(true); - Assert.Contains(typeof(ICommandHandler), options.HandlerServiceTypes); - Assert.Contains(typeof(IDomainEventHandler), options.HandlerServiceTypes); - Assert.Contains(typeof(IIntegrationEventHandler), options.HandlerServiceTypes); - Assert.Contains(typeof(IQueryHandler), options.HandlerServiceTypes); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorCommandHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorDomainEventHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorIntegrationEventHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorQueryHandler"); - Assert.Equal(options.HandlerImplementationTypes.Count, options.HandlerImplementationTypes.Distinct().Count()); - } + Assert.Contains(typeof(ICommandHandler), options.HandlerServiceTypes); + Assert.Contains(typeof(IDomainEventHandler), options.HandlerServiceTypes); + Assert.Contains(typeof(IIntegrationEventHandler), options.HandlerServiceTypes); + Assert.Contains(typeof(IQueryHandler), options.HandlerServiceTypes); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorCommandHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorDomainEventHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorIntegrationEventHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorQueryHandler"); + Assert.Equal(options.HandlerImplementationTypes.Count, options.HandlerImplementationTypes.Distinct().Count()); + } - [Fact] - public void UseAutomaticDispatcherDiscovery_ShouldUseCallingAssembly_WhenBruteAssemblyScanningIsFalse() - { - var options = new SavvyioOptions().UseAutomaticDispatcherDiscovery(); + [Fact] + public void UseAutomaticDispatcherDiscovery_ShouldUseCallingAssembly_WhenBruteAssemblyScanningIsFalse() + { + var options = new SavvyioOptions().UseAutomaticDispatcherDiscovery(); - Assert.Empty(options.DispatcherServiceTypes); - Assert.Empty(options.DispatcherImplementationTypes); - } + Assert.Empty(options.DispatcherServiceTypes); + Assert.Empty(options.DispatcherImplementationTypes); + } - [Fact] - public void UseAutomaticHandlerDiscovery_ShouldUseCallingAssembly_WhenBruteAssemblyScanningIsFalse() - { - var options = new SavvyioOptions().UseAutomaticHandlerDiscovery(); + [Fact] + public void UseAutomaticHandlerDiscovery_ShouldUseCallingAssembly_WhenBruteAssemblyScanningIsFalse() + { + var options = new SavvyioOptions().UseAutomaticHandlerDiscovery(); - Assert.Collection(options.HandlerServiceTypes.OrderBy(type => type.Name), - type => Assert.Equal(typeof(ICommandHandler), type), - type => Assert.Equal(typeof(IDomainEventHandler), type), - type => Assert.Equal(typeof(IIntegrationEventHandler), type), - type => Assert.Equal(typeof(IQueryHandler), type)); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorCommandHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorDomainEventHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorIntegrationEventHandler"); - Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorQueryHandler"); - } + Assert.Collection(options.HandlerServiceTypes.OrderBy(type => type.Name), + type => Assert.Equal(typeof(ICommandHandler), type), + type => Assert.Equal(typeof(IDomainEventHandler), type), + type => Assert.Equal(typeof(IIntegrationEventHandler), type), + type => Assert.Equal(typeof(IQueryHandler), type)); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorCommandHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorDomainEventHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorIntegrationEventHandler"); + Assert.Contains(options.HandlerImplementationTypes, type => type.Name == "TestMediatorQueryHandler"); } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/DomainEventDispatcherExtensionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/DomainEventDispatcherExtensionsTest.cs index 332105b7..e041af09 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/DomainEventDispatcherExtensionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/DomainEventDispatcherExtensionsTest.cs @@ -10,71 +10,70 @@ using Savvyio.Domain; using Xunit; -namespace Savvyio.Extensions.EFCore.Domain +namespace Savvyio.Extensions.EFCore.Domain; + +public class DomainEventDispatcherExtensionsTest : Test { - public class DomainEventDispatcherExtensionsTest : Test + public DomainEventDispatcherExtensionsTest(ITestOutputHelper output) : base(output) { - public DomainEventDispatcherExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DomainEventDispatcherExtensions_ShouldRaiseManySynchronously() + [Fact] + public void DomainEventDispatcherExtensions_ShouldRaiseManySynchronously() + { + var dispatcher = new TrackingDomainEventDispatcher(); + var source = new EfCoreAggregateDataSource(null, new EfCoreDataSourceOptions { - var dispatcher = new TrackingDomainEventDispatcher(); - var source = new EfCoreAggregateDataSource(null, new EfCoreDataSourceOptions - { - ContextConfigurator = b => b.UseInMemoryDatabase("dispatcher-" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var repository = new EfCoreRepository(source); - var id = Guid.NewGuid(); + ContextConfigurator = b => b.UseInMemoryDatabase("dispatcher-" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var repository = new EfCoreRepository(source); + var id = Guid.NewGuid(); - repository.Add(new Account(id, "Test", "test@unit.test")); - dispatcher.RaiseMany(source.DbContext); + repository.Add(new Account(id, "Test", "test@unit.test")); + dispatcher.RaiseMany(source.DbContext); - var tracked = source.DbContext.ChangeTracker.Entries>().Single().Entity; + var tracked = source.DbContext.ChangeTracker.Entries>().Single().Entity; - Assert.Single(dispatcher.Events); - Assert.IsType(dispatcher.Events.Single()); - Assert.Equal(id, ((AccountInitiated)dispatcher.Events.Single()).PlatformProviderId); - Assert.Empty(tracked.Events); - } + Assert.Single(dispatcher.Events); + Assert.IsType(dispatcher.Events.Single()); + Assert.Equal(id, ((AccountInitiated)dispatcher.Events.Single()).PlatformProviderId); + Assert.Empty(tracked.Events); + } - [Fact] - public async Task EfCoreAggregateDataSource_ShouldSaveChangesWithoutDispatcher() + [Fact] + public async Task EfCoreAggregateDataSource_ShouldSaveChangesWithoutDispatcher() + { + var id = Guid.NewGuid(); + var source = new EfCoreAggregateDataSource(null, new EfCoreDataSourceOptions { - var id = Guid.NewGuid(); - var source = new EfCoreAggregateDataSource(null, new EfCoreDataSourceOptions - { - ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-null-dispatcher-" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var repository = new EfCoreRepository(source); + ContextConfigurator = b => b.UseInMemoryDatabase("aggregate-null-dispatcher-" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var repository = new EfCoreRepository(source); - repository.Add(new Account(id, "Test", "test@unit.test")); - await source.SaveChangesAsync(); + repository.Add(new Account(id, "Test", "test@unit.test")); + await source.SaveChangesAsync(); - var sut = await repository.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + var sut = await repository.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - Assert.NotNull(sut); - Assert.Equal(id, sut.PlatformProviderId); - } + Assert.NotNull(sut); + Assert.Equal(id, sut.PlatformProviderId); + } - private sealed class TrackingDomainEventDispatcher : IDomainEventDispatcher - { - public List Events { get; } = new(); + private sealed class TrackingDomainEventDispatcher : IDomainEventDispatcher + { + public List Events { get; } = new(); - public void Raise(IDomainEvent request) - { - Events.Add(request); - } + public void Raise(IDomainEvent request) + { + Events.Add(request); + } - public Task RaiseAsync(IDomainEvent request, Action setup = null) - { - Events.Add(request); - return Task.CompletedTask; - } + public Task RaiseAsync(IDomainEvent request, Action setup = null) + { + Events.Add(request); + return Task.CompletedTask; } } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs index a0ff4754..ff6df775 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs @@ -1,22 +1,21 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +public class EfCoreDataSourceOptionsTest : Test { - public class EfCoreDataSourceOptionsTest : Test + public EfCoreDataSourceOptionsTest(ITestOutputHelper output) : base(output) { - public EfCoreDataSourceOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EfCoreDataSourceOptions_Ensure_Initialization_Defaults() - { - var sut = new EfCoreDataSourceOptions(); + [Fact] + public void EfCoreDataSourceOptions_Ensure_Initialization_Defaults() + { + var sut = new EfCoreDataSourceOptions(); - Assert.Null(sut.ContextConfigurator); - Assert.Null(sut.ConventionsConfigurator); - Assert.Null(sut.ModelConstructor); - } + Assert.Null(sut.ContextConfigurator); + Assert.Null(sut.ConventionsConfigurator); + Assert.Null(sut.ModelConstructor); } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs index b38f33f7..fdcd051b 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs @@ -13,62 +13,61 @@ using Savvyio.Extensions.EFCore.Domain; using Xunit; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +public class EfCoreDataSourceTest : Test { - public class EfCoreDataSourceTest : Test + public EfCoreDataSourceTest(ITestOutputHelper output) : base(output) { - public EfCoreDataSourceTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task EfCoreDataSource_ShouldFailWithInvalidOperationException_NoDatabaseProvider() - { - var sut = new EfCoreDataSource(new EfCoreDataSourceOptions()); - var ex = await Assert.ThrowsAsync(() => sut.SaveChangesAsync()); - Assert.StartsWith("No database provider has been configured for this DbContext.", ex.Message); - } + [Fact] + public async Task EfCoreDataSource_ShouldFailWithInvalidOperationException_NoDatabaseProvider() + { + var sut = new EfCoreDataSource(new EfCoreDataSourceOptions()); + var ex = await Assert.ThrowsAsync(() => sut.SaveChangesAsync()); + Assert.StartsWith("No database provider has been configured for this DbContext.", ex.Message); + } - [Fact] - public async Task EfCoreDataSource_ShouldFailWithObjectDisposedException() + [Fact] + public async Task EfCoreDataSource_ShouldFailWithObjectDisposedException() + { + var sut = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var sut = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy") - }); - sut.Dispose(); + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy") + }); + sut.Dispose(); - await Assert.ThrowsAsync(() => sut.SaveChangesAsync()); - Assert.True(sut.Disposed); - } + await Assert.ThrowsAsync(() => sut.SaveChangesAsync()); + Assert.True(sut.Disposed); + } - [Fact] - public async Task EfCoreDataSource_ShouldRaiseDomainEvents() + [Fact] + public async Task EfCoreDataSource_ShouldRaiseDomainEvents() + { + var sut1 = new ServiceCollection(); + sut1.AddServiceLocator(); + sut1.AddScoped(); + sut1.AddScoped(); + sut1.AddScoped, InMemoryTestStore>(); + sut1.AddConfiguredOptions(o => { - var sut1 = new ServiceCollection(); - sut1.AddServiceLocator(); - sut1.AddScoped(); - sut1.AddScoped(); - sut1.AddScoped, InMemoryTestStore>(); - sut1.AddConfiguredOptions(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = mb => mb.AddAccount(); - }); - var sut2 = sut1.BuildServiceProvider(); - var sut3 = new EfCoreAggregateDataSource(sut2.GetRequiredService(), sut2.GetRequiredService()); - var sut4 = new EfCoreRepository(sut3); + o.ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = mb => mb.AddAccount(); + }); + var sut2 = sut1.BuildServiceProvider(); + var sut3 = new EfCoreAggregateDataSource(sut2.GetRequiredService(), sut2.GetRequiredService()); + var sut4 = new EfCoreRepository(sut3); - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; - sut4.Add(new Account(id, name, email)); - await sut3.SaveChangesAsync(); // should raise domain events + sut4.Add(new Account(id, name, email)); + await sut3.SaveChangesAsync(); // should raise domain events - Assert.Equal(id, sut2.GetRequiredService>().QueryFor().Single().PlatformProviderId); - Assert.Equal(name, sut2.GetRequiredService>().QueryFor().Single().FullName); - Assert.Equal(email, sut2.GetRequiredService>().QueryFor().Single().EmailAddress); - } + Assert.Equal(id, sut2.GetRequiredService>().QueryFor().Single().PlatformProviderId); + Assert.Equal(name, sut2.GetRequiredService>().QueryFor().Single().FullName); + Assert.Equal(email, sut2.GetRequiredService>().QueryFor().Single().EmailAddress); } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs index 12e10486..c0c3b4ac 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs @@ -7,131 +7,130 @@ using Savvyio.Assets.Domain; using Xunit; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +public class EfCoreDataStoreTest : Test { - public class EfCoreDataStoreTest : Test + public EfCoreDataStoreTest(ITestOutputHelper output) : base(output) { - public EfCoreDataStoreTest(ITestOutputHelper output) : base(output) - { - } + } + + [Fact] + public async Task EfCoreDataStore_ShouldCreateObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; - [Fact] - public async Task EfCoreDataStore_ShouldCreateObject() + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + var sut2 = new EfCoreDataStore(sut1); + await sut2.CreateAsync(new Account(id, name, email)); - var sut2 = new EfCoreDataStore(sut1); - await sut2.CreateAsync(new Account(id, name, email)); + var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + Assert.Equal(id, sut3.PlatformProviderId); + Assert.Equal(name, sut3.FullName); + Assert.Equal(email, sut3.EmailAddress); + } - Assert.Equal(id, sut3.PlatformProviderId); - Assert.Equal(name, sut3.FullName); - Assert.Equal(email, sut3.EmailAddress); - } + [Fact] + public async Task EfCoreDataStore_ShouldRemoveObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; + var dto = new Account(id, name, email); - [Fact] - public async Task EfCoreDataStore_ShouldRemoveObject() + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; - var dto = new Account(id, name, email); + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + var sut2 = new EfCoreDataStore(sut1); + await sut2.CreateAsync(dto); - var sut2 = new EfCoreDataStore(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + await sut2.DeleteAsync(dto); - await sut2.DeleteAsync(dto); + var sut4 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut4 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + Assert.NotNull(sut3); + Assert.Null(sut4); + } - Assert.NotNull(sut3); - Assert.Null(sut4); - } + [Fact] + public async Task EfCoreDataStore_ShouldUpdateObject() + { + var id = Guid.NewGuid(); + var name = "Test"; + var newName = "Unit Test"; + var email = "test@unit.test"; + var dto = new Account(id, name, email); - [Fact] - public async Task EfCoreDataStore_ShouldUpdateObject() + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var newName = "Unit Test"; - var email = "test@unit.test"; - var dto = new Account(id, name, email); + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + var sut2 = new EfCoreDataStore(sut1); + await sut2.CreateAsync(dto); - var sut2 = new EfCoreDataStore(sut1); - await sut2.CreateAsync(dto); + var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + sut3.ChangeFullName(newName); - sut3.ChangeFullName(newName); + await sut2.UpdateAsync(sut3); - await sut2.UpdateAsync(sut3); + var sut4 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut4 = await sut2.FindAllAsync(o => o.Predicate = a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - - Assert.NotEqual(name, sut3.FullName); - Assert.Equal(newName, sut4.FullName); - } + Assert.NotEqual(name, sut3.FullName); + Assert.Equal(newName, sut4.FullName); + } - [Fact] - public async Task EfCoreDataStore_ShouldGetObjectById() + [Fact] + public async Task EfCoreDataStore_ShouldGetObjectById() + { + var id = Guid.NewGuid(); + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var sut2 = new EfCoreDataStore(sut1); - var dto = new Account(id, "Test", "test@unit.test"); - - await sut2.CreateAsync(dto); - - var sut3 = await sut2.GetByIdAsync(dto.Id); - var sut4 = await sut2.GetByIdAsync(long.MaxValue); - - Assert.Equal(dto.Id, sut3.Id); - Assert.Null(sut4); - } - - [Fact] - public async Task EfCoreDataStore_ShouldReturnAllObjectsWhenPredicateIsMissing() + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var sut2 = new EfCoreDataStore(sut1); + var dto = new Account(id, "Test", "test@unit.test"); + + await sut2.CreateAsync(dto); + + var sut3 = await sut2.GetByIdAsync(dto.Id); + var sut4 = await sut2.GetByIdAsync(long.MaxValue); + + Assert.Equal(dto.Id, sut3.Id); + Assert.Null(sut4); + } + + [Fact] + public async Task EfCoreDataStore_ShouldReturnAllObjectsWhenPredicateIsMissing() + { + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var sut2 = new EfCoreDataStore(sut1); + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var sut2 = new EfCoreDataStore(sut1); - await sut2.CreateAsync(new Account(Guid.NewGuid(), "Test1", "test1@unit.test")); - await sut2.CreateAsync(new Account(Guid.NewGuid(), "Test2", "test2@unit.test")); + await sut2.CreateAsync(new Account(Guid.NewGuid(), "Test1", "test1@unit.test")); + await sut2.CreateAsync(new Account(Guid.NewGuid(), "Test2", "test2@unit.test")); - var sut3 = await sut2.FindAllAsync(); + var sut3 = await sut2.FindAllAsync(); - Assert.Equal(2, sut3.Count()); - } + Assert.Equal(2, sut3.Count()); } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs index 902a595e..b9b81088 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs @@ -9,171 +9,170 @@ using Savvyio.Extensions.DependencyInjection.EFCore; using Xunit; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +public class EfCoreRepositoryTest : Test { - public class EfCoreRepositoryTest : Test + public EfCoreRepositoryTest(ITestOutputHelper output) : base(output) { - public EfCoreRepositoryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EfCoreRepository_ShouldFailWithInvalidModel() + [Fact] + public void EfCoreRepository_ShouldFailWithInvalidModel() + { + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy") - }); - var sut2 = new EfCoreRepository(sut1); - var ex = Assert.Throws(() => sut2.Add(new Account(1))); - Assert.StartsWith("Cannot create a DbSet for 'Account' because this type is not included in the model for the context.", ex.Message); - } - - [Fact] - public async Task EfCoreRepository_ShouldAddEntity() + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy") + }); + var sut2 = new EfCoreRepository(sut1); + var ex = Assert.Throws(() => sut2.Add(new Account(1))); + Assert.StartsWith("Cannot create a DbSet for 'Account' because this type is not included in the model for the context.", ex.Message); + } + + [Fact] + public async Task EfCoreRepository_ShouldAddEntity() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; + + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + var sut2 = new EfCoreRepository(sut1); + sut2.Add(new Account(id, name, email)); + await sut1.SaveChangesAsync(); - var sut2 = new EfCoreRepository(sut1); - sut2.Add(new Account(id, name, email)); - await sut1.SaveChangesAsync(); + var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + Assert.Equal(id, sut3.PlatformProviderId); + Assert.Equal(name, sut3.FullName); + Assert.Equal(email, sut3.EmailAddress); + } - Assert.Equal(id, sut3.PlatformProviderId); - Assert.Equal(name, sut3.FullName); - Assert.Equal(email, sut3.EmailAddress); - } + [Fact] + public async Task EfCoreRepository_ShouldRemoveEntity() + { + var id = Guid.NewGuid(); + var name = "Test"; + var email = "test@unit.test"; + var entity = new Account(id, name, email); - [Fact] - public async Task EfCoreRepository_ShouldRemoveEntity() + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var id = Guid.NewGuid(); - var name = "Test"; - var email = "test@unit.test"; - var entity = new Account(id, name, email); + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); + + var sut2 = new EfCoreRepository(sut1); + sut2.Add(entity); + await sut1.SaveChangesAsync(); + + var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + sut2.Remove(entity); + await sut1.SaveChangesAsync(); - var sut2 = new EfCoreRepository(sut1); - sut2.Add(entity); - await sut1.SaveChangesAsync(); + var sut4 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + Assert.NotNull(sut3); + Assert.Null(sut4); + } - sut2.Remove(entity); - await sut1.SaveChangesAsync(); + [Fact] + public async Task EfCoreRepository_ShouldUpdateEntity() + { + var id = Guid.NewGuid(); + var name = "Test"; + var newName = "Unit Test"; + var email = "test@unit.test"; + var entity = new Account(id, name, email); - var sut4 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() + { + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), + ModelConstructor = mb => mb.AddAccount() + }); - Assert.NotNull(sut3); - Assert.Null(sut4); - } + var events = new List(); - [Fact] - public async Task EfCoreRepository_ShouldUpdateEntity() + sut1.DbContext.ChangeTracker.StateChanged += (sender, args) => { - var id = Guid.NewGuid(); - var name = "Test"; - var newName = "Unit Test"; - var email = "test@unit.test"; - var entity = new Account(id, name, email); + var trace = $"{sender}: {args.OldState} --> {args.NewState}"; + events.Add(trace); + TestOutput.WriteLine(trace); + }; - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy"), - ModelConstructor = mb => mb.AddAccount() - }); + var sut2 = new EfCoreRepository(sut1); - var events = new List(); + sut2.Add(entity); - sut1.DbContext.ChangeTracker.StateChanged += (sender, args) => - { - var trace = $"{sender}: {args.OldState} --> {args.NewState}"; - events.Add(trace); - TestOutput.WriteLine(trace); - }; + await sut1.SaveChangesAsync(); - var sut2 = new EfCoreRepository(sut1); + var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - sut2.Add(entity); + Assert.Equal(entity, sut3); - await sut1.SaveChangesAsync(); + sut3.ChangeFullName(newName); - var sut3 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + await sut1.SaveChangesAsync(); // modified - Assert.Equal(entity, sut3); + var sut4 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); - sut3.ChangeFullName(newName); + Assert.NotEqual(name, sut3.FullName); + Assert.Equal(newName, sut4.FullName); + Assert.Collection(events, + s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Added --> Unchanged", s), + s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Unchanged --> Modified", s), + s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Modified --> Unchanged", s)); + } + + [Fact] + public async Task EfCoreRepository_ShouldGetEntityById() + { + var entity = new Account(Guid.NewGuid(), "Test", "test@unit.test"); + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() + { + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var sut2 = new EfCoreRepository(sut1); - await sut1.SaveChangesAsync(); // modified + sut2.Add(entity); + await sut1.SaveChangesAsync(); - var sut4 = await sut2.FindAllAsync(a => a.PlatformProviderId == id).SingleOrDefaultAsync(); + var sut3 = await sut2.GetByIdAsync(entity.Id); + var sut4 = await sut2.GetByIdAsync(long.MaxValue); - Assert.NotEqual(name, sut3.FullName); - Assert.Equal(newName, sut4.FullName); - Assert.Collection(events, - s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Added --> Unchanged", s), - s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Unchanged --> Modified", s), - s => Assert.Equal("Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker: Modified --> Unchanged", s)); - } + Assert.Equal(entity.Id, sut3.Id); + Assert.Null(sut4); + } - [Fact] - public async Task EfCoreRepository_ShouldGetEntityById() + [Fact] + public async Task EfCoreRepository_ShouldAddAndRemoveRangeOfEntities() + { + var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() { - var entity = new Account(Guid.NewGuid(), "Test", "test@unit.test"); - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var sut2 = new EfCoreRepository(sut1); - - sut2.Add(entity); - await sut1.SaveChangesAsync(); - - var sut3 = await sut2.GetByIdAsync(entity.Id); - var sut4 = await sut2.GetByIdAsync(long.MaxValue); - - Assert.Equal(entity.Id, sut3.Id); - Assert.Null(sut4); - } - - [Fact] - public async Task EfCoreRepository_ShouldAddAndRemoveRangeOfEntities() + ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), + ModelConstructor = mb => mb.AddAccount() + }); + var sut2 = new EfCoreRepository(sut1); + var entities = new[] { - var sut1 = new EfCoreDataSource(new EfCoreDataSourceOptions() - { - ContextConfigurator = b => b.UseInMemoryDatabase("Dummy_" + Guid.NewGuid()), - ModelConstructor = mb => mb.AddAccount() - }); - var sut2 = new EfCoreRepository(sut1); - var entities = new[] - { - new Account(Guid.NewGuid(), "Test1", "test1@unit.test"), - new Account(Guid.NewGuid(), "Test2", "test2@unit.test") - }; - - sut2.AddRange(entities); - await sut1.SaveChangesAsync(); - Assert.Equal(2, (await sut2.FindAllAsync()).Count()); - - sut2.RemoveRange(entities); - await sut1.SaveChangesAsync(); - - Assert.Empty(await sut2.FindAllAsync()); - } + new Account(Guid.NewGuid(), "Test1", "test1@unit.test"), + new Account(Guid.NewGuid(), "Test2", "test2@unit.test") + }; + + sut2.AddRange(entities); + await sut1.SaveChangesAsync(); + Assert.Equal(2, (await sut2.FindAllAsync()).Count()); + + sut2.RemoveRange(entities); + await sut1.SaveChangesAsync(); + + Assert.Empty(await sut2.FindAllAsync()); } } diff --git a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs index 20b3eb08..9f0d5942 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs @@ -13,154 +13,153 @@ using Savvyio.Extensions.DependencyInjection.EFCore; using Xunit; -namespace Savvyio.Extensions.EFCore +namespace Savvyio.Extensions.EFCore; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddEfCoreDataStore_ShouldAddDefaultImplementationWithDefaultOptions() + { + var sut1 = new ServiceCollection(); + sut1.AddDataSource() + .AddUnitOfWork(); + sut1.AddConfiguredOptions(_ => { }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + Assert.IsType(sut2.GetRequiredService()); + Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); + Assert.Null(sut2.GetRequiredService>().Value.ContextConfigurator); + Assert.Null(sut2.GetRequiredService>().Value.ModelConstructor); + Assert.Null(sut2.GetRequiredService>().Value.ConventionsConfigurator); + } + + [Fact] + public void AddEfCoreDataStore_ShouldAddDefaultImplementation() { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - } + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount(); + o.ConventionsConfigurator = _ => { }; + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType(sut2.GetRequiredService()); + Assert.NotNull(sut2.GetRequiredService>().Value.ContextConfigurator); + Assert.NotNull(sut2.GetRequiredService>().Value.ModelConstructor); + Assert.NotNull(sut2.GetRequiredService>().Value.ConventionsConfigurator); + } - [Fact] - public void AddEfCoreDataStore_ShouldAddDefaultImplementationWithDefaultOptions() + [Fact] + public void AddEfCoreDataStore_ShouldAddDefaultImplementationWithMarker() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddDataSource() - .AddUnitOfWork(); - sut1.AddConfiguredOptions(_ => { }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType(sut2.GetRequiredService()); - Assert.IsType(sut2.GetRequiredService()); - Assert.Same(sut2.GetRequiredService(), sut2.GetRequiredService()); - Assert.Null(sut2.GetRequiredService>().Value.ContextConfigurator); - Assert.Null(sut2.GetRequiredService>().Value.ModelConstructor); - Assert.Null(sut2.GetRequiredService>().Value.ConventionsConfigurator); - } - - [Fact] - public void AddEfCoreDataStore_ShouldAddDefaultImplementation() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount(); + }); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.NotNull(sut2.GetRequiredService>>().Value.ContextConfigurator); + Assert.NotNull(sut2.GetRequiredService>>().Value.ModelConstructor); + Assert.Null(sut2.GetRequiredService>>().Value.ConventionsConfigurator); + } + + [Fact] + public void AddEfCoreRepository_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount(); - o.ConventionsConfigurator = _ => { }; - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType(sut2.GetRequiredService()); - Assert.NotNull(sut2.GetRequiredService>().Value.ContextConfigurator); - Assert.NotNull(sut2.GetRequiredService>().Value.ModelConstructor); - Assert.NotNull(sut2.GetRequiredService>().Value.ConventionsConfigurator); - } - - [Fact] - public void AddEfCoreDataStore_ShouldAddDefaultImplementationWithMarker() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + } + + [Fact] + public void AddEfCoreRepository_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount(); - }); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.NotNull(sut2.GetRequiredService>>().Value.ContextConfigurator); - Assert.NotNull(sut2.GetRequiredService>>().Value.ModelConstructor); - Assert.Null(sut2.GetRequiredService>>().Value.ConventionsConfigurator); - } - - [Fact] - public void AddEfCoreRepository_ShouldAddManyImplementations() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - } - - [Fact] - public void AddEfCoreRepository_ShouldAddManyImplementationsWithMarkers() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("AnotherDummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreRepository(); + sut1.AddEfCoreRepository(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.IsType>(sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); + } + + [Fact] + public void AddEfCoreDataStore_ShouldAddManyImplementations() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("AnotherDummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreRepository(); - sut1.AddEfCoreRepository(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.IsType>(sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - Assert.NotSame(sut2.GetRequiredService>(), sut2.GetRequiredService>()); - } - - [Fact] - public void AddEfCoreDataStore_ShouldAddManyImplementations() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService>>()); + Assert.IsType>(sut2.GetRequiredService>>()); + } + + [Fact] + public void AddEfCoreDataStore_ShouldAddManyImplementationsWithMarkers() + { + var sut1 = new ServiceCollection(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService>>()); - Assert.IsType>(sut2.GetRequiredService>>()); - } - - [Fact] - public void AddEfCoreDataStore_ShouldAddManyImplementationsWithMarkers() + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataSource(o => { - var sut1 = new ServiceCollection(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataSource(o => - { - o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); - o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); - }); - sut1.AddEfCoreDataStore(); - sut1.AddEfCoreDataStore(); - var sut2 = sut1.BuildServiceProvider(); - - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); - } + o.ContextConfigurator = builder => builder.UseInMemoryDatabase("Dummy"); + o.ModelConstructor = builder => builder.AddAccount().AddPlatformProvider(); + }); + sut1.AddEfCoreDataStore(); + sut1.AddEfCoreDataStore(); + var sut2 = sut1.BuildServiceProvider(); + + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, DbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.IsType>(sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); + Assert.NotSame(sut2.GetRequiredService, DbMarker>>(), sut2.GetRequiredService, AnotherDbMarker>>()); } } diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs index 48481a77..b7eb3395 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,20 +1,19 @@ using Savvyio.Commands; -namespace Savvyio.Extensions.NATS.Assets +namespace Savvyio.Extensions.NATS.Assets; + +internal record CreateMemberCommand : Command { - internal record CreateMemberCommand : Command + public CreateMemberCommand(string name, byte age, string emailAddress) { - public CreateMemberCommand(string name, byte age, string emailAddress) - { - Name = name; - Age = age; - EmailAddress = emailAddress; - } + Name = name; + Age = age; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public byte Age { get; } + public byte Age { get; } - public string EmailAddress { 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 index a8bc248f..c0a0ae0a 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs @@ -1,17 +1,16 @@ using Savvyio.EventDriven; -namespace Savvyio.Extensions.NATS.Assets +namespace Savvyio.Extensions.NATS.Assets; + +public record MemberCreated : IntegrationEvent { - public record MemberCreated : IntegrationEvent + public MemberCreated(string name, string emailAddress) { - public MemberCreated(string name, string emailAddress) - { - Name = name; - EmailAddress = emailAddress; - } + Name = name; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public string EmailAddress { 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 index f8bd02e0..c3b0329d 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs @@ -20,182 +20,181 @@ using System.Threading.Tasks; using Xunit; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +public class NatsCommandQueueJsonSerializerContextTest : Test { - public class NatsCommandQueueJsonSerializerContextTest : Test + public NatsCommandQueueJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public NatsCommandQueueJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.AutoAcknowledge = true; - o.Subject = Guid.NewGuid().ToString(); - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.AutoAcknowledge = true; + o.Subject = Guid.NewGuid().ToString(); + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.AutoAcknowledge = true; - o.Subject = Guid.NewGuid().ToString(); - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.AutoAcknowledge = true; + o.Subject = Guid.NewGuid().ToString(); + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) as ISignedMessage; - received.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) 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); - } + 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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - o.Subject = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); + o.Subject = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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 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 receivedMessages = Channel.CreateUnbounded>(); - var count1 = 0; - Task.Run(async () => + var count1 = 0; + Task.Run(async () => + { + while (count1 < messages.Count) { - while (count1 < messages.Count) + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - Interlocked.Increment(ref count1); - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - await msg.AcknowledgeAsync().ConfigureAwait(false); - } + Interlocked.Increment(ref count1); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); } - }); + } + }); - var count2 = 0; - Task.Run(async () => + var count2 = 0; + Task.Run(async () => + { + while (count2 < messages.Count) { - while (count2 < messages.Count) + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - Interlocked.Increment(ref count2); - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - await msg.AcknowledgeAsync().ConfigureAwait(false); - } + Interlocked.Increment(ref count2); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); } - }); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(messages).ConfigureAwait(false); + await queue.SendAsync(messages).ConfigureAwait(false); - var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); + var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); - Assert.Equal(messages.Count, count1 + count2); + Assert.Equal(messages.Count, count1 + count2); - TestOutput.WriteLine(count1.ToString()); - TestOutput.WriteLine(count2.ToString()); + TestOutput.WriteLine(count1.ToString()); + TestOutput.WriteLine(count2.ToString()); - TestOutput.WriteLine(received.Count.ToString()); - TestOutput.WriteLines(received.Take(10)); + 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)); - } + 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 index ac591682..dbba0585 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -20,182 +20,181 @@ using System.Threading.Tasks; using Xunit; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +public class NatsCommandQueueNewtonsoftJsonSerializerContextTest : Test { - public class NatsCommandQueueNewtonsoftJsonSerializerContextTest : Test + public NatsCommandQueueNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public NatsCommandQueueNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.AutoAcknowledge = true; - o.Subject = Guid.NewGuid().ToString(); - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.AutoAcknowledge = true; + o.Subject = Guid.NewGuid().ToString(); + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.AutoAcknowledge = true; - o.Subject = Guid.NewGuid().ToString(); - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.AutoAcknowledge = true; + o.Subject = Guid.NewGuid().ToString(); + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) 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); - } + 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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.StreamName = Guid.NewGuid().ToString(); - o.ConsumerName = Guid.NewGuid().ToString(); - o.Subject = Guid.NewGuid().ToString(); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.StreamName = Guid.NewGuid().ToString(); + o.ConsumerName = Guid.NewGuid().ToString(); + o.Subject = Guid.NewGuid().ToString(); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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 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 receivedMessages = Channel.CreateUnbounded>(); - var count1 = 0; - Task.Run(async () => + var count1 = 0; + Task.Run(async () => + { + while (count1 < messages.Count) { - while (count1 < messages.Count) + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - Interlocked.Increment(ref count1); - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - await msg.AcknowledgeAsync().ConfigureAwait(false); - } + Interlocked.Increment(ref count1); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); } - }); + } + }); - var count2 = 0; - Task.Run(async () => + var count2 = 0; + Task.Run(async () => + { + while (count2 < messages.Count) { - while (count2 < messages.Count) + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - Interlocked.Increment(ref count2); - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - await msg.AcknowledgeAsync().ConfigureAwait(false); - } + Interlocked.Increment(ref count2); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + await msg.AcknowledgeAsync().ConfigureAwait(false); } - }); + } + }); - await queue.WaitUntilConsumerReadyAsync(); + await queue.WaitUntilConsumerReadyAsync(); - await queue.SendAsync(messages).ConfigureAwait(false); + await queue.SendAsync(messages).ConfigureAwait(false); - var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); + var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); - Assert.Equal(messages.Count, count1 + count2); + Assert.Equal(messages.Count, count1 + count2); - TestOutput.WriteLine(count1.ToString()); - TestOutput.WriteLine(count2.ToString()); + TestOutput.WriteLine(count1.ToString()); + TestOutput.WriteLine(count2.ToString()); - TestOutput.WriteLine(received.Count.ToString()); - TestOutput.WriteLines(received.Take(10)); + 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)); - } + 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/ObservableNatsCommandQueue.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/ObservableNatsCommandQueue.cs index 7170af63..67a4c2ce 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/ObservableNatsCommandQueue.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/ObservableNatsCommandQueue.cs @@ -5,26 +5,25 @@ using NATS.Client.JetStream.Models; using Savvyio.Messaging; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +internal sealed class ObservableNatsCommandQueue : NatsCommandQueue { - internal sealed class ObservableNatsCommandQueue : NatsCommandQueue - { - private readonly TaskCompletionSource _consumerReady = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _consumerReady = new(TaskCreationOptions.RunContinuationsAsynchronously); - public ObservableNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options) : base(marshaller, options) - { - } + public ObservableNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options) : base(marshaller, options) + { + } - internal Task WaitUntilConsumerReadyAsync() - { - return _consumerReady.Task.WaitAsync(TimeSpan.FromSeconds(10)); - } + internal Task WaitUntilConsumerReadyAsync() + { + return _consumerReady.Task.WaitAsync(TimeSpan.FromSeconds(10)); + } - protected override async Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) - { - var consumer = await base.CreateConsumerAsync(streamConfig, consumerConfig, cancellationToken).ConfigureAwait(false); - _consumerReady.TrySetResult(); - return consumer; - } + protected override async Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) + { + var consumer = await base.CreateConsumerAsync(streamConfig, consumerConfig, cancellationToken).ConfigureAwait(false); + _consumerReady.TrySetResult(); + return consumer; } } diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs index 6db420a2..47924aa3 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs @@ -21,280 +21,279 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +public class NatsEventBusJsonSerializerContextTest : Test { - public class NatsEventBusJsonSerializerContextTest : Test + public NatsEventBusJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public NatsEventBusJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ICloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedCloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + 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 bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); - var handlerInvocations2 = 0; - Task.Run(async () => + 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) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations2++; - await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); - - await bus.WaitUntilSubscribedAsync(2); + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - return bus.PublishAsync(message, o => o.CancellationToken = token); + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); }).ConfigureAwait(false); + }); - var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); - var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); - await Task.WhenAll(received1Task, received2Task); - var received1 = await received1Task; - var received2 = await received2Task; - - 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)); - } + await bus.WaitUntilSubscribedAsync(2); + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); + var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); + await Task.WhenAll(received1Task, received2Task); + var received1 = await received1Task; + var received2 = await received2Task; + + 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 index 84a41c65..a72ce811 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs @@ -21,280 +21,279 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +public class NatsEventBusNewtonsoftJsonSerializerContextTest : Test { - public class NatsEventBusNewtonsoftJsonSerializerContextTest : Test + public NatsEventBusNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public NatsEventBusNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ICloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + o.Subject = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await bus.WaitUntilSubscribedAsync(); + await bus.WaitUntilSubscribedAsync(); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedCloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.NatsUrl = NatsTestEnvironment.Url; - o.Subject = Generate.RandomString(10); - }); + o.NatsUrl = NatsTestEnvironment.Url; + 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 bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); - var handlerInvocations2 = 0; - Task.Run(async () => + 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) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations2++; - await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); - - await bus.WaitUntilSubscribedAsync(2); + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - return bus.PublishAsync(message, o => o.CancellationToken = token); + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); }).ConfigureAwait(false); + }); - var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); - var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); - await Task.WhenAll(received1Task, received2Task); - var received1 = await received1Task; - var received2 = await received2Task; - - 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)); - } + await bus.WaitUntilSubscribedAsync(2); + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); + var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); + await Task.WhenAll(received1Task, received2Task); + var received1 = await received1Task; + var received2 = await received2Task; + + 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/EventDriven/ObservableNatsEventBus.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/ObservableNatsEventBus.cs index 2c63894f..dfb29ae0 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/ObservableNatsEventBus.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/ObservableNatsEventBus.cs @@ -6,79 +6,78 @@ using NATS.Client.Core; using Savvyio.Messaging; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +internal sealed class ObservableNatsEventBus : NatsEventBus { - internal sealed class ObservableNatsEventBus : NatsEventBus - { - private readonly object _subscribedSyncRoot = new(); - private TaskCompletionSource _subscribed = new(TaskCreationOptions.RunContinuationsAsynchronously); - private int _subscriptionCount; + private readonly object _subscribedSyncRoot = new(); + private TaskCompletionSource _subscribed = new(TaskCreationOptions.RunContinuationsAsynchronously); + private int _subscriptionCount; - public ObservableNatsEventBus(IMarshaller marshaller, NatsEventBusOptions options) : base(marshaller, options) - { - } + public ObservableNatsEventBus(IMarshaller marshaller, NatsEventBusOptions options) : base(marshaller, options) + { + } - internal Task WaitUntilSubscribedAsync(int expectedSubscriptionCount = 1) - { - if (expectedSubscriptionCount < 1) { throw new ArgumentOutOfRangeException(nameof(expectedSubscriptionCount)); } - return WaitUntilSubscribedCoreAsync(expectedSubscriptionCount).WaitAsync(TimeSpan.FromSeconds(10)); - } + internal Task WaitUntilSubscribedAsync(int expectedSubscriptionCount = 1) + { + if (expectedSubscriptionCount < 1) { throw new ArgumentOutOfRangeException(nameof(expectedSubscriptionCount)); } + return WaitUntilSubscribedCoreAsync(expectedSubscriptionCount).WaitAsync(TimeSpan.FromSeconds(10)); + } - private async Task WaitUntilSubscribedCoreAsync(int expectedSubscriptionCount) + private async Task WaitUntilSubscribedCoreAsync(int expectedSubscriptionCount) + { + while (Volatile.Read(ref _subscriptionCount) < expectedSubscriptionCount) { - while (Volatile.Read(ref _subscriptionCount) < expectedSubscriptionCount) + Task subscribedTask; + lock (_subscribedSyncRoot) { - Task subscribedTask; - lock (_subscribedSyncRoot) + if (_subscriptionCount >= expectedSubscriptionCount) { - if (_subscriptionCount >= expectedSubscriptionCount) - { - return; - } - - subscribedTask = _subscribed.Task; + return; } - await subscribedTask.ConfigureAwait(false); + subscribedTask = _subscribed.Task; } + + await subscribedTask.ConfigureAwait(false); } + } - private void SignalSubscribed() + private void SignalSubscribed() + { + TaskCompletionSource subscribed; + lock (_subscribedSyncRoot) { - TaskCompletionSource subscribed; - lock (_subscribedSyncRoot) - { - _subscriptionCount++; - subscribed = _subscribed; - _subscribed = new(TaskCreationOptions.RunContinuationsAsynchronously); - } - - subscribed.TrySetResult(); + _subscriptionCount++; + subscribed = _subscribed; + _subscribed = new(TaskCreationOptions.RunContinuationsAsynchronously); } - protected override async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [EnumeratorCancellation] CancellationToken cancellationToken) + subscribed.TrySetResult(); + } + + protected override async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [EnumeratorCancellation] CancellationToken cancellationToken) + { + var subscriptionRegistered = 0; + var observedOptions = new NatsSubOpts { - var subscriptionRegistered = 0; - var observedOptions = new NatsSubOpts + Events = new NatsSubEvents { - Events = new NatsSubEvents + OnSubscribed = _ => { - OnSubscribed = _ => + if (Interlocked.Exchange(ref subscriptionRegistered, 1) == 0) { - if (Interlocked.Exchange(ref subscriptionRegistered, 1) == 0) - { - SignalSubscribed(); - } - - return default; + SignalSubscribed(); } - } - }; - await foreach (var message in base.SubscribeMessagesAsync(subject, observedOptions, cancellationToken)) - { - yield return message; + return default; + } } + }; + + await foreach (var message in base.SubscribeMessagesAsync(subject, observedOptions, cancellationToken)) + { + yield return message; } } } diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/MessageTestHelper.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/MessageTestHelper.cs index 4c32efeb..82994ff2 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/MessageTestHelper.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/MessageTestHelper.cs @@ -4,19 +4,18 @@ using System.Threading.Channels; using System.Threading.Tasks; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +internal static class MessageTestHelper { - internal static class MessageTestHelper + internal static async Task> ReadAsync(ChannelReader reader, int count) { - internal static async Task> ReadAsync(ChannelReader reader, int count) + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + var messages = new List(count); + while (messages.Count < count) { - using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - var messages = new List(count); - while (messages.Count < count) - { - messages.Add(await reader.ReadAsync(timeout.Token)); - } - return messages; + messages.Add(await reader.ReadAsync(timeout.Token)); } + return messages; } } diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/NatsTestEnvironment.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/NatsTestEnvironment.cs index 21a49848..45f6a7da 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/NatsTestEnvironment.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/NatsTestEnvironment.cs @@ -1,9 +1,8 @@ using System; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +internal static class NatsTestEnvironment { - internal static class NatsTestEnvironment - { - internal static Uri Url { get; } = new(Environment.GetEnvironmentVariable("SAVVYIO_NATS_URL") ?? "nats://127.0.0.1:4222"); - } + internal static Uri Url { get; } = new(Environment.GetEnvironmentVariable("SAVVYIO_NATS_URL") ?? "nats://127.0.0.1:4222"); } diff --git a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs index 9546eb88..6dcfd15e 100644 --- a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs @@ -2,175 +2,174 @@ using System; using Xunit; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +public class NatsCommandQueueOptionsTest : Test { - public class NatsCommandQueueOptionsTest : Test + public NatsCommandQueueOptionsTest(ITestOutputHelper output) : base(output) { - 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) + [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 { - var options = new NatsCommandQueueOptions - { - MaxMessages = input - }; + MaxMessages = input + }; - Assert.Equal(expected, options.MaxMessages); - } + Assert.Equal(expected, options.MaxMessages); + } - [Fact] - public void Expires_Sets_Heartbeat_When_Expires_AtLeast_30Seconds() - { - var options = new NatsCommandQueueOptions(); + [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(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(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); - } + 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() + [Fact] + public void Heartbeat_Can_Be_Set_Manually() + { + var options = new NatsCommandQueueOptions { - var options = new NatsCommandQueueOptions - { - Heartbeat = TimeSpan.FromSeconds(10) - }; + Heartbeat = TimeSpan.FromSeconds(10) + }; - Assert.Equal(TimeSpan.FromSeconds(10), options.Heartbeat); - } + Assert.Equal(TimeSpan.FromSeconds(10), options.Heartbeat); + } - [Fact] - public void Heartbeat_Can_Be_Overridden_After_Expires() - { - var options = new NatsCommandQueueOptions(); + [Fact] + public void Heartbeat_Can_Be_Overridden_After_Expires() + { + var options = new NatsCommandQueueOptions(); - options.Expires = TimeSpan.FromSeconds(60); - Assert.Equal(TimeSpan.FromSeconds(5), options.Heartbeat); + options.Expires = TimeSpan.FromSeconds(60); + Assert.Equal(TimeSpan.FromSeconds(5), options.Heartbeat); - options.Heartbeat = TimeSpan.FromSeconds(15); - Assert.Equal(TimeSpan.FromSeconds(15), options.Heartbeat); - } + options.Heartbeat = TimeSpan.FromSeconds(15); + Assert.Equal(TimeSpan.FromSeconds(15), options.Heartbeat); + } - [Fact] - public void StreamName_And_ConsumerName_Can_Be_Set_And_Gotten() + [Fact] + public void StreamName_And_ConsumerName_Can_Be_Set_And_Gotten() + { + var options = new NatsCommandQueueOptions { - 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() + 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 { - var options = new NatsCommandQueueOptions - { - AutoAcknowledge = true - }; + AutoAcknowledge = true + }; - Assert.True(options.AutoAcknowledge); - } + Assert.True(options.AutoAcknowledge); + } - [Fact] - public void ValidateOptions_Throws_If_StreamName_Is_Null_Or_Whitespace() + [Fact] + public void ValidateOptions_Throws_If_StreamName_Is_Null_Or_Whitespace() + { + var options = new NatsCommandQueueOptions { - var options = new NatsCommandQueueOptions - { - StreamName = null, - ConsumerName = "consumer" - }; + StreamName = null, + ConsumerName = "consumer" + }; - Assert.Throws(() => options.ValidateOptions()); + Assert.Throws(() => options.ValidateOptions()); - options.StreamName = ""; - Assert.Throws(() => options.ValidateOptions()); + options.StreamName = ""; + 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() + [Fact] + public void ValidateOptions_Throws_If_ConsumerName_Is_Null_Or_Whitespace() + { + var options = new NatsCommandQueueOptions { - var options = new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = null - }; + StreamName = "stream", + ConsumerName = null + }; - Assert.Throws(() => options.ValidateOptions()); + Assert.Throws(() => options.ValidateOptions()); - options.ConsumerName = ""; - Assert.Throws(() => options.ValidateOptions()); + options.ConsumerName = ""; + 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() + [Fact] + public void ValidateOptions_Throws_If_Base_Options_Invalid() + { + var options = new NatsCommandQueueOptions { - 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() + 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 { - 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); - } + 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/Commands/NatsCommandQueueTest.cs b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs index 2e78021b..da159e46 100644 --- a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs @@ -15,334 +15,333 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.NATS.Commands +namespace Savvyio.Extensions.NATS.Commands; + +public class NatsCommandQueueTest : Test { - public class NatsCommandQueueTest : Test - { - private IMarshaller _marshaller = JsonMarshaller.Default; - private NatsCommandQueueOptions _options = new (); + private IMarshaller _marshaller = JsonMarshaller.Default; + private NatsCommandQueueOptions _options = new (); - public NatsCommandQueueTest(ITestOutputHelper output) : base(output) { } + public NatsCommandQueueTest(ITestOutputHelper output) : base(output) { } - [Fact] - public void Constructor_ShouldInitialize_WithValidOptions() + [Fact] + public void Constructor_ShouldInitialize_WithValidOptions() + { + var options = new NatsCommandQueueOptions { - var options = new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject" - }; + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject" + }; - var queue = new NatsCommandQueue(_marshaller, options); + var queue = new NatsCommandQueue(_marshaller, options); - Assert.NotNull(queue); - Assert.IsAssignableFrom>(queue); - Assert.IsAssignableFrom>(queue); - Assert.IsAssignableFrom>(queue); - } + Assert.NotNull(queue); + Assert.IsAssignableFrom>(queue); + Assert.IsAssignableFrom>(queue); + Assert.IsAssignableFrom>(queue); + } - [Fact] - public void Constructor_ShouldThrow_WhenMarshallerIsNull() - { - Assert.Throws(() => new NatsCommandQueue(null, _options)); - } + [Fact] + public void Constructor_ShouldThrow_WhenMarshallerIsNull() + { + Assert.Throws(() => new NatsCommandQueue(null, _options)); + } - [Fact] - public void Constructor_ShouldThrow_WhenOptionsIsNull() - { - Assert.Throws(() => new NatsCommandQueue(_marshaller, null)); - } + [Fact] + public void Constructor_ShouldThrow_WhenOptionsIsNull() + { + Assert.Throws(() => new NatsCommandQueue(_marshaller, null)); + } - - [Fact] - public void Constructor_ShouldThrow_WhenOptionsAreInvalid() - { - Assert.Throws(() => new NatsCommandQueue(_marshaller, _options)); - } + + [Fact] + public void Constructor_ShouldThrow_WhenOptionsAreInvalid() + { + Assert.Throws(() => new NatsCommandQueue(_marshaller, _options)); + } - [Fact] - public void GetHealthCheckTarget_Should_Return_Connection() + [Fact] + public void GetHealthCheckTarget_Should_Return_Connection() + { + var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions { - var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject" - }); + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject" + }); - Assert.Same(queue.GetHealthCheckTarget(), queue.GetHealthCheckTarget()); - Assert.NotNull(queue.GetHealthCheckTarget()); - } + Assert.Same(queue.GetHealthCheckTarget(), queue.GetHealthCheckTarget()); + Assert.NotNull(queue.GetHealthCheckTarget()); + } - [Fact] - public async Task SendAsync_WithEmptyMessages_ShouldCoverJetStreamContextCreation() + [Fact] + public async Task SendAsync_WithEmptyMessages_ShouldCoverJetStreamContextCreation() + { + var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions { - var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject" - }); + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject" + }); - await queue.SendAsync(Array.Empty>()); + await queue.SendAsync(Array.Empty>()); - Assert.True(true); - } + Assert.True(true); + } - [Fact] - public async Task SendAsync_WithOneMessage_ShouldCoverLoopBodyBeforeConnectionFailure() + [Fact] + public async Task SendAsync_WithOneMessage_ShouldCoverLoopBodyBeforeConnectionFailure() + { + var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions { - var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject", - NatsUrl = new Uri("nats://localhost:59999") - }); + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject", + NatsUrl = new Uri("nats://localhost:59999") + }); - var message = new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test", - new TestCommand()); + var message = new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test", + new TestCommand()); - var ex = await Record.ExceptionAsync(() => queue.SendAsync(new IMessage[] { message })); + var ex = await Record.ExceptionAsync(() => queue.SendAsync(new IMessage[] { message })); - Assert.NotNull(ex); - } + Assert.NotNull(ex); + } - [Fact] - public async Task SendAsync_ShouldPublishSerializedMessages() - { - var queue = new TestableNatsCommandQueue(_marshaller, CreateOptions()); - var message = CreateMessage(); + [Fact] + public async Task SendAsync_ShouldPublishSerializedMessages() + { + var queue = new TestableNatsCommandQueue(_marshaller, CreateOptions()); + var message = CreateMessage(); - await queue.SendAsync([message]); + await queue.SendAsync([message]); - Assert.Equal("subject", queue.PublishedSubject); - Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), queue.PublishedHeaders["type"]); - Assert.NotNull(queue.PublishedMessage); - } + Assert.Equal("subject", queue.PublishedSubject); + Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), queue.PublishedHeaders["type"]); + Assert.NotNull(queue.PublishedMessage); + } - [Fact] - public async Task SendAsync_ShouldUseJetStreamContext_WhenPublishingMessage() - { - var context = new Mock(); - context.Setup(c => c.PublishAsync(It.IsAny(), It.IsAny(), null, null, It.IsAny(), It.IsAny())) - .Returns(new ValueTask(default(PubAckResponse))); - var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), context.Object); - var message = CreateMessage(); + [Fact] + public async Task SendAsync_ShouldUseJetStreamContext_WhenPublishingMessage() + { + var context = new Mock(); + context.Setup(c => c.PublishAsync(It.IsAny(), It.IsAny(), null, null, It.IsAny(), It.IsAny())) + .Returns(new ValueTask(default(PubAckResponse))); + var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), context.Object); + var message = CreateMessage(); - await queue.SendAsync([message]); + await queue.SendAsync([message]); - context.Verify(c => c.PublishAsync("subject", It.IsAny(), null, null, It.Is(headers => headers["type"] == message.GetType().ToFullNameIncludingAssemblyName()), It.IsAny()), Times.Once); - } + context.Verify(c => c.PublishAsync("subject", It.IsAny(), null, null, It.Is(headers => headers["type"] == message.GetType().ToFullNameIncludingAssemblyName()), It.IsAny()), Times.Once); + } - [Fact] - public async Task ReceiveAsync_ShouldDeserializeFetchedMessagesAndAcknowledge() + [Fact] + public async Task ReceiveAsync_ShouldDeserializeFetchedMessagesAndAcknowledge() + { + var options = CreateOptions(); + options.AutoAcknowledge = true; + options.Expires = TimeSpan.FromSeconds(30); + var message = CreateMessage(); + var queue = new TestableNatsCommandQueue(_marshaller, options, message); + + var received = new List>(); + await foreach (var item in queue.ReceiveAsync()) { - var options = CreateOptions(); - options.AutoAcknowledge = true; - options.Expires = TimeSpan.FromSeconds(30); - var message = CreateMessage(); - var queue = new TestableNatsCommandQueue(_marshaller, options, message); - - var received = new List>(); - await foreach (var item in queue.ReceiveAsync()) - { - received.Add(item); - } - - Assert.Single(received); - Assert.Equal(message.Id, received[0].Id); - Assert.Equal("stream", queue.StreamConfig.Name); - Assert.Equal("consumer", queue.ConsumerConfig.Name); - Assert.Equal(TimeSpan.FromSeconds(30), queue.FetchOptions.Expires); - Assert.Equal(TimeSpan.FromSeconds(5), queue.FetchOptions.IdleHeartbeat); - Assert.Equal(1, queue.AcknowledgedCount); + received.Add(item); } - [Fact] - public async Task ReceiveAsync_ShouldUseJetStreamContext_WhenCreatingConsumer() - { - var context = new Mock(); - context.Setup(c => c.CreateOrUpdateStreamAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(Mock.Of()); - context.Setup(c => c.CreateOrUpdateConsumerAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(Mock.Of()); - var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), context.Object); - - var consumer = await queue.CallCreateConsumerAsync( - new StreamConfig("stream", ["subject"]), - new ConsumerConfig("consumer"), - CancellationToken.None); - - Assert.NotNull(consumer); - context.Verify(c => c.CreateOrUpdateStreamAsync(It.Is(config => config.Name == "stream"), It.IsAny()), Times.Once); - context.Verify(c => c.CreateOrUpdateConsumerAsync("stream", It.Is(config => config.Name == "consumer"), It.IsAny()), Times.Once); - } + Assert.Single(received); + Assert.Equal(message.Id, received[0].Id); + Assert.Equal("stream", queue.StreamConfig.Name); + Assert.Equal("consumer", queue.ConsumerConfig.Name); + Assert.Equal(TimeSpan.FromSeconds(30), queue.FetchOptions.Expires); + Assert.Equal(TimeSpan.FromSeconds(5), queue.FetchOptions.IdleHeartbeat); + Assert.Equal(1, queue.AcknowledgedCount); + } - [Fact] - public async Task ReceiveAsync_ShouldFetchMessagesFromConsumer() - { - var message = CreateMessage(); - var payload = JsonMarshaller.Default.Serialize(message).ToByteArray().ToBase64String(); - var headers = new NatsHeaders - { - { "type", message.GetType().ToFullNameIncludingAssemblyName() } - }; - var natsMessage = new NatsMsg("subject", "reply", payload.Length, headers, payload, Mock.Of(), default); - var jetStreamMessage = new NatsJSMsg(natsMessage, Mock.Of()); - var consumer = new Mock(); - consumer.Setup(c => c.FetchAsync(It.IsAny(), It.IsAny>(), It.IsAny())) - .Returns(Yield>(jetStreamMessage)); - var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), Mock.Of()); - - var fetched = await queue.CallFetchMessagesAsync(consumer.Object, new NatsJSFetchOpts(), CancellationToken.None); - - Assert.Equal(1, fetched.Count); - Assert.Equal(payload, fetched.Data); - } + [Fact] + public async Task ReceiveAsync_ShouldUseJetStreamContext_WhenCreatingConsumer() + { + var context = new Mock(); + context.Setup(c => c.CreateOrUpdateStreamAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(Mock.Of()); + context.Setup(c => c.CreateOrUpdateConsumerAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Mock.Of()); + var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), context.Object); + + var consumer = await queue.CallCreateConsumerAsync( + new StreamConfig("stream", ["subject"]), + new ConsumerConfig("consumer"), + CancellationToken.None); + + Assert.NotNull(consumer); + context.Verify(c => c.CreateOrUpdateStreamAsync(It.Is(config => config.Name == "stream"), It.IsAny()), Times.Once); + context.Verify(c => c.CreateOrUpdateConsumerAsync("stream", It.Is(config => config.Name == "consumer"), It.IsAny()), Times.Once); + } - [Fact] - public async Task ReceiveAsync_WithPreCancelledToken_ShouldThrowException() + [Fact] + public async Task ReceiveAsync_ShouldFetchMessagesFromConsumer() + { + var message = CreateMessage(); + var payload = JsonMarshaller.Default.Serialize(message).ToByteArray().ToBase64String(); + var headers = new NatsHeaders { - using var cts = new CancellationTokenSource(); - cts.Cancel(); - - var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject" - }); - - var exception = await Record.ExceptionAsync(async () => - { - await foreach (var _ in queue.ReceiveAsync(o => o.CancellationToken = cts.Token)) { } - }); + { "type", message.GetType().ToFullNameIncludingAssemblyName() } + }; + var natsMessage = new NatsMsg("subject", "reply", payload.Length, headers, payload, Mock.Of(), default); + var jetStreamMessage = new NatsJSMsg(natsMessage, Mock.Of()); + var consumer = new Mock(); + consumer.Setup(c => c.FetchAsync(It.IsAny(), It.IsAny>(), It.IsAny())) + .Returns(Yield>(jetStreamMessage)); + var queue = new ContextNatsCommandQueue(_marshaller, CreateOptions(), Mock.Of()); + + var fetched = await queue.CallFetchMessagesAsync(consumer.Object, new NatsJSFetchOpts(), CancellationToken.None); + + Assert.Equal(1, fetched.Count); + Assert.Equal(payload, fetched.Data); + } - Assert.NotNull(exception); - } + [Fact] + public async Task ReceiveAsync_WithPreCancelledToken_ShouldThrowException() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); - private static NatsCommandQueueOptions CreateOptions() + var queue = new NatsCommandQueue(_marshaller, new NatsCommandQueueOptions { - return new NatsCommandQueueOptions - { - StreamName = "stream", - ConsumerName = "consumer", - Subject = "subject" - }; - } + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject" + }); - private static IMessage CreateMessage() + var exception = await Record.ExceptionAsync(async () => { - return new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test", - new TestCommand()); - } + await foreach (var _ in queue.ReceiveAsync(o => o.CancellationToken = cts.Token)) { } + }); + + Assert.NotNull(exception); + } - private sealed class TestableNatsCommandQueue : NatsCommandQueue + private static NatsCommandQueueOptions CreateOptions() + { + return new NatsCommandQueueOptions { - private readonly IMessage _message; + StreamName = "stream", + ConsumerName = "consumer", + Subject = "subject" + }; + } - public TestableNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options, IMessage message = null) : base(marshaller, options) - { - _message = message; - } + private static IMessage CreateMessage() + { + return new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test", + new TestCommand()); + } - public string PublishedSubject { get; private set; } + private sealed class TestableNatsCommandQueue : NatsCommandQueue + { + private readonly IMessage _message; - public string PublishedMessage { get; private set; } + public TestableNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options, IMessage message = null) : base(marshaller, options) + { + _message = message; + } - public NatsHeaders PublishedHeaders { get; private set; } + public string PublishedSubject { get; private set; } - public StreamConfig StreamConfig { get; private set; } + public string PublishedMessage { get; private set; } - public ConsumerConfig ConsumerConfig { get; private set; } + public NatsHeaders PublishedHeaders { get; private set; } - public NatsJSFetchOpts FetchOptions { get; private set; } + public StreamConfig StreamConfig { get; private set; } - public int AcknowledgedCount { get; private set; } + public ConsumerConfig ConsumerConfig { get; private set; } - protected override Task PublishMessageAsync(INatsJSContext context, string subject, string message, NatsHeaders headers) - { - PublishedSubject = subject; - PublishedMessage = message; - PublishedHeaders = headers; - return Task.CompletedTask; - } + public NatsJSFetchOpts FetchOptions { get; private set; } - protected override Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) - { - StreamConfig = streamConfig; - ConsumerConfig = consumerConfig; - return Task.FromResult(null); - } + public int AcknowledgedCount { get; private set; } - protected override async IAsyncEnumerable FetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) - { - FetchOptions = options; - if (_message != null) - { - var payload = JsonMarshaller.Default.Serialize(_message).ToByteArray().ToBase64String(); - yield return new ReceivedNatsMessage(new NatsHeaders - { - { "type", _message.GetType().ToFullNameIncludingAssemblyName() } - }, payload, _ => - { - AcknowledgedCount++; - return Task.CompletedTask; - }); - } - - await Task.CompletedTask.ConfigureAwait(false); - } + protected override Task PublishMessageAsync(INatsJSContext context, string subject, string message, NatsHeaders headers) + { + PublishedSubject = subject; + PublishedMessage = message; + PublishedHeaders = headers; + return Task.CompletedTask; } - private sealed class ContextNatsCommandQueue : NatsCommandQueue + protected override Task CreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) { - private readonly INatsJSContext _context; + StreamConfig = streamConfig; + ConsumerConfig = consumerConfig; + return Task.FromResult(null); + } - public ContextNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options, INatsJSContext context) : base(marshaller, options) + protected override async IAsyncEnumerable FetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) + { + FetchOptions = options; + if (_message != null) { - _context = context; + var payload = JsonMarshaller.Default.Serialize(_message).ToByteArray().ToBase64String(); + yield return new ReceivedNatsMessage(new NatsHeaders + { + { "type", _message.GetType().ToFullNameIncludingAssemblyName() } + }, payload, _ => + { + AcknowledgedCount++; + return Task.CompletedTask; + }); } - public Task CallCreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) - { - return base.CreateConsumerAsync(streamConfig, consumerConfig, cancellationToken); - } + await Task.CompletedTask.ConfigureAwait(false); + } + } - public async Task<(int Count, string Data)> CallFetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, CancellationToken cancellationToken) - { - var count = 0; - string data = null; - await foreach (var message in base.FetchMessagesAsync(consumer, options, cancellationToken)) - { - count++; - data = message.Data; - await Record.ExceptionAsync(() => message.AcknowledgeAsync(cancellationToken)).ConfigureAwait(false); - } + private sealed class ContextNatsCommandQueue : NatsCommandQueue + { + private readonly INatsJSContext _context; - return (count, data); - } + public ContextNatsCommandQueue(IMarshaller marshaller, NatsCommandQueueOptions options, INatsJSContext context) : base(marshaller, options) + { + _context = context; + } + + public Task CallCreateConsumerAsync(StreamConfig streamConfig, ConsumerConfig consumerConfig, CancellationToken cancellationToken) + { + return base.CreateConsumerAsync(streamConfig, consumerConfig, cancellationToken); + } - protected override INatsJSContext CreateJetStreamContext() + public async Task<(int Count, string Data)> CallFetchMessagesAsync(INatsJSConsumer consumer, NatsJSFetchOpts options, CancellationToken cancellationToken) + { + var count = 0; + string data = null; + await foreach (var message in base.FetchMessagesAsync(consumer, options, cancellationToken)) { - return _context; + count++; + data = message.Data; + await Record.ExceptionAsync(() => message.AcknowledgeAsync(cancellationToken)).ConfigureAwait(false); } + + return (count, data); } - private static async IAsyncEnumerable Yield(T item) + protected override INatsJSContext CreateJetStreamContext() { - yield return item; - await Task.CompletedTask.ConfigureAwait(false); + return _context; } + } - private record TestCommand : Command { } + private static async IAsyncEnumerable Yield(T item) + { + yield return item; + await Task.CompletedTask.ConfigureAwait(false); } + + private record TestCommand : Command { } } diff --git a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusOptionsTest.cs index ad01e1db..88fa0131 100644 --- a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusOptionsTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusOptionsTest.cs @@ -1,30 +1,29 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +public class NatsEventBusOptionsTest : Test { - public class NatsEventBusOptionsTest : Test + public NatsEventBusOptionsTest(ITestOutputHelper output) : base(output) { - public NatsEventBusOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Inherit_Defaults_From_Base_Type() - { - var options = new NatsEventBusOptions(); + [Fact] + public void Constructor_Should_Inherit_Defaults_From_Base_Type() + { + var options = new NatsEventBusOptions(); - Assert.IsAssignableFrom(options); - Assert.Equal(new System.Uri("nats://127.0.0.1:4222"), options.NatsUrl); - Assert.Null(options.Subject); - } + Assert.IsAssignableFrom(options); + Assert.Equal(new System.Uri("nats://127.0.0.1:4222"), options.NatsUrl); + Assert.Null(options.Subject); + } - [Fact] - public void ValidateOptions_Should_Require_Subject() - { - var options = new NatsEventBusOptions(); + [Fact] + public void ValidateOptions_Should_Require_Subject() + { + var options = new NatsEventBusOptions(); - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); } } diff --git a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs index b78e0823..e0eeb948 100644 --- a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs @@ -13,180 +13,179 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.NATS.EventDriven +namespace Savvyio.Extensions.NATS.EventDriven; + +public class NatsEventBusTest : Test { - public class NatsEventBusTest : Test - { - private IMarshaller _marshaller = JsonMarshaller.Default; - private NatsEventBusOptions _options = new (); + private IMarshaller _marshaller = JsonMarshaller.Default; + private NatsEventBusOptions _options = new (); - public NatsEventBusTest(ITestOutputHelper output) : base(output) { } + public NatsEventBusTest(ITestOutputHelper output) : base(output) { } - [Fact] - public void Constructor_ShouldInitialize_WithValidOptions() + [Fact] + public void Constructor_ShouldInitialize_WithValidOptions() + { + var options = new NatsEventBusOptions { - var options = new NatsEventBusOptions - { - Subject = "subject" - }; + Subject = "subject" + }; - var bus = new NatsEventBus(_marshaller, options); + var bus = new NatsEventBus(_marshaller, options); - Assert.NotNull(bus); - Assert.IsAssignableFrom>(bus); - Assert.IsAssignableFrom>(bus); - Assert.IsAssignableFrom>(bus); - } + Assert.NotNull(bus); + Assert.IsAssignableFrom>(bus); + Assert.IsAssignableFrom>(bus); + Assert.IsAssignableFrom>(bus); + } - [Fact] - public void Constructor_ShouldThrow_WhenMarshallerIsNull() - { - Assert.Throws(() => new NatsEventBus(null, _options)); - } + [Fact] + public void Constructor_ShouldThrow_WhenMarshallerIsNull() + { + Assert.Throws(() => new NatsEventBus(null, _options)); + } - [Fact] - public void Constructor_ShouldThrow_WhenOptionsIsNull() - { - Assert.Throws(() => new NatsEventBus(_marshaller, null)); - } + [Fact] + public void Constructor_ShouldThrow_WhenOptionsIsNull() + { + Assert.Throws(() => new NatsEventBus(_marshaller, null)); + } - - [Fact] - public void Constructor_ShouldThrow_WhenOptionsAreInvalid() - { - Assert.Throws(() => new NatsEventBus(_marshaller, _options)); - } + + [Fact] + public void Constructor_ShouldThrow_WhenOptionsAreInvalid() + { + Assert.Throws(() => new NatsEventBus(_marshaller, _options)); + } - [Fact] - public void GetHealthCheckTarget_Should_Return_Connection() + [Fact] + public void GetHealthCheckTarget_Should_Return_Connection() + { + var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { - var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions - { - Subject = "subject" - }); + Subject = "subject" + }); - Assert.Same(bus.GetHealthCheckTarget(), bus.GetHealthCheckTarget()); - Assert.NotNull(bus.GetHealthCheckTarget()); - } + Assert.Same(bus.GetHealthCheckTarget(), bus.GetHealthCheckTarget()); + Assert.NotNull(bus.GetHealthCheckTarget()); + } - [Fact] - public async Task PublishAsync_WithPreCancelledToken_ShouldThrowOperationCanceledException() - { - using var cts = new CancellationTokenSource(); - cts.Cancel(); + [Fact] + public async Task PublishAsync_WithPreCancelledToken_ShouldThrowOperationCanceledException() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); - var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); - var message = new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test.event", - new TestIntegrationEvent()); + var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); + var message = new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test.event", + new TestIntegrationEvent()); - var ex = await Record.ExceptionAsync( - () => bus.PublishAsync(message, o => o.CancellationToken = cts.Token)); + var ex = await Record.ExceptionAsync( + () => bus.PublishAsync(message, o => o.CancellationToken = cts.Token)); - Assert.NotNull(ex); - Assert.IsAssignableFrom(ex); - } + Assert.NotNull(ex); + Assert.IsAssignableFrom(ex); + } - [Fact] - public async Task PublishAsync_ShouldPublishSerializedMessage() - { - var bus = new TestableNatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); - var message = CreateMessage(); + [Fact] + public async Task PublishAsync_ShouldPublishSerializedMessage() + { + var bus = new TestableNatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); + var message = CreateMessage(); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - Assert.Equal("subject", bus.PublishedSubject); - Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), bus.PublishedHeaders["type"]); - Assert.NotNull(bus.PublishedMessage); - } + Assert.Equal("subject", bus.PublishedSubject); + Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), bus.PublishedHeaders["type"]); + Assert.NotNull(bus.PublishedMessage); + } - [Fact] - public async Task SubscribeAsync_WithPreCancelledToken_ShouldThrowOperationCanceledException() - { - using var cts = new CancellationTokenSource(); - cts.Cancel(); + [Fact] + public async Task SubscribeAsync_WithPreCancelledToken_ShouldThrowOperationCanceledException() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); - var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); + var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); - var ex = await Record.ExceptionAsync( - () => bus.SubscribeAsync( - (msg, ct) => Task.CompletedTask, - o => o.CancellationToken = cts.Token)); + var ex = await Record.ExceptionAsync( + () => bus.SubscribeAsync( + (msg, ct) => Task.CompletedTask, + o => o.CancellationToken = cts.Token)); - Assert.NotNull(ex); - Assert.IsAssignableFrom(ex); - } + Assert.NotNull(ex); + Assert.IsAssignableFrom(ex); + } + + [Fact] + public async Task SubscribeAsync_ShouldDeserializeMessagesAndInvokeHandler() + { + var message = CreateMessage(); + var bus = new TestableNatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }, message); + IMessage received = null; - [Fact] - public async Task SubscribeAsync_ShouldDeserializeMessagesAndInvokeHandler() + await bus.SubscribeAsync((msg, _) => { - var message = CreateMessage(); - var bus = new TestableNatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }, message); - IMessage received = null; + received = msg; + return Task.CompletedTask; + }); - await bus.SubscribeAsync((msg, _) => - { - received = msg; - return Task.CompletedTask; - }); + Assert.NotNull(received); + Assert.Equal(message.Id, received.Id); + Assert.Equal("subject", bus.SubscribedSubject); + } - Assert.NotNull(received); - Assert.Equal(message.Id, received.Id); - Assert.Equal("subject", bus.SubscribedSubject); - } + private static IMessage CreateMessage() + { + return new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test.event", + new TestIntegrationEvent()); + } - private static IMessage CreateMessage() - { - return new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test.event", - new TestIntegrationEvent()); - } + private sealed class TestableNatsEventBus : NatsEventBus + { + private readonly IMessage _message; - private sealed class TestableNatsEventBus : NatsEventBus + public TestableNatsEventBus(IMarshaller marshaller, NatsEventBusOptions options, IMessage message = null) : base(marshaller, options) { - private readonly IMessage _message; - - public TestableNatsEventBus(IMarshaller marshaller, NatsEventBusOptions options, IMessage message = null) : base(marshaller, options) - { - _message = message; - } + _message = message; + } - public string PublishedSubject { get; private set; } + public string PublishedSubject { get; private set; } - public string PublishedMessage { get; private set; } + public string PublishedMessage { get; private set; } - public NatsHeaders PublishedHeaders { get; private set; } + public NatsHeaders PublishedHeaders { get; private set; } - public string SubscribedSubject { get; private set; } + public string SubscribedSubject { get; private set; } - protected override Task PublishMessageAsync(string subject, string message, NatsHeaders headers, CancellationToken cancellationToken) - { - PublishedSubject = subject; - PublishedMessage = message; - PublishedHeaders = headers; - return Task.CompletedTask; - } + protected override Task PublishMessageAsync(string subject, string message, NatsHeaders headers, CancellationToken cancellationToken) + { + PublishedSubject = subject; + PublishedMessage = message; + PublishedHeaders = headers; + return Task.CompletedTask; + } - protected override async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) + protected override async IAsyncEnumerable SubscribeMessagesAsync(string subject, NatsSubOpts options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken) + { + SubscribedSubject = subject; + if (_message != null) { - SubscribedSubject = subject; - if (_message != null) + yield return new ReceivedNatsMessage(new NatsHeaders { - yield return new ReceivedNatsMessage(new NatsHeaders - { - { "type", _message.GetType().ToFullNameIncludingAssemblyName() } - }, JsonMarshaller.Default.Serialize(_message).ToByteArray().ToBase64String()); - } - - await Task.CompletedTask.ConfigureAwait(false); + { "type", _message.GetType().ToFullNameIncludingAssemblyName() } + }, JsonMarshaller.Default.Serialize(_message).ToByteArray().ToBase64String()); } - } - private record TestIntegrationEvent : IntegrationEvent { } + await Task.CompletedTask.ConfigureAwait(false); + } } + + private record TestIntegrationEvent : IntegrationEvent { } } diff --git a/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs index ce9d699b..3719e109 100644 --- a/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs @@ -3,58 +3,57 @@ using Cuemon; using Xunit; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +public class NatsMessageOptionsTest : Test { - public class NatsMessageOptionsTest : Test + public NatsMessageOptionsTest(ITestOutputHelper output) : base(output) { } + + [Fact] + public void Constructor_ShouldSetDefaults() + { + var options = new NatsMessageOptions(); + Assert.NotNull(options.NatsUrl); + Assert.Equal("nats://127.0.0.1:4222", options.NatsUrl.OriginalString); + Assert.Null(options.Subject); + } + + [Fact] + public void ValidateOptions_ShouldThrow_WhenNatsUrlIsNull() + { + var options = new NatsMessageOptions { NatsUrl = null, Subject = "foo" }; + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_ShouldThrow_WhenSubjectIsNullOrWhitespace() + { + var options = new NatsMessageOptions { Subject = null }; + Assert.Throws(() => options.ValidateOptions()); + + options.Subject = ""; + Assert.Throws(() => options.ValidateOptions()); + + options.Subject = " "; + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_ShouldNotThrow_WhenValid() { - public NatsMessageOptionsTest(ITestOutputHelper output) : base(output) { } - - [Fact] - public void Constructor_ShouldSetDefaults() - { - var options = new NatsMessageOptions(); - Assert.NotNull(options.NatsUrl); - Assert.Equal("nats://127.0.0.1:4222", options.NatsUrl.OriginalString); - Assert.Null(options.Subject); - } - - [Fact] - public void ValidateOptions_ShouldThrow_WhenNatsUrlIsNull() - { - var options = new NatsMessageOptions { NatsUrl = null, Subject = "foo" }; - Assert.Throws(() => options.ValidateOptions()); - } - - [Fact] - public void ValidateOptions_ShouldThrow_WhenSubjectIsNullOrWhitespace() - { - var options = new NatsMessageOptions { Subject = null }; - Assert.Throws(() => options.ValidateOptions()); - - options.Subject = ""; - Assert.Throws(() => options.ValidateOptions()); - - options.Subject = " "; - Assert.Throws(() => options.ValidateOptions()); - } - - [Fact] - public void ValidateOptions_ShouldNotThrow_WhenValid() - { - var options = new NatsMessageOptions { Subject = "foo" }; - var ex = Record.Exception(() => options.ValidateOptions()); - Assert.Null(ex); - } - - [Fact] - public void Validator_Should_Wrap_Invalid_Options() - { - var options = new NatsMessageOptions(); - - var exception = Assert.Throws(() => Validator.ThrowIfInvalidOptions(options)); - - Assert.Equal($"{nameof(NatsMessageOptions)} are not in a valid state. (Parameter '{nameof(options)}')", exception.Message); - Assert.IsType(exception.InnerException); - } + var options = new NatsMessageOptions { Subject = "foo" }; + var ex = Record.Exception(() => options.ValidateOptions()); + Assert.Null(ex); + } + + [Fact] + public void Validator_Should_Wrap_Invalid_Options() + { + var options = new NatsMessageOptions(); + + var exception = Assert.Throws(() => Validator.ThrowIfInvalidOptions(options)); + + Assert.Equal($"{nameof(NatsMessageOptions)} are not in a valid state. (Parameter '{nameof(options)}')", exception.Message); + Assert.IsType(exception.InnerException); } } diff --git a/test/Savvyio.Extensions.NATS.Tests/NatsMessageTest.cs b/test/Savvyio.Extensions.NATS.Tests/NatsMessageTest.cs index 1c1b182c..5909271f 100644 --- a/test/Savvyio.Extensions.NATS.Tests/NatsMessageTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/NatsMessageTest.cs @@ -5,79 +5,78 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.Extensions.NATS +namespace Savvyio.Extensions.NATS; + +public class TestNatsMessage : NatsMessage { - public class TestNatsMessage : NatsMessage + public TestNatsMessage(IMarshaller marshaller, NatsMessageOptions options) + : base(marshaller, options) { } + + public Task CallOnDisposeManagedResourcesAsync() { - public TestNatsMessage(IMarshaller marshaller, NatsMessageOptions options) - : base(marshaller, options) { } + return DisposeAsync().AsTask(); + } + + public NatsClient ExposedNatsClient => NatsClient; + public IMarshaller ExposedMarshaller => Marshaller; +} - public Task CallOnDisposeManagedResourcesAsync() - { - return DisposeAsync().AsTask(); - } +public class NatsMessageTest : Test +{ + public NatsMessageTest(ITestOutputHelper output) : base(output) { } + + [Fact] + public void Constructor_ShouldInitializeProperties() + { + var marshaller = JsonMarshaller.Default; + var options = new NatsMessageOptions { Subject = "foo" }; - public NatsClient ExposedNatsClient => NatsClient; - public IMarshaller ExposedMarshaller => Marshaller; + var sut = new TestNatsMessage(marshaller, options); + + Assert.NotNull(sut.ExposedNatsClient); + Assert.Same(marshaller, sut.ExposedMarshaller); + } + + [Fact] + public void Constructor_ShouldThrow_WhenMarshallerIsNull() + { + var options = new NatsMessageOptions { Subject = "foo" }; + Assert.Throws(() => new TestNatsMessage(null, options)); } - public class NatsMessageTest : Test + [Fact] + public void Constructor_ShouldThrow_WhenOptionsIsNull() { - public NatsMessageTest(ITestOutputHelper output) : base(output) { } - - [Fact] - public void Constructor_ShouldInitializeProperties() - { - var marshaller = JsonMarshaller.Default; - var options = new NatsMessageOptions { Subject = "foo" }; - - var sut = new TestNatsMessage(marshaller, options); - - Assert.NotNull(sut.ExposedNatsClient); - Assert.Same(marshaller, sut.ExposedMarshaller); - } - - [Fact] - public void Constructor_ShouldThrow_WhenMarshallerIsNull() - { - var options = new NatsMessageOptions { Subject = "foo" }; - Assert.Throws(() => new TestNatsMessage(null, options)); - } - - [Fact] - public void Constructor_ShouldThrow_WhenOptionsIsNull() - { - Assert.Throws(() => new TestNatsMessage(JsonMarshaller.Default, null)); - } - - [Fact] - public void Constructor_ShouldThrow_WhenOptionsInvalid() - { - Assert.Throws(() => new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions())); - } - - [Fact] - public void GetHealthCheckTarget_ShouldReturnNatsConnection() - { - var sut = new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions { Subject = "foo" }); - - var connection = sut.GetHealthCheckTarget(); - - Assert.NotNull(connection); - Assert.Same(sut.ExposedNatsClient.Connection, connection); - } - - [Fact] - public async Task OnDisposeManagedResourcesAsync_ShouldDisposeNatsClient() - { - var sut = new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions { Subject = "foo" }); - - // NatsClient should not be disposed before - Assert.False(sut.Disposed); - - await sut.CallOnDisposeManagedResourcesAsync(); - - Assert.True(sut.Disposed); - } + Assert.Throws(() => new TestNatsMessage(JsonMarshaller.Default, null)); + } + + [Fact] + public void Constructor_ShouldThrow_WhenOptionsInvalid() + { + Assert.Throws(() => new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions())); + } + + [Fact] + public void GetHealthCheckTarget_ShouldReturnNatsConnection() + { + var sut = new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions { Subject = "foo" }); + + var connection = sut.GetHealthCheckTarget(); + + Assert.NotNull(connection); + Assert.Same(sut.ExposedNatsClient.Connection, connection); + } + + [Fact] + public async Task OnDisposeManagedResourcesAsync_ShouldDisposeNatsClient() + { + var sut = new TestNatsMessage(JsonMarshaller.Default, new NatsMessageOptions { Subject = "foo" }); + + // NatsClient should not be disposed before + Assert.False(sut.Disposed); + + await sut.CallOnDisposeManagedResourcesAsync(); + + Assert.True(sut.Disposed); } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/AggregateRootConverterTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/AggregateRootConverterTest.cs index 056db83d..0ed6eb72 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/AggregateRootConverterTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/AggregateRootConverterTest.cs @@ -5,100 +5,99 @@ using Savvyio.Domain; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +public class AggregateRootConverterTest : Test { - public class AggregateRootConverterTest : Test + public AggregateRootConverterTest(ITestOutputHelper output) : base(output) { - public AggregateRootConverterTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AggregateRootConverter_ShouldDeserializeUsingMatchingConstructor() - { - var id = Guid.NewGuid(); - var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(new MatchingAggregate(id, "Jane Doe"), settings); + [Fact] + public void AggregateRootConverter_ShouldDeserializeUsingMatchingConstructor() + { + var id = Guid.NewGuid(); + var settings = CreateSettings(); + var json = JsonConvert.SerializeObject(new MatchingAggregate(id, "Jane Doe"), settings); - var sut = JsonConvert.DeserializeObject(json, settings); + var sut = JsonConvert.DeserializeObject(json, settings); - Assert.NotNull(sut); - Assert.Equal(id, sut.Id); - Assert.Equal("Jane Doe", sut.Name); - } + Assert.NotNull(sut); + Assert.Equal(id, sut.Id); + Assert.Equal("Jane Doe", sut.Name); + } - [Fact] - public void AggregateRootConverter_ShouldDeserializeUsingDefaultConstructorFallback() + [Fact] + public void AggregateRootConverter_ShouldDeserializeUsingDefaultConstructorFallback() + { + var id = Guid.NewGuid(); + var providerId = new PlatformProviderId(Guid.NewGuid()); + var settings = CreateSettings(); + var json = JsonConvert.SerializeObject(new FallbackAggregate(id, "Jane Doe") { - var id = Guid.NewGuid(); - var providerId = new PlatformProviderId(Guid.NewGuid()); - var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(new FallbackAggregate(id, "Jane Doe") - { - PlatformProviderId = providerId - }, settings); - - var sut = JsonConvert.DeserializeObject(json, settings); - - Assert.NotNull(sut); - Assert.Equal(id, sut.Id); - Assert.Equal("Jane Doe", sut.Name); - Assert.Equal(providerId, sut.PlatformProviderId); - } + PlatformProviderId = providerId + }, settings); - [Fact] - public void AggregateRootConverter_ShouldThrowWhenNoSuitableConstructorExists() - { - var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(new UnsupportedAggregate("Jane Doe"), settings); + var sut = JsonConvert.DeserializeObject(json, settings); + + Assert.NotNull(sut); + Assert.Equal(id, sut.Id); + Assert.Equal("Jane Doe", sut.Name); + Assert.Equal(providerId, sut.PlatformProviderId); + } + + [Fact] + public void AggregateRootConverter_ShouldThrowWhenNoSuitableConstructorExists() + { + var settings = CreateSettings(); + var json = JsonConvert.SerializeObject(new UnsupportedAggregate("Jane Doe"), settings); - var ex = Assert.Throws(() => JsonConvert.DeserializeObject(json, settings)); + var ex = Assert.Throws(() => JsonConvert.DeserializeObject(json, settings)); - Assert.StartsWith("Unable to deserialize", ex.Message); - } + Assert.StartsWith("Unable to deserialize", ex.Message); + } + + private static JsonSerializerSettings CreateSettings() + { + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new AggregateRootConverter()); + settings.Converters.Add(new SingleValueObjectConverter()); + return settings; + } - private static JsonSerializerSettings CreateSettings() + private sealed class MatchingAggregate : AggregateRoot + { + public MatchingAggregate(Guid id, string name) : base(id) { - var settings = new JsonSerializerSettings(); - settings.Converters.Add(new AggregateRootConverter()); - settings.Converters.Add(new SingleValueObjectConverter()); - return settings; + Name = name; } - private sealed class MatchingAggregate : AggregateRoot - { - public MatchingAggregate(Guid id, string name) : base(id) - { - Name = name; - } + public string Name { get; } + } - public string Name { get; } + private sealed class FallbackAggregate : AggregateRoot + { + public FallbackAggregate() + { } - private sealed class FallbackAggregate : AggregateRoot + public FallbackAggregate(Guid id, string name) : base(id) { - public FallbackAggregate() - { - } - - public FallbackAggregate(Guid id, string name) : base(id) - { - Name = name; - } + Name = name; + } - public string Name { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; - public PlatformProviderId PlatformProviderId { get; set; } - } + public PlatformProviderId PlatformProviderId { get; set; } + } - private sealed class UnsupportedAggregate : AggregateRoot + private sealed class UnsupportedAggregate : AggregateRoot + { + public UnsupportedAggregate(string name) { - public UnsupportedAggregate(string name) - { - Name = name; - } - - public string Name { get; } + Name = name; } + + public string Name { get; } } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs index 3ad76df4..88e7f038 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs @@ -4,42 +4,41 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Commands +namespace Savvyio.Extensions.Newtonsoft.Json.Commands; + +public class CommandTest : Test { - public class CommandTest : Test + public CommandTest(ITestOutputHelper output) : base(output) { - public CommandTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CreateAccount_ShouldUseCustomConverter() - { - var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + [Fact] + public void CreateAccount_ShouldUseCustomConverter() + { + var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var json = new NewtonsoftJsonMarshaller().Serialize(ca); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(ca); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); + var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); - Assert.Equivalent(ca, rehydrated, true); - } + Assert.Equivalent(ca, rehydrated, true); + } - [Fact] - public void CreateAccountWithValueObjects_ShouldUseCustomConverter() - { - var ca = new CreateAccountWithValueObjects(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + [Fact] + public void CreateAccountWithValueObjects_ShouldUseCustomConverter() + { + var ca = new CreateAccountWithValueObjects(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var json = new NewtonsoftJsonMarshaller().Serialize(ca); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(ca); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); + var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); - Assert.Equivalent(ca, rehydrated, true); - } + Assert.Equivalent(ca, rehydrated, true); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs index 6a08b053..7e7ff31e 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs @@ -7,35 +7,35 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging +namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging; + +public class CommandExtensionsTest : Test { - public class CommandExtensionsTest : Test + public CommandExtensionsTest(ITestOutputHelper output) : base(output) { - public CommandExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EncloseToMessage_ShouldSerialize_WithoutSignature() + [Fact] + public void EncloseToMessage_ShouldSerialize_WithoutSignature() + { + var utcNow = DateTime.UtcNow; + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }); - var json = new NewtonsoftJsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); + var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -52,6 +52,5 @@ public void EncloseToMessage_ShouldSerialize_WithoutSignature() } } """.ReplaceLineEndings(), jsonString); - } } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs index b1032c49..9f369668 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs @@ -9,71 +9,70 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging.Cryptography +namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging.Cryptography; + +public class MessageExtensionsTest : Test { - public class MessageExtensionsTest : Test + public MessageExtensionsTest(ITestOutputHelper output) : base(output) { - public MessageExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EncloseToSignedMessage_ShouldSerializeAndDeserialize_WithSignature() + [Fact] + public void EncloseToSignedMessage_ShouldSerializeAndDeserialize_WithSignature() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }); - var sut3 = sut2.Sign(NewtonsoftJsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); + var sut3 = sut2.Sign(NewtonsoftJsonMarshaller.Default, o => + { + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut3); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut3); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - sut3.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + sut3.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var signatureException = Assert.Throws(() => - { - sut3.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + var signatureException = Assert.Throws(() => + { + sut3.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"CreateMemberCommand","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","age":21,"emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.Commands.CreateMemberCommand, Savvyio.Assets.Tests","correlationId":"3eefdef050c340bfba100bd49c58c181"}},"signature":"0cb0f1b239d9a31fad1dcbf9819e105d841f860c818f389d487d0693ed014c5b"}""", jsonString); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"CreateMemberCommand","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","age":21,"emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.Commands.CreateMemberCommand, Savvyio.Assets.Tests","correlationId":"3eefdef050c340bfba100bd49c58c181"}},"signature":"0cb0f1b239d9a31fad1dcbf9819e105d841f860c818f389d487d0693ed014c5b"}""", jsonString); - } + } - [Fact] - public void EncloseToSignedMessage_ShouldDeserializeSignedMessageInterface_WithSignature() + [Fact] + public void EncloseToSignedMessage_ShouldDeserializeSignedMessageInterface_WithSignature() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var sut3 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var sut3 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - Assert.IsType>(sut3); - Assert.Equal(sut2.Id, sut3.Id); - Assert.Equal(sut2.Source, sut3.Source); - Assert.Equal(sut2.Type, sut3.Type); - Assert.Equal(sut2.Signature, sut3.Signature); - Assert.Equivalent(sut2.Data, sut3.Data, true); - } + Assert.IsType>(sut3); + Assert.Equal(sut2.Id, sut3.Id); + Assert.Equal(sut2.Source, sut3.Source); + Assert.Equal(sut2.Type, sut3.Type); + Assert.Equal(sut2.Signature, sut3.Signature); + Assert.Equivalent(sut2.Data, sut3.Data, true); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs index dbdd96e8..5b989b16 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs @@ -14,75 +14,74 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging +namespace Savvyio.Extensions.Newtonsoft.Json.Commands.Messaging; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class InMemoryCommandQueueTest : Test { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class InMemoryCommandQueueTest : Test - { - private static readonly InMemoryCommandQueue Queue = new(); - private static readonly InMemoryTestStore> Comparer = new(); + private static readonly InMemoryCommandQueue Queue = new(); + private static readonly InMemoryTestStore> Comparer = new(); - public InMemoryCommandQueueTest(ITestOutputHelper output) : base(output) - { - } + public InMemoryCommandQueueTest(ITestOutputHelper output) : base(output) + { + } - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); - TestOutput.WriteLine(new NewtonsoftJsonMarshaller().Serialize(sut2).ToEncodedString()); + TestOutput.WriteLine(new NewtonsoftJsonMarshaller().Serialize(sut2).ToEncodedString()); - Comparer.Add(sut3); + Comparer.Add(sut3); - await Queue.SendAsync(sut3.Yield()); - } + await Queue.SendAsync(sut3.Yield()); + } - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() - { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - var sut2 = await Queue.ReceiveAsync().SingleOrDefaultAsync(); + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); + var sut2 = await Queue.ReceiveAsync().SingleOrDefaultAsync(); - Assert.Equal(sut1.Data, sut2.Data); - Assert.Equal(sut1.Time, sut2.Time); - Assert.Equal(sut1.Source, sut2.Source); - Assert.Equal(sut1.Id, sut2.Id); - Assert.Equal(sut1.Type, sut2.Type); - } + Assert.Equal(sut1.Data, sut2.Data); + Assert.Equal(sut1.Time, sut2.Time); + Assert.Equal(sut1.Source, sut2.Source); + Assert.Equal(sut1.Id, sut2.Id); + Assert.Equal(sut1.Type, sut2.Type); + } - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_ThousandTimes() + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_ThousandTimes() + { + var messages = Generate.RangeOf(1000, i => { - var messages = Generate.RangeOf(1000, i => - { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); - }); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return Queue.SendAsync(message.Yield(), o => o.CancellationToken = token); - }); - } - - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_All() + await ParallelFactory.ForEachAsync(messages, (message, token) => { - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - var sut2 = await Queue.ReceiveAsync().ToListAsync(); + Comparer.Add(message); + return Queue.SendAsync(message.Yield(), o => o.CancellationToken = token); + }); + } + + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + var sut2 = await Queue.ReceiveAsync().ToListAsync(); - TestOutput.WriteLines(sut2.Take(10)); + TestOutput.WriteLines(sut2.Take(10)); - Assert.Equal(sut1.Count, sut2.Count); - Assert.Equal(sut1, sut2); - Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + Assert.Equal(sut1.Count, sut2.Count); + Assert.Equal(sut1, sut2); + Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Converters/ValueObjectConverterTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Converters/ValueObjectConverterTest.cs index 0f29af40..5518e8b0 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Converters/ValueObjectConverterTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Converters/ValueObjectConverterTest.cs @@ -4,162 +4,161 @@ using Savvyio.Domain; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +public class ValueObjectConverterTest : Test { - public class ValueObjectConverterTest : Test + public ValueObjectConverterTest(ITestOutputHelper output) : base(output) { - public ValueObjectConverterTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void WriteJson_ShouldSerializeValueObjectWithSimpleProperties() - { - var sut = new SimplePoint(3, 7); - var settings = CreateSettings(); + [Fact] + public void WriteJson_ShouldSerializeValueObjectWithSimpleProperties() + { + var sut = new SimplePoint(3, 7); + var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(sut, settings); + var json = JsonConvert.SerializeObject(sut, settings); - TestOutput.WriteLine(json); + TestOutput.WriteLine(json); - Assert.Contains("X", json); - Assert.Contains("Y", json); - Assert.Contains("3", json); - Assert.Contains("7", json); - } + Assert.Contains("X", json); + Assert.Contains("Y", json); + Assert.Contains("3", json); + Assert.Contains("7", json); + } - [Fact] - public void WriteJson_ShouldSerializeSingleValueObjectProperty() - { - var sut = new LabeledPoint("origin", new PointLabel("O")); - var settings = CreateSettings(); + [Fact] + public void WriteJson_ShouldSerializeSingleValueObjectProperty() + { + var sut = new LabeledPoint("origin", new PointLabel("O")); + var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(sut, settings); + var json = JsonConvert.SerializeObject(sut, settings); - TestOutput.WriteLine(json); + TestOutput.WriteLine(json); - Assert.Contains("Name", json); - Assert.Contains("Label", json); - Assert.Contains("origin", json); - Assert.Contains("O", json); - } + Assert.Contains("Name", json); + Assert.Contains("Label", json); + Assert.Contains("origin", json); + Assert.Contains("O", json); + } - [Fact] - public void ReadJson_ShouldDeserializeSingleValueObjectScalarWhenNested() - { - var original = new LabeledPoint("center", new PointLabel("C")); - var settings = CreateSettings(); + [Fact] + public void ReadJson_ShouldDeserializeSingleValueObjectScalarWhenNested() + { + var original = new LabeledPoint("center", new PointLabel("C")); + var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(original, settings); - TestOutput.WriteLine(json); + var json = JsonConvert.SerializeObject(original, settings); + TestOutput.WriteLine(json); - var result = JsonConvert.DeserializeObject(json, settings); + var result = JsonConvert.DeserializeObject(json, settings); - Assert.NotNull(result); - Assert.Equal("center", result.Name); - Assert.NotNull(result.Label); - Assert.Equal("C", result.Label.Value); - } + Assert.NotNull(result); + Assert.Equal("center", result.Name); + Assert.NotNull(result.Label); + Assert.Equal("C", result.Label.Value); + } - [Fact] - public void ReadJson_ShouldDeserializeComplexValueObjectWithMatchingCtor() - { - var original = new SimplePoint(1, 2); - var settings = CreateSettings(); + [Fact] + public void ReadJson_ShouldDeserializeComplexValueObjectWithMatchingCtor() + { + var original = new SimplePoint(1, 2); + var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(original, settings); - TestOutput.WriteLine(json); + var json = JsonConvert.SerializeObject(original, settings); + TestOutput.WriteLine(json); - var result = JsonConvert.DeserializeObject(json, settings); + var result = JsonConvert.DeserializeObject(json, settings); - Assert.NotNull(result); - Assert.Equal(1, result.X); - Assert.Equal(2, result.Y); - } + Assert.NotNull(result); + Assert.Equal(1, result.X); + Assert.Equal(2, result.Y); + } - [Fact] - public void ReadJson_ShouldDeserializeValueObjectWithDefaultCtor() - { - var original = new MutablePoint { X = 5, Y = 6 }; - var settings = CreateSettings(); + [Fact] + public void ReadJson_ShouldDeserializeValueObjectWithDefaultCtor() + { + var original = new MutablePoint { X = 5, Y = 6 }; + var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(original, settings); - TestOutput.WriteLine(json); + var json = JsonConvert.SerializeObject(original, settings); + TestOutput.WriteLine(json); - var result = JsonConvert.DeserializeObject(json, settings); + var result = JsonConvert.DeserializeObject(json, settings); - Assert.NotNull(result); - Assert.Equal(5, result.X); - Assert.Equal(6, result.Y); - } + Assert.NotNull(result); + Assert.Equal(5, result.X); + Assert.Equal(6, result.Y); + } - [Fact] - public void ReadJson_ShouldThrowInvalidOperationException_WhenNoSuitableCtorExists() - { - var settings = CreateSettings(); - var json = JsonConvert.SerializeObject(new NoSuitableCtorPoint("a", "b"), settings); - TestOutput.WriteLine(json); + [Fact] + public void ReadJson_ShouldThrowInvalidOperationException_WhenNoSuitableCtorExists() + { + var settings = CreateSettings(); + var json = JsonConvert.SerializeObject(new NoSuitableCtorPoint("a", "b"), settings); + TestOutput.WriteLine(json); - var ex = Assert.Throws(() => - JsonConvert.DeserializeObject(json, settings)); + var ex = Assert.Throws(() => + JsonConvert.DeserializeObject(json, settings)); - Assert.Contains("Unable to deserialize", ex.Message); - } + Assert.Contains("Unable to deserialize", ex.Message); + } - private static JsonSerializerSettings CreateSettings() - { - var settings = new JsonSerializerSettings(); - settings.Converters.Add(new ValueObjectConverter()); - return settings; - } + private static JsonSerializerSettings CreateSettings() + { + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new ValueObjectConverter()); + return settings; + } - private record SimplePoint : ValueObject + private record SimplePoint : ValueObject + { + public SimplePoint(int x, int y) { - public SimplePoint(int x, int y) - { - X = x; - Y = y; - } - - public int X { get; } - public int Y { get; } + X = x; + Y = y; } - private sealed record PointLabel : SingleValueObject - { - public PointLabel(string value) : base(value) { } - } + public int X { get; } + public int Y { get; } + } - private record LabeledPoint : ValueObject + private sealed record PointLabel : SingleValueObject + { + public PointLabel(string value) : base(value) { } + } + + private record LabeledPoint : ValueObject + { + public LabeledPoint(string name, PointLabel label) { - public LabeledPoint(string name, PointLabel label) - { - Name = name; - Label = label; - } - - public string Name { get; } - public PointLabel Label { get; } + Name = name; + Label = label; } - private record MutablePoint : ValueObject - { - public MutablePoint() { } + public string Name { get; } + public PointLabel Label { get; } + } - public int X { get; set; } - public int Y { get; set; } - } + private record MutablePoint : ValueObject + { + public MutablePoint() { } + + public int X { get; set; } + public int Y { get; set; } + } - private record NoSuitableCtorPoint : ValueObject + private record NoSuitableCtorPoint : ValueObject + { + public NoSuitableCtorPoint(string a, string b, string c = null) { - public NoSuitableCtorPoint(string a, string b, string c = null) - { - A = a; - B = b; - } - - public string A { get; } - public string B { get; } + A = a; + B = b; } + + public string A { get; } + public string B { get; } } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs index 4d485bd7..5b145ef9 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs @@ -4,61 +4,60 @@ using Savvyio.Assets.Domain; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Domain +namespace Savvyio.Extensions.Newtonsoft.Json.Domain; + +public class DomainTest : Test { - public class DomainTest : Test + public DomainTest(ITestOutputHelper output) : base(output) { - public DomainTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Coordinates_ShouldBeAbleToBothSerializeAndDeserialize() - { - var sut = new Coordinates(10.1, 10.2); + [Fact] + public void Coordinates_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new Coordinates(10.1, 10.2); - var json = new NewtonsoftJsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); + var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); + } - [Fact] - public void Timestamp_ShouldBeAbleToBothSerializeAndDeserialize() + [Fact] + public void Timestamp_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new Timestamp(DateTimeOffset.UtcNow) { - var sut = new Timestamp(DateTimeOffset.UtcNow) - { - IsDaylightSavingTime = false, - TimeZone = "Europe/Berlin" - }; + IsDaylightSavingTime = false, + TimeZone = "Europe/Berlin" + }; - var json = new NewtonsoftJsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); + var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); + } - [Fact] - public void PlatformProviderId_ShouldBeAbleToBothSerializeAndDeserialize() - { - var sut = new PlatformProviderId(Guid.NewGuid()); + [Fact] + public void PlatformProviderId_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new PlatformProviderId(Guid.NewGuid()); - var json = new NewtonsoftJsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); + var rehydrated = new NewtonsoftJsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs index fee98665..7606a17d 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs @@ -9,80 +9,79 @@ using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.CloudEvents.Cryptography; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent() + .SignCloudEvent(NewtonsoftJsonMarshaller.Default, o => { - } + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - [Fact] - public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + TestOutput.WriteLine(jsonString); + + sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + var signatureException = Assert.Throws(() => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent() - .SignCloudEvent(NewtonsoftJsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - - var signatureException = Assert.Throws(() => - { - sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - - var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"049ca36b460e2ac4ee002c37e4c34b7963d9db1b14e1ff150eb8acbd7d7b8f6f"}""", jsonString); - } - - [Fact] - public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + + var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"049ca36b460e2ac4ee002c37e4c34b7963d9db1b14e1ff150eb8acbd7d7b8f6f"}""", jsonString); + } + + [Fact] + public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent() + .SignCloudEvent(NewtonsoftJsonMarshaller.Default, o => + { + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + + TestOutput.WriteLine(jsonString); + + sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + var signatureException = Assert.Throws(() => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent() - .SignCloudEvent(NewtonsoftJsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - - var signatureException = Assert.Throws(() => - { - sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - - var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"049ca36b460e2ac4ee002c37e4c34b7963d9db1b14e1ff150eb8acbd7d7b8f6f"}""", jsonString); - } + sut2.CheckCloudEventSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the cloud event does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + + var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"049ca36b460e2ac4ee002c37e4c34b7963d9db1b14e1ff150eb8acbd7d7b8f6f"}""", jsonString); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs index 3872f12b..eda2e3b7 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs @@ -8,35 +8,35 @@ using Savvyio.EventDriven.Messaging.CloudEvents; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.CloudEvents +namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.CloudEvents; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent(); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent(); - var json = new NewtonsoftJsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); + var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal(""" + Assert.Equal(""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -54,29 +54,29 @@ public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_U "specversion": "1.0" } """.ReplaceLineEndings(), jsonString); - } + } - [Fact] - public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utcNow = DateTime.UtcNow; + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }).ToCloudEvent(); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }).ToCloudEvent(); - var json = new NewtonsoftJsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); + var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -94,27 +94,26 @@ public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_U "specversion": "1.0" } """.ReplaceLineEndings(), jsonString); - } + } - [Fact] - public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_ExtensionAttributes_UsingInterface() + [Fact] + public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_ExtensionAttributes_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent(); - sut2["tenant"] = "acme"; - sut2["sequence"] = 42; - - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var sut3 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - - Assert.Equal("acme", sut3["tenant"]); - Assert.Equal(42L, sut3["sequence"]); - Assert.Equivalent(sut2.Data, sut3.Data, true); - } + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent(); + sut2["tenant"] = "acme"; + sut2["sequence"] = 42; + + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var sut3 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + + Assert.Equal("acme", sut3["tenant"]); + Assert.Equal(42L, sut3["sequence"]); + Assert.Equivalent(sut2.Data, sut3.Data, true); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs index 908ad419..51e043b4 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs @@ -8,76 +8,75 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.Cryptography +namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging.Cryptography; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(NewtonsoftJsonMarshaller.Default, o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(NewtonsoftJsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var signatureException = Assert.Throws(() => - { - sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + var signatureException = Assert.Throws(() => + { + sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"cf6710e4fc2877c87630fe94956a899240bfc7fdb1d6a0bb12446bd77890c448"}""", jsonString); - } + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"cf6710e4fc2877c87630fe94956a899240bfc7fdb1d6a0bb12446bd77890c448"}""", jsonString); + } - [Fact] - public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(NewtonsoftJsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(NewtonsoftJsonMarshaller.Default, o => + { + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + var json = NewtonsoftJsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var signatureException = Assert.Throws(() => - { - sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + var signatureException = Assert.Throws(() => + { + sut2.CheckSignature(NewtonsoftJsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); + var sut4 = NewtonsoftJsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"cf6710e4fc2877c87630fe94956a899240bfc7fdb1d6a0bb12446bd77890c448"}""", jsonString); - } + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"cf6710e4fc2877c87630fe94956a899240bfc7fdb1d6a0bb12446bd77890c448"}""", jsonString); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs index 80a45f27..b564f864 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs @@ -8,35 +8,35 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging +namespace Savvyio.Extensions.Newtonsoft.Json.EventDriven.Messaging; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }); - var json = new NewtonsoftJsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); + var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal(""" + Assert.Equal(""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -53,29 +53,29 @@ public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface } } """.ReplaceLineEndings(), jsonString); - } + } - [Fact] - public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utcNow = DateTime.UtcNow; + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }); - var json = new NewtonsoftJsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new NewtonsoftJsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); + var sut4 = new NewtonsoftJsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -92,6 +92,5 @@ public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteT } } """.ReplaceLineEndings(), jsonString); - } } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonConverterExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonConverterExtensionsTest.cs index 548aa60a..76998207 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonConverterExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonConverterExtensionsTest.cs @@ -5,46 +5,45 @@ using Savvyio.Extensions.Newtonsoft.Json.Converters; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +public class JsonConverterExtensionsTest : Test { - public class JsonConverterExtensionsTest : Test + public JsonConverterExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void JsonConverterExtensions_ShouldAddExpectedConverters() { - public JsonConverterExtensionsTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void JsonConverterExtensions_ShouldAddExpectedConverters() - { - ICollection sut = new List(); - - var chained = sut.AddValueObjectConverter() - .AddAggregateRootConverter() - .AddMetadataDictionaryConverter() - .AddRequestConverter() - .AddMessageConverter() - .AddSingleValueObjectConverter(); - - Assert.Same(sut, chained); - Assert.Contains(sut, c => c is ValueObjectConverter); - Assert.Contains(sut, c => c is AggregateRootConverter); - Assert.Contains(sut, c => c is RequestConverter); - Assert.Contains(sut, c => c is MessageConverter); - Assert.Contains(sut, c => c is SingleValueObjectConverter); - Assert.Equal(6, sut.Count); - } - - [Fact] - public void AddMetadataDictionaryConverter_ShouldDeserializeMetadataDictionary() - { - var settings = new JsonSerializerSettings(); - settings.Converters.AddMetadataDictionaryConverter(); - - var sut = JsonConvert.DeserializeObject("{\"memberType\":\"custom\",\"attempts\":42}", settings); - - Assert.IsType(sut); - Assert.Equal("custom", sut["memberType"]); - Assert.Equal(42L, sut["attempts"]); - } + ICollection sut = new List(); + + var chained = sut.AddValueObjectConverter() + .AddAggregateRootConverter() + .AddMetadataDictionaryConverter() + .AddRequestConverter() + .AddMessageConverter() + .AddSingleValueObjectConverter(); + + Assert.Same(sut, chained); + Assert.Contains(sut, c => c is ValueObjectConverter); + Assert.Contains(sut, c => c is AggregateRootConverter); + Assert.Contains(sut, c => c is RequestConverter); + Assert.Contains(sut, c => c is MessageConverter); + Assert.Contains(sut, c => c is SingleValueObjectConverter); + Assert.Equal(6, sut.Count); + } + + [Fact] + public void AddMetadataDictionaryConverter_ShouldDeserializeMetadataDictionary() + { + var settings = new JsonSerializerSettings(); + settings.Converters.AddMetadataDictionaryConverter(); + + var sut = JsonConvert.DeserializeObject("{\"memberType\":\"custom\",\"attempts\":42}", settings); + + Assert.IsType(sut); + Assert.Equal("custom", sut["memberType"]); + Assert.Equal(42L, sut["attempts"]); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonSerializerExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonSerializerExtensionsTest.cs index e6d849e1..7dcdbfcd 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonSerializerExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/JsonSerializerExtensionsTest.cs @@ -3,36 +3,35 @@ using Newtonsoft.Json.Serialization; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +public class JsonSerializerExtensionsTest : Test { - public class JsonSerializerExtensionsTest : Test + public JsonSerializerExtensionsTest(ITestOutputHelper output) : base(output) { - public JsonSerializerExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void JsonSerializerExtensions_ShouldResolveKeysWithDefaultNamingStrategy() - { - var sut = JsonSerializer.CreateDefault(); + [Fact] + public void JsonSerializerExtensions_ShouldResolveKeysWithDefaultNamingStrategy() + { + var sut = JsonSerializer.CreateDefault(); - Assert.Equal("MemberType", sut.ResolvePropertyKeyByConvention("MemberType")); - Assert.Equal("MemberType", sut.ResolveDictionaryKeyByConvention("MemberType")); - } + Assert.Equal("MemberType", sut.ResolvePropertyKeyByConvention("MemberType")); + Assert.Equal("MemberType", sut.ResolveDictionaryKeyByConvention("MemberType")); + } - [Fact] - public void JsonSerializerExtensions_ShouldResolveKeysWithCamelCaseNamingStrategy() + [Fact] + public void JsonSerializerExtensions_ShouldResolveKeysWithCamelCaseNamingStrategy() + { + var sut = JsonSerializer.CreateDefault(new JsonSerializerSettings { - var sut = JsonSerializer.CreateDefault(new JsonSerializerSettings + ContractResolver = new DefaultContractResolver { - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new CamelCaseNamingStrategy() - } - }); + NamingStrategy = new CamelCaseNamingStrategy() + } + }); - Assert.Equal("memberType", sut.ResolvePropertyKeyByConvention("MemberType")); - Assert.Equal("MemberType", sut.ResolveDictionaryKeyByConvention("MemberType")); - } + Assert.Equal("memberType", sut.ResolvePropertyKeyByConvention("MemberType")); + Assert.Equal("MemberType", sut.ResolveDictionaryKeyByConvention("MemberType")); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs index 4aa2fd54..78966f5f 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs @@ -4,37 +4,36 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +public class MetadataDictionaryTest : Test { - public class MetadataDictionaryTest : Test + public MetadataDictionaryTest(ITestOutputHelper output) : base(output) { - public MetadataDictionaryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void MetadataDictionary_ShouldUseCustomConverter() + [Fact] + public void MetadataDictionary_ShouldUseCustomConverter() + { + var md = new MetadataDictionary() { - var md = new MetadataDictionary() - { - { "guid", $"{Guid.NewGuid()}" }, - { "int32", 2312313 }, - { "dateTime", DateTime.UtcNow } - }; + { "guid", $"{Guid.NewGuid()}" }, + { "int32", 2312313 }, + { "dateTime", DateTime.UtcNow } + }; - var json = NewtonsoftJsonFormatter.SerializeObject(md); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = NewtonsoftJsonFormatter.SerializeObject(md); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var mdRehydrated = NewtonsoftJsonFormatter.DeserializeObject(json, o => - { - o.Settings.Converters - .AddMessageConverter() - .AddMetadataDictionaryConverter(); - }); + var mdRehydrated = NewtonsoftJsonFormatter.DeserializeObject(json, o => + { + o.Settings.Converters + .AddMessageConverter() + .AddMetadataDictionaryConverter(); + }); - Assert.Equivalent(md, mdRehydrated, true); - } + Assert.Equivalent(md, mdRehydrated, true); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/NewtonsoftJsonMarshallerTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/NewtonsoftJsonMarshallerTest.cs index cd96cf9e..345cf6ed 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/NewtonsoftJsonMarshallerTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/NewtonsoftJsonMarshallerTest.cs @@ -5,46 +5,45 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json +namespace Savvyio.Extensions.Newtonsoft.Json; + +public class NewtonsoftJsonMarshallerTest : Test { - public class NewtonsoftJsonMarshallerTest : Test + public NewtonsoftJsonMarshallerTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void NewtonsoftJsonMarshaller_Default_ShouldUseCompactFormatting() + { + using var stream = NewtonsoftJsonMarshaller.Default.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com")); + using var reader = new StreamReader(stream); + var json = reader.ReadToEnd(); + + Assert.DoesNotContain(Environment.NewLine, json); + } + + [Fact] + public void NewtonsoftJsonMarshaller_Create_ShouldHonorConfiguredFormatting() { - public NewtonsoftJsonMarshallerTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void NewtonsoftJsonMarshaller_Default_ShouldUseCompactFormatting() - { - using var stream = NewtonsoftJsonMarshaller.Default.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com")); - using var reader = new StreamReader(stream); - var json = reader.ReadToEnd(); - - Assert.DoesNotContain(Environment.NewLine, json); - } - - [Fact] - public void NewtonsoftJsonMarshaller_Create_ShouldHonorConfiguredFormatting() - { - var sut = NewtonsoftJsonMarshaller.Create(o => o.Settings.Formatting = Formatting.Indented); - - using var stream = sut.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com")); - using var reader = new StreamReader(stream); - var json = reader.ReadToEnd(); - - Assert.Contains(Environment.NewLine, json); - } - - [Fact] - public void NewtonsoftJsonMarshaller_ShouldRoundtripUsingTypeBasedMethods() - { - var marshaller = new NewtonsoftJsonMarshaller(); - using var stream = marshaller.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com"), typeof(CreateMemberCommand)); - - var sut = marshaller.Deserialize(stream, typeof(CreateMemberCommand)); - - Assert.IsType(sut); - Assert.Equal("Jane Doe", ((CreateMemberCommand)sut).Name); - } + var sut = NewtonsoftJsonMarshaller.Create(o => o.Settings.Formatting = Formatting.Indented); + + using var stream = sut.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com")); + using var reader = new StreamReader(stream); + var json = reader.ReadToEnd(); + + Assert.Contains(Environment.NewLine, json); + } + + [Fact] + public void NewtonsoftJsonMarshaller_ShouldRoundtripUsingTypeBasedMethods() + { + var marshaller = new NewtonsoftJsonMarshaller(); + using var stream = marshaller.Serialize(new CreateMemberCommand("Jane Doe", 21, "jd@office.com"), typeof(CreateMemberCommand)); + + var sut = marshaller.Deserialize(stream, typeof(CreateMemberCommand)); + + Assert.IsType(sut); + Assert.Equal("Jane Doe", ((CreateMemberCommand)sut).Name); } } diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/RequestConverterTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/RequestConverterTest.cs index 0eeecf6c..7f9455d4 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/RequestConverterTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/RequestConverterTest.cs @@ -6,80 +6,79 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Extensions.Newtonsoft.Json.Converters +namespace Savvyio.Extensions.Newtonsoft.Json.Converters; + +public class RequestConverterTest : Test { - public class RequestConverterTest : Test + public RequestConverterTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void RequestConverter_ShouldExposeReadOnlyCapabilities() + { + var sut = new RequestConverter(); + + Assert.False(sut.CanWrite); + Assert.True(sut.CanConvert(typeof(CreateMemberCommand))); + Assert.False(sut.CanConvert(typeof(string))); + } + + [Fact] + public void RequestConverter_ShouldThrowWhenWritingJson() { - public RequestConverterTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void RequestConverter_ShouldExposeReadOnlyCapabilities() - { - var sut = new RequestConverter(); - - Assert.False(sut.CanWrite); - Assert.True(sut.CanConvert(typeof(CreateMemberCommand))); - Assert.False(sut.CanConvert(typeof(string))); - } - - [Fact] - public void RequestConverter_ShouldThrowWhenWritingJson() - { - var sut = new RequestConverter(); - using var writer = new JsonTextWriter(new StringWriter()); - - Assert.Throws(() => sut.WriteJson(writer, new CreateMemberCommand("Jane Doe", 21, "jd@office.com"), JsonSerializer.CreateDefault())); - } - - [Fact] - public void RequestConverter_ShouldRehydrateAutoPropertyRequests() - { - var settings = new JsonSerializerSettings(); - settings.Converters.Add(new RequestConverter()); - - var sut = JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\",\"age\":21,\"emailAddress\":\"jd@office.com\"}", settings); - - Assert.NotNull(sut); - Assert.Equal("Jane Doe", sut.Name); - Assert.Equal((byte)21, sut.Age); - Assert.Equal("jd@office.com", sut.EmailAddress); - } - - [Fact] - public void RequestConverter_ShouldRehydrateWritableProperties() - { - var settings = new JsonSerializerSettings(); - settings.Converters.Add(new RequestConverter()); - - var sut = JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\"}", settings); - - Assert.NotNull(sut); - Assert.Equal("Jane Doe", sut.Name); - } - - [Fact] - public void RequestConverter_ShouldFailWhenNoSupportedBackingFieldExists() - { - var settings = new JsonSerializerSettings(); - settings.Converters.Add(new RequestConverter()); - - var ex = Assert.Throws(() => JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\"}", settings)); - - Assert.StartsWith("This deserializer only supports rehydration", ex.Message); - } - - private sealed class WritableRequest : IRequest - { - public string Name { get; set; } - } - - private sealed class UnsupportedRequest : IRequest - { - private readonly string _name = string.Empty; - - public string Name => _name; - } + var sut = new RequestConverter(); + using var writer = new JsonTextWriter(new StringWriter()); + + Assert.Throws(() => sut.WriteJson(writer, new CreateMemberCommand("Jane Doe", 21, "jd@office.com"), JsonSerializer.CreateDefault())); + } + + [Fact] + public void RequestConverter_ShouldRehydrateAutoPropertyRequests() + { + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new RequestConverter()); + + var sut = JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\",\"age\":21,\"emailAddress\":\"jd@office.com\"}", settings); + + Assert.NotNull(sut); + Assert.Equal("Jane Doe", sut.Name); + Assert.Equal((byte)21, sut.Age); + Assert.Equal("jd@office.com", sut.EmailAddress); + } + + [Fact] + public void RequestConverter_ShouldRehydrateWritableProperties() + { + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new RequestConverter()); + + var sut = JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\"}", settings); + + Assert.NotNull(sut); + Assert.Equal("Jane Doe", sut.Name); + } + + [Fact] + public void RequestConverter_ShouldFailWhenNoSupportedBackingFieldExists() + { + var settings = new JsonSerializerSettings(); + settings.Converters.Add(new RequestConverter()); + + var ex = Assert.Throws(() => JsonConvert.DeserializeObject("{\"name\":\"Jane Doe\"}", settings)); + + Assert.StartsWith("This deserializer only supports rehydration", ex.Message); + } + + private sealed class WritableRequest : IRequest + { + public string Name { get; set; } + } + + private sealed class UnsupportedRequest : IRequest + { + private readonly string _name = string.Empty; + + public string Name => _name; } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs index d462cf82..b4972970 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,20 +1,19 @@ using Savvyio.Commands; -namespace Savvyio.Extensions.QueueStorage.Assets +namespace Savvyio.Extensions.QueueStorage.Assets; + +internal record CreateMemberCommand : Command { - internal record CreateMemberCommand : Command + public CreateMemberCommand(string name, byte age, string emailAddress) { - public CreateMemberCommand(string name, byte age, string emailAddress) - { - Name = name; - Age = age; - EmailAddress = emailAddress; - } + Name = name; + Age = age; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public byte Age { get; } + public byte Age { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs index 89cac802..fd2a98ba 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs @@ -1,18 +1,17 @@ -namespace Savvyio.Extensions.QueueStorage.Assets +namespace Savvyio.Extensions.QueueStorage.Assets; + +public struct WindowsDebug { - public struct WindowsDebug - { - } +} - public struct WindowsRelease - { - } +public struct WindowsRelease +{ +} - public struct LinuxDebug - { - } +public struct LinuxDebug +{ +} - public struct LinuxRelease - { - } +public struct LinuxRelease +{ } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs index 2d0acd98..f37fc726 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs @@ -1,17 +1,16 @@ using Savvyio.EventDriven; -namespace Savvyio.Extensions.QueueStorage.Assets +namespace Savvyio.Extensions.QueueStorage.Assets; + +public record MemberCreated : IntegrationEvent { - public record MemberCreated : IntegrationEvent + public MemberCreated(string name, string emailAddress) { - public MemberCreated(string name, string emailAddress) - { - Name = name; - EmailAddress = emailAddress; - } + Name = name; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs index 7e1004fb..ef7d0a71 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs @@ -26,153 +26,152 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.QueueStorage.Commands +namespace Savvyio.Extensions.QueueStorage.Commands; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AzureCommandQueueJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AzureCommandQueueJsonSerializerContextTest : HostTest + private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "windows"; + private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly AzureCommandQueue _queue; + private readonly IMarshaller _marshaller; + + public AzureCommandQueueJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "windows"; - private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly AzureCommandQueue _queue; - private readonly IMarshaller _marshaller; + _queue = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AzureCommandQueueJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _queue = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + IMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); + if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } + } - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - IMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); - if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } - } + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - } + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members/signed".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members/signed".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + ISignedMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - ISignedMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; - sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } - } - - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; + sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } } - [Fact, Priority(4)] - public async Task SendAsync_CreateMemberCommand_HundredTimes() + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } + + [Fact, Priority(4)] + public async Task SendAsync_CreateMemberCommand_HundredTimes() + { + var messages = Generate.RangeOf(100, i => { - 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)); - Comparer.Add(message); - return message; - }).ToList(); + 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)); + Comparer.Add(message); + return message; + }).ToList(); - var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); + var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); - TestOutput.WriteLine(profiler.ToString()); - } + TestOutput.WriteLine(profiler.ToString()); + } - [Fact, Priority(5)] - public async Task ReceiveAsync_CreateMemberCommand_All() - { - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; - var realizedCommands = new List>(); - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + [Fact, Priority(5)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; + var realizedCommands = new List>(); + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - while (realizedCommands.Count < sut1.Count) + while (realizedCommands.Count < sut1.Count) + { + realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).Select(message => { - realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).Select(message => - { - message.AcknowledgeAsync(); - return message; - }).ToListAsync(ct).ConfigureAwait(false)); - } - - TestOutput.WriteLine(realizedCommands.Count.ToString()); - TestOutput.WriteLines(realizedCommands.Take(10)); - - Assert.Equivalent(sut1.Count, realizedCommands.Count); - Assert.Equivalent(sut1, realizedCommands); - Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + message.AcknowledgeAsync(); + return message; + }).ToListAsync(ct).ConfigureAwait(false)); } - public override void ConfigureServices(IServiceCollection services) + TestOutput.WriteLine(realizedCommands.Count.ToString()); + TestOutput.WriteLines(realizedCommands.Take(10)); + + Assert.Equivalent(sut1.Count, realizedCommands.Count); + Assert.Equivalent(sut1, realizedCommands); + Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller() + .AddConfiguredOptions(o => o.Settings.PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower); + services.AddAzureCommandQueue(o => { - services.AddMarshaller() - .AddConfiguredOptions(o => o.Settings.PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower); - services.AddAzureCommandQueue(o => + o.QueueName = $"savvyio-commands-{Platform}-{BuildType}"; + o.ConnectionString = Configuration["Azure:Storage:QueueConnectionString"]; + o.PostConfigureClient(client => { - o.QueueName = $"savvyio-commands-{Platform}-{BuildType}"; - o.ConnectionString = Configuration["Azure:Storage:QueueConnectionString"]; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); + client.CreateIfNotExists(); + client.ClearMessages(); }); - } + }); } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs index fe936011..9bd0f8d5 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -26,153 +26,152 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.QueueStorage.Commands +namespace Savvyio.Extensions.QueueStorage.Commands; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AzureCommandQueueNewtonsoftJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AzureCommandQueueNewtonsoftJsonSerializerContextTest : HostTest + private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "windows"; + private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly AzureCommandQueue _queue; + private readonly IMarshaller _marshaller; + + public AzureCommandQueueNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "windows"; - private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly AzureCommandQueue _queue; - private readonly IMarshaller _marshaller; + _queue = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AzureCommandQueueNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _queue = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + IMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); + if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } + } - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - IMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); - if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } - } + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - } + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members/signed".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members/signed".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + ISignedMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - ISignedMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; - sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } - } - - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; + sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + if (sut2 != null) { await sut2.AcknowledgeAsync().ConfigureAwait(false); } } - [Fact, Priority(4)] - public async Task SendAsync_CreateMemberCommand_HundredTimes() + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } + + [Fact, Priority(4)] + public async Task SendAsync_CreateMemberCommand_HundredTimes() + { + var messages = Generate.RangeOf(100, i => { - 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)); - Comparer.Add(message); - return message; - }).ToList(); + 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)); + Comparer.Add(message); + return message; + }).ToList(); - var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); + var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); - TestOutput.WriteLine(profiler.ToString()); - } + TestOutput.WriteLine(profiler.ToString()); + } - [Fact, Priority(5)] - public async Task ReceiveAsync_CreateMemberCommand_All() - { - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; - var realizedCommands = new List>(); - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + [Fact, Priority(5)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; + var realizedCommands = new List>(); + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - while (realizedCommands.Count < sut1.Count) + while (realizedCommands.Count < sut1.Count) + { + realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).Select(message => { - realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).Select(message => - { - message.AcknowledgeAsync(); - return message; - }).ToListAsync(ct).ConfigureAwait(false)); - } - - TestOutput.WriteLine(realizedCommands.Count.ToString()); - TestOutput.WriteLines(realizedCommands.Take(10)); - - Assert.Equivalent(sut1.Count, realizedCommands.Count); - Assert.Equivalent(sut1, realizedCommands); - Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + message.AcknowledgeAsync(); + return message; + }).ToListAsync(ct).ConfigureAwait(false)); } - public override void ConfigureServices(IServiceCollection services) + TestOutput.WriteLine(realizedCommands.Count.ToString()); + TestOutput.WriteLines(realizedCommands.Take(10)); + + Assert.Equivalent(sut1.Count, realizedCommands.Count); + Assert.Equivalent(sut1, realizedCommands); + Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller() + .AddConfiguredOptions(o => o.Settings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new KebabCaseNamingStrategy() { ProcessDictionaryKeys = false } }); + services.AddAzureCommandQueue(o => { - services.AddMarshaller() - .AddConfiguredOptions(o => o.Settings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new KebabCaseNamingStrategy() { ProcessDictionaryKeys = false } }); - services.AddAzureCommandQueue(o => + o.QueueName = $"newtonsoft-savvyio-commands-{Platform}-{BuildType}"; + o.ConnectionString = Configuration["Azure:Storage:QueueConnectionString"]; + o.PostConfigureClient(client => { - o.QueueName = $"newtonsoft-savvyio-commands-{Platform}-{BuildType}"; - o.ConnectionString = Configuration["Azure:Storage:QueueConnectionString"]; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); + client.CreateIfNotExists(); + client.ClearMessages(); }); - } + }); } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs index c1de4b52..4bfc1a68 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs @@ -28,323 +28,322 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AzureEventBusJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AzureEventBusJsonSerializerContextTest : HostTest - { - private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "win"; - private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly AzureEventBus _bus; - private readonly IMarshaller _marshaller; + private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "win"; + private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly AzureEventBus _bus; + private readonly IMarshaller _marshaller; - public AzureEventBusJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _bus = ResolveEventBus(fixture); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + public AzureEventBusJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) + { + _bus = ResolveEventBus(fixture); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - private static AzureEventBus ResolveEventBus(ManagedHostFixture fixture) + private static AzureEventBus ResolveEventBus(ManagedHostFixture fixture) + { + return Platform switch { - return Platform switch + "win" => BuildType switch { - "win" => BuildType switch - { - "debug" => fixture.Host.Services.GetRequiredService>(), - "release" => fixture.Host.Services.GetRequiredService>(), - _ => throw new NotSupportedException() - }, - "linux" => BuildType switch - { - "debug" => fixture.Host.Services.GetRequiredService>(), - "release" => fixture.Host.Services.GetRequiredService>(), - _ => throw new NotSupportedException() - }, + "debug" => fixture.Host.Services.GetRequiredService>(), + "release" => fixture.Host.Services.GetRequiredService>(), _ => throw new NotSupportedException() - }; - } + }, + "linux" => BuildType switch + { + "debug" => fixture.Host.Services.GetRequiredService>(), + "release" => fixture.Host.Services.GetRequiredService>(), + _ => throw new NotSupportedException() + }, + _ => throw new NotSupportedException() + }; + } - [Fact, Priority(0)] - public async Task PublishAsync_MemberCreated_OneTime() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{BuildType}.updated-event"); + [Fact, Priority(0)] + public async Task PublishAsync_MemberCreated_OneTime() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{BuildType}.updated-event"); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(_marshaller.Serialize(sut3.ToCloudEvent()).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(_marshaller.Serialize(sut3.ToCloudEvent()).ToEncodedString(o => o.LeaveOpen = true)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(1)] - public async Task SubscribeAsync_MemberCreated_OneTime() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{BuildType}.updated-event")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + [Fact, Priority(1)] + public async Task SubscribeAsync_MemberCreated_OneTime() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{BuildType}.updated-event")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - while (!cancellationToken.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{BuildType}.updated-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }, o => o.CancellationToken = cancellationToken.Token).ConfigureAwait(false); - } - - Assert.Equal(1, handlerInvocations); + if (!sut2.Type.Contains($"{BuildType}.updated-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }, o => o.CancellationToken = cancellationToken.Token).ConfigureAwait(false); } - [Fact, Priority(2)] - public async Task PublishAsync_MemberCreated_OneTime_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(2)] + public async Task PublishAsync_MemberCreated_OneTime_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(3)] - public async Task SubscribeAsync_MemberCreated_OneTime_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + await _bus.PublishAsync(sut3); + } - while (!cancellationToken.IsCancellationRequested) + [Fact, Priority(3)] + public async Task SubscribeAsync_MemberCreated_OneTime_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")) { return Task.CompletedTask; } - ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - } - Assert.Equal(1, handlerInvocations); + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")) { return Task.CompletedTask; } + ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }).ConfigureAwait(false); } + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(4)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.cloud-event").ToCloudEvent(); + [Fact, Priority(4)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.cloud-event").ToCloudEvent(); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(5)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")).Single() as ICloudEvent; - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + [Fact, Priority(5)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")).Single() as ICloudEvent; + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - while (!cancellationToken.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - - } - Assert.Equal(1, handlerInvocations); - } + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }).ConfigureAwait(false); - [Fact, Priority(6)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + } + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(6)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(7)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + await _bus.PublishAsync(sut3); + } - while (!cancellationToken.IsCancellationRequested) - { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } - ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - } - Assert.Equal(1, handlerInvocations); - } + [Fact, Priority(7)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - [Fact, Priority(8)] - public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + while (!cancellationToken.IsCancellationRequested) { - var messages = Generate.RangeOf(100, _ => + await _bus.SubscribeAsync((sut2, _) => { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}.{Platform}.{BuildType}"); - }); - - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return _bus.PublishAsync(message, o => o.CancellationToken = token); + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } + ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; }).ConfigureAwait(false); } + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(9)] - public async Task SubscribeAsync_MemberCreated_All() + [Fact, Priority(8)] + public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + { + var messages = Generate.RangeOf(100, _ => { - var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{Platform}.{BuildType}")).ToList(); - var sut2 = new List>(); - var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - - await _bus.SubscribeAsync((message, _) => - { - if (!message.Type.Contains($"{Platform}.{BuildType}")) { return Task.CompletedTask; } - sut2.Add(message); - message.AcknowledgeAsync(); - return Task.CompletedTask; - }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}.{Platform}.{BuildType}"); + }); - TestOutput.WriteLine(sut2.Count.ToString()); - TestOutput.WriteLines(sut2.Take(10)); + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + Comparer.Add(message); + return _bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + } - Assert.Equivalent(sut1.Count, sut2.Count); - Assert.Equivalent(sut1, sut2); - Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + [Fact, Priority(9)] + public async Task SubscribeAsync_MemberCreated_All() + { + var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{Platform}.{BuildType}")).ToList(); + var sut2 = new List>(); + var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - public override void ConfigureServices(IServiceCollection services) + await _bus.SubscribeAsync((message, _) => { - var queueName = $"savvyio-events-{Platform}-{BuildType}"; - var queueConnection = Configuration["Azure:Storage:QueueConnectionString"]; + if (!message.Type.Contains($"{Platform}.{BuildType}")) { return Task.CompletedTask; } + sut2.Add(message); + message.AcknowledgeAsync(); + return Task.CompletedTask; + }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + + TestOutput.WriteLine(sut2.Count.ToString()); + TestOutput.WriteLines(sut2.Take(10)); + + Assert.Equivalent(sut1.Count, sut2.Count); + Assert.Equivalent(sut1, sut2); + Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); + } - services.AddMarshaller(); + public override void ConfigureServices(IServiceCollection services) + { + var queueName = $"savvyio-events-{Platform}-{BuildType}"; + var queueConnection = Configuration["Azure:Storage:QueueConnectionString"]; - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddMarshaller(); + + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://savvyio-events-win-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Windows:Debug:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://savvyio-events-win-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Windows:Debug:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://savvyio-events-win-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Windows:Release:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://savvyio-events-win-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Windows:Release:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://savvyio-events-linux-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Linux:Debug:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://savvyio-events-linux-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Linux:Debug:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://savvyio-events-linux-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Linux:Release:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); - } + }, o => + { + o.TopicEndpoint = "https://savvyio-events-linux-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:EventGrid:Linux:Release:Key"]!); + }); } } diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs index d98c493d..00e91c81 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs @@ -28,323 +28,322 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AzureEventBusNewtonsoftJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AzureEventBusNewtonsoftJsonSerializerContextTest : HostTest - { - private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "win"; - private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly AzureEventBus _bus; - private readonly IMarshaller _marshaller; + private static readonly string Platform = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "win"; + private static readonly string BuildType = typeof(AzureCommandQueue).Assembly.IsDebugBuild() ? "debug" : "release"; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly AzureEventBus _bus; + private readonly IMarshaller _marshaller; - public AzureEventBusNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _bus = ResolveEventBus(fixture); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + public AzureEventBusNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) + { + _bus = ResolveEventBus(fixture); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - private static AzureEventBus ResolveEventBus(ManagedHostFixture fixture) + private static AzureEventBus ResolveEventBus(ManagedHostFixture fixture) + { + return Platform switch { - return Platform switch + "win" => BuildType switch { - "win" => BuildType switch - { - "debug" => fixture.Host.Services.GetRequiredService>(), - "release" => fixture.Host.Services.GetRequiredService>(), - _ => throw new NotSupportedException() - }, - "linux" => BuildType switch - { - "debug" => fixture.Host.Services.GetRequiredService>(), - "release" => fixture.Host.Services.GetRequiredService>(), - _ => throw new NotSupportedException() - }, + "debug" => fixture.Host.Services.GetRequiredService>(), + "release" => fixture.Host.Services.GetRequiredService>(), _ => throw new NotSupportedException() - }; - } + }, + "linux" => BuildType switch + { + "debug" => fixture.Host.Services.GetRequiredService>(), + "release" => fixture.Host.Services.GetRequiredService>(), + _ => throw new NotSupportedException() + }, + _ => throw new NotSupportedException() + }; + } - [Fact, Priority(0)] - public async Task PublishAsync_MemberCreated_OneTime() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{BuildType}.updated-event"); + [Fact, Priority(0)] + public async Task PublishAsync_MemberCreated_OneTime() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{BuildType}.updated-event"); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(_marshaller.Serialize(sut3.ToCloudEvent()).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(_marshaller.Serialize(sut3.ToCloudEvent()).ToEncodedString(o => o.LeaveOpen = true)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(1)] - public async Task SubscribeAsync_MemberCreated_OneTime() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{BuildType}.updated-event")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + [Fact, Priority(1)] + public async Task SubscribeAsync_MemberCreated_OneTime() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{BuildType}.updated-event")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - while (!cancellationToken.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{BuildType}.updated-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }, o => o.CancellationToken = cancellationToken.Token).ConfigureAwait(false); - } - - Assert.Equal(1, handlerInvocations); + if (!sut2.Type.Contains($"{BuildType}.updated-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }, o => o.CancellationToken = cancellationToken.Token).ConfigureAwait(false); } - [Fact, Priority(2)] - public async Task PublishAsync_MemberCreated_OneTime_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(2)] + public async Task PublishAsync_MemberCreated_OneTime_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(3)] - public async Task SubscribeAsync_MemberCreated_OneTime_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + await _bus.PublishAsync(sut3); + } - while (!cancellationToken.IsCancellationRequested) + [Fact, Priority(3)] + public async Task SubscribeAsync_MemberCreated_OneTime_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")) { return Task.CompletedTask; } - ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - } - Assert.Equal(1, handlerInvocations); + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed")) { return Task.CompletedTask; } + ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }).ConfigureAwait(false); } + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(4)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.cloud-event").ToCloudEvent(); + [Fact, Priority(4)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.cloud-event").ToCloudEvent(); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(5)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")).Single() as ICloudEvent; - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + [Fact, Priority(5)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")).Single() as ICloudEvent; + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - while (!cancellationToken.IsCancellationRequested) + while (!cancellationToken.IsCancellationRequested) + { + await _bus.SubscribeAsync((sut2, _) => { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - - } - Assert.Equal(1, handlerInvocations); - } + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.cloud-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; + }).ConfigureAwait(false); - [Fact, Priority(6)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = "urn:member-events-one".ToUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + } + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(6)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = "urn:member-events-one".ToUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{Platform}.{BuildType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut3).ToEncodedString(o => o.LeaveOpen = true)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(7)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")).Single(); - var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); + await _bus.PublishAsync(sut3); + } - while (!cancellationToken.IsCancellationRequested) - { - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } - ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - sut2.AcknowledgeAsync(); - cancellationToken.Cancel(); - return Task.CompletedTask; - }).ConfigureAwait(false); - } - Assert.Equal(1, handlerInvocations); - } + [Fact, Priority(7)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")).Single(); + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)); - [Fact, Priority(8)] - public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + while (!cancellationToken.IsCancellationRequested) { - var messages = Generate.RangeOf(100, _ => + await _bus.SubscribeAsync((sut2, _) => { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}.{Platform}.{BuildType}"); - }); - - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return _bus.PublishAsync(message, o => o.CancellationToken = token); + if (!sut2.Type.Contains($"{Platform}.{BuildType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } + ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + sut2.AcknowledgeAsync(); + cancellationToken.Cancel(); + return Task.CompletedTask; }).ConfigureAwait(false); } + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(9)] - public async Task SubscribeAsync_MemberCreated_All() + [Fact, Priority(8)] + public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + { + var messages = Generate.RangeOf(100, _ => { - var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{Platform}.{BuildType}")).ToList(); - var sut2 = new List>(); - var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - - await _bus.SubscribeAsync((message, _) => - { - if (!message.Type.Contains($"{Platform}.{BuildType}")) { return Task.CompletedTask; } - sut2.Add(message); - message.AcknowledgeAsync(); - return Task.CompletedTask; - }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage("urn:member-events-many".ToUri(), $"{nameof(MemberCreated)}.{Platform}.{BuildType}"); + }); - TestOutput.WriteLine(sut2.Count.ToString()); - TestOutput.WriteLines(sut2.Take(10)); + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + Comparer.Add(message); + return _bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + } - Assert.Equivalent(sut1.Count, sut2.Count); - Assert.Equivalent(sut1, sut2); - Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + [Fact, Priority(9)] + public async Task SubscribeAsync_MemberCreated_All() + { + var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{Platform}.{BuildType}")).ToList(); + var sut2 = new List>(); + var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - public override void ConfigureServices(IServiceCollection services) + await _bus.SubscribeAsync((message, _) => { - var queueName = $"newtonsoft-savvyio-events-{Platform}-{BuildType}"; - var queueConnection = Configuration["Azure:Storage:QueueConnectionString"]; + if (!message.Type.Contains($"{Platform}.{BuildType}")) { return Task.CompletedTask; } + sut2.Add(message); + message.AcknowledgeAsync(); + return Task.CompletedTask; + }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + + TestOutput.WriteLine(sut2.Count.ToString()); + TestOutput.WriteLines(sut2.Take(10)); + + Assert.Equivalent(sut1.Count, sut2.Count); + Assert.Equivalent(sut1, sut2); + Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); + } - services.AddMarshaller(); + public override void ConfigureServices(IServiceCollection services) + { + var queueName = $"newtonsoft-savvyio-events-{Platform}-{BuildType}"; + var queueConnection = Configuration["Azure:Storage:QueueConnectionString"]; - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddMarshaller(); + + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://newtonsoft-savvyio-events-win-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Windows:Debug:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://newtonsoft-savvyio-events-win-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Windows:Debug:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://newtonsoft-savvyio-events-win-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Windows:Release:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://newtonsoft-savvyio-events-win-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Windows:Release:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://newtonsoft-savvyio-events-linux-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Linux:Debug:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); + }, o => + { + o.TopicEndpoint = "https://newtonsoft-savvyio-events-linux-debug.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Linux:Debug:Key"]!); + }); - services.AddAzureEventBus(o => - { - o.QueueName = queueName; - o.ConnectionString = queueConnection; - o.PostConfigureClient(client => - { - client.CreateIfNotExists(); - client.ClearMessages(); - }); - }, o => + services.AddAzureEventBus(o => + { + o.QueueName = queueName; + o.ConnectionString = queueConnection; + o.PostConfigureClient(client => { - o.TopicEndpoint = "https://newtonsoft-savvyio-events-linux-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); - o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Linux:Release:Key"]!); + client.CreateIfNotExists(); + client.ClearMessages(); }); - } + }, o => + { + o.TopicEndpoint = "https://newtonsoft-savvyio-events-linux-release.swedencentral-1.eventgrid.azure.net/api/events".ToUri(); + o.KeyCredential = new AzureKeyCredential(Configuration["Azure:Newtonsoft:EventGrid:Linux:Release:Key"]!); + }); } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs index 7844d133..aec8217e 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs @@ -8,144 +8,143 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +public class AzureQueueOptionsTest : Test { - public class AzureQueueOptionsTest : Test + public AzureQueueOptionsTest(ITestOutputHelper output) : base(output) { - public AzureQueueOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_ShouldInitializeWithDefaultValues() - { - var options = new AzureQueueOptions(); - - Assert.NotNull(options.Credential); - Assert.IsType(options.Credential); - Assert.NotNull(options.Settings); - Assert.NotNull(options.ReceiveContext); - Assert.NotNull(options.SendContext); - Assert.Null(options.StorageAccountName); - Assert.Null(options.QueueName); - Assert.Null(options.SasCredential); - Assert.Null(options.StorageKeyCredential); - Assert.Null(options.ConnectionString); - } - - [Fact] - public void ValidateOptions_ShouldThrowException_WhenOptionsAreInvalid() - { - var options = new AzureQueueOptions(); + [Fact] + public void Constructor_ShouldInitializeWithDefaultValues() + { + var options = new AzureQueueOptions(); + + Assert.NotNull(options.Credential); + Assert.IsType(options.Credential); + Assert.NotNull(options.Settings); + Assert.NotNull(options.ReceiveContext); + Assert.NotNull(options.SendContext); + Assert.Null(options.StorageAccountName); + Assert.Null(options.QueueName); + Assert.Null(options.SasCredential); + Assert.Null(options.StorageKeyCredential); + Assert.Null(options.ConnectionString); + } - Assert.Throws(() => options.ValidateOptions()); + [Fact] + public void ValidateOptions_ShouldThrowException_WhenOptionsAreInvalid() + { + var options = new AzureQueueOptions(); - options.ConnectionString = "DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=testkey;EndpointSuffix=core.windows.net"; - options.QueueName = "testqueue"; - options.ValidateOptions(); // Should not throw + Assert.Throws(() => options.ValidateOptions()); - options.ConnectionString = null; - options.Credential = null; - options.SasCredential = null; - options.StorageKeyCredential = null; + options.ConnectionString = "DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=testkey;EndpointSuffix=core.windows.net"; + options.QueueName = "testqueue"; + options.ValidateOptions(); // Should not throw - Assert.Throws(() => options.ValidateOptions()); - } + options.ConnectionString = null; + options.Credential = null; + options.SasCredential = null; + options.StorageKeyCredential = null; - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenConnectionStringIsSetAndQueueNameIsNull() - { - var sut1 = new AzureQueueOptions - { - ConnectionString = "DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=testkey;EndpointSuffix=core.windows.net", - QueueName = null - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - TestOutput.WriteLine(sut2.Message); - - Assert.Equal($"{nameof(AzureQueueOptions.QueueName)} cannot be null, empty, or consists only of white-space when a {nameof(AzureQueueOptions.ConnectionString)} has been specified. (Expression '!string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.ConnectionString)}) && string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.QueueName)})')", sut2.Message); - Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenAllCredentialPropertiesAreNull() + Assert.Throws(() => options.ValidateOptions()); + } + + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenConnectionStringIsSetAndQueueNameIsNull() + { + var sut1 = new AzureQueueOptions { - var sut1 = new AzureQueueOptions - { - Credential = null, - SasCredential = null, - StorageKeyCredential = null - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - TestOutput.WriteLine(sut2.Message); - - Assert.Equal($"A credential type has to be specified for Azure authentication. (Expression '{nameof(AzureQueueOptions.Credential)} == null && {nameof(AzureQueueOptions.SasCredential)} == null && {nameof(AzureQueueOptions.StorageKeyCredential)} == null')", sut2.Message); - Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenStorageNameAndQueueNameIsNotSpecified() + ConnectionString = "DefaultEndpointsProtocol=https;AccountName=testaccount;AccountKey=testkey;EndpointSuffix=core.windows.net", + QueueName = null + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + TestOutput.WriteLine(sut2.Message); + + Assert.Equal($"{nameof(AzureQueueOptions.QueueName)} cannot be null, empty, or consists only of white-space when a {nameof(AzureQueueOptions.ConnectionString)} has been specified. (Expression '!string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.ConnectionString)}) && string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.QueueName)})')", sut2.Message); + Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } + + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenAllCredentialPropertiesAreNull() + { + var sut1 = new AzureQueueOptions { - var sut1 = new AzureQueueOptions(); - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + Credential = null, + SasCredential = null, + StorageKeyCredential = null + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + TestOutput.WriteLine(sut2.Message); + + Assert.Equal($"A credential type has to be specified for Azure authentication. (Expression '{nameof(AzureQueueOptions.Credential)} == null && {nameof(AzureQueueOptions.SasCredential)} == null && {nameof(AzureQueueOptions.StorageKeyCredential)} == null')", sut2.Message); + Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - TestOutput.WriteLine(sut2.Message); + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenStorageNameAndQueueNameIsNotSpecified() + { + var sut1 = new AzureQueueOptions(); + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + TestOutput.WriteLine(sut2.Message); + + Assert.Equal($"{nameof(AzureQueueOptions.StorageAccountName)} and {nameof(AzureQueueOptions.QueueName)} cannot be null, empty, or consists only of white-space characters. (Expression 'string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.StorageAccountName)}) && string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.QueueName)})')", sut2.Message); + Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - Assert.Equal($"{nameof(AzureQueueOptions.StorageAccountName)} and {nameof(AzureQueueOptions.QueueName)} cannot be null, empty, or consists only of white-space characters. (Expression 'string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.StorageAccountName)}) && string.IsNullOrWhiteSpace({nameof(AzureQueueOptions.QueueName)})')", sut2.Message); - Assert.Equal($"{nameof(AzureQueueOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + [Fact] + public void Credential_Setters_Should_Be_Mutually_Exclusive() + { + var sut = new AzureQueueOptions + { + SasCredential = new AzureSasCredential("sig") + }; + + Assert.NotNull(sut.SasCredential); + Assert.Null(sut.Credential); + Assert.Null(sut.StorageKeyCredential); + + sut.StorageKeyCredential = new StorageSharedKeyCredential("account", Convert.ToBase64String(new byte[32])); + Assert.NotNull(sut.StorageKeyCredential); + Assert.Null(sut.Credential); + Assert.Null(sut.SasCredential); + + sut.Credential = new DefaultAzureCredential(); + Assert.NotNull(sut.Credential); + Assert.Null(sut.SasCredential); + Assert.Null(sut.StorageKeyCredential); + } - [Fact] - public void Credential_Setters_Should_Be_Mutually_Exclusive() + [Fact] + public void PostConfigureClient_ShouldInvokeCallback() + { + var callbackInvoked = false; + var options = new AzureQueueOptions() { - var sut = new AzureQueueOptions - { - SasCredential = new AzureSasCredential("sig") - }; - - Assert.NotNull(sut.SasCredential); - Assert.Null(sut.Credential); - Assert.Null(sut.StorageKeyCredential); - - sut.StorageKeyCredential = new StorageSharedKeyCredential("account", Convert.ToBase64String(new byte[32])); - Assert.NotNull(sut.StorageKeyCredential); - Assert.Null(sut.Credential); - Assert.Null(sut.SasCredential); - - sut.Credential = new DefaultAzureCredential(); - Assert.NotNull(sut.Credential); - Assert.Null(sut.SasCredential); - Assert.Null(sut.StorageKeyCredential); - } - - [Fact] - public void PostConfigureClient_ShouldInvokeCallback() + ConnectionString = "UseDevelopmentStorage=true", + QueueName = "testqueue" + }; + + var returned = options.PostConfigureClient(c => { - var callbackInvoked = false; - var options = new AzureQueueOptions() - { - ConnectionString = "UseDevelopmentStorage=true", - QueueName = "testqueue" - }; - - var returned = options.PostConfigureClient(c => - { - callbackInvoked = true; - Assert.Equal("testqueue", c.Name); - }); - - _ = new AzureCommandQueue(JsonMarshaller.Default, options); - - Assert.Same(options, returned); - Assert.True(callbackInvoked); - } + callbackInvoked = true; + Assert.Equal("testqueue", c.Name); + }); + + _ = new AzureCommandQueue(JsonMarshaller.Default, options); + + Assert.Same(options, returned); + Assert.True(callbackInvoked); } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs index d3944872..9140e7af 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs @@ -2,73 +2,72 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +public class AzureQueueReceiveOptionsTest : Test { - public class AzureQueueReceiveOptionsTest : Test + public AzureQueueReceiveOptionsTest(ITestOutputHelper output) : base(output) { - public AzureQueueReceiveOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_ShouldInitializeWithDefaultValues() - { - var options = new AzureQueueOptions().ReceiveContext; + [Fact] + public void Constructor_ShouldInitializeWithDefaultValues() + { + var options = new AzureQueueOptions().ReceiveContext; - Assert.Equal(10, options.NumberOfMessagesToTakePerRequest); - Assert.Equal(TimeSpan.FromSeconds(30), options.VisibilityTimeout); - } + Assert.Equal(10, options.NumberOfMessagesToTakePerRequest); + Assert.Equal(TimeSpan.FromSeconds(30), options.VisibilityTimeout); + } - [Fact] - public void NumberOfMessagesToTakePerRequest_ShouldSetAndGetCorrectly() + [Fact] + public void NumberOfMessagesToTakePerRequest_ShouldSetAndGetCorrectly() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - ReceiveContext = { NumberOfMessagesToTakePerRequest = 5 } - }; + ReceiveContext = { NumberOfMessagesToTakePerRequest = 5 } + }; - Assert.Equal(5, options.ReceiveContext.NumberOfMessagesToTakePerRequest); - } + Assert.Equal(5, options.ReceiveContext.NumberOfMessagesToTakePerRequest); + } - [Fact] - public void NumberOfMessagesToTakePerRequest_ShouldClampToValidRange() + [Fact] + public void NumberOfMessagesToTakePerRequest_ShouldClampToValidRange() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - ReceiveContext = { NumberOfMessagesToTakePerRequest = 50 } - }; + ReceiveContext = { NumberOfMessagesToTakePerRequest = 50 } + }; - Assert.Equal(AzureQueueOptions.MaxNumberOfMessages, options.ReceiveContext.NumberOfMessagesToTakePerRequest); + Assert.Equal(AzureQueueOptions.MaxNumberOfMessages, options.ReceiveContext.NumberOfMessagesToTakePerRequest); - options.ReceiveContext.NumberOfMessagesToTakePerRequest = -1; + options.ReceiveContext.NumberOfMessagesToTakePerRequest = -1; - Assert.Equal(1, options.ReceiveContext.NumberOfMessagesToTakePerRequest); - } + Assert.Equal(1, options.ReceiveContext.NumberOfMessagesToTakePerRequest); + } - [Fact] - public void VisibilityTimeout_ShouldSetAndGetCorrectly() + [Fact] + public void VisibilityTimeout_ShouldSetAndGetCorrectly() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - ReceiveContext = { VisibilityTimeout = TimeSpan.FromMinutes(1) } - }; + ReceiveContext = { VisibilityTimeout = TimeSpan.FromMinutes(1) } + }; - Assert.Equal(TimeSpan.FromMinutes(1), options.ReceiveContext.VisibilityTimeout); - } + Assert.Equal(TimeSpan.FromMinutes(1), options.ReceiveContext.VisibilityTimeout); + } - [Fact] - public void VisibilityTimeout_ShouldClampToValidRange() + [Fact] + public void VisibilityTimeout_ShouldClampToValidRange() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - ReceiveContext = { VisibilityTimeout = TimeSpan.FromDays(10) } - }; + ReceiveContext = { VisibilityTimeout = TimeSpan.FromDays(10) } + }; - Assert.Equal(AzureQueueOptions.MaxVisibilityTimeout, options.ReceiveContext.VisibilityTimeout); + Assert.Equal(AzureQueueOptions.MaxVisibilityTimeout, options.ReceiveContext.VisibilityTimeout); - options.ReceiveContext.VisibilityTimeout = TimeSpan.FromMilliseconds(500); + options.ReceiveContext.VisibilityTimeout = TimeSpan.FromMilliseconds(500); - Assert.Equal(TimeSpan.FromSeconds(1), options.ReceiveContext.VisibilityTimeout); - } + Assert.Equal(TimeSpan.FromSeconds(1), options.ReceiveContext.VisibilityTimeout); } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs index b2547a0e..e657ae7e 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs @@ -2,58 +2,57 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.QueueStorage +namespace Savvyio.Extensions.QueueStorage; + +public class AzureQueueSendOptionsTest : Test { - public class AzureQueueSendOptionsTest : Test + public AzureQueueSendOptionsTest(ITestOutputHelper output) : base(output) { - public AzureQueueSendOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_ShouldInitializeWithDefaultValues() - { - var options = new AzureQueueOptions().SendContext; + [Fact] + public void Constructor_ShouldInitializeWithDefaultValues() + { + var options = new AzureQueueOptions().SendContext; - Assert.Equal(TimeSpan.Zero, options.VisibilityTimeout); - Assert.Equal(TimeSpan.FromDays(7), options.TimeToLive); - } + Assert.Equal(TimeSpan.Zero, options.VisibilityTimeout); + Assert.Equal(TimeSpan.FromDays(7), options.TimeToLive); + } - [Fact] - public void VisibilityTimeout_ShouldSetAndGetCorrectly() + [Fact] + public void VisibilityTimeout_ShouldSetAndGetCorrectly() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - SendContext = { VisibilityTimeout = TimeSpan.FromMinutes(1) } - }; + SendContext = { VisibilityTimeout = TimeSpan.FromMinutes(1) } + }; - Assert.Equal(TimeSpan.FromMinutes(1), options.SendContext.VisibilityTimeout); - } + Assert.Equal(TimeSpan.FromMinutes(1), options.SendContext.VisibilityTimeout); + } - [Fact] - public void TimeToLive_ShouldSetAndGetCorrectly() + [Fact] + public void TimeToLive_ShouldSetAndGetCorrectly() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - SendContext = { TimeToLive = TimeSpan.FromHours(1) } - }; + SendContext = { TimeToLive = TimeSpan.FromHours(1) } + }; - Assert.Equal(TimeSpan.FromHours(1), options.SendContext.TimeToLive); - } + Assert.Equal(TimeSpan.FromHours(1), options.SendContext.TimeToLive); + } - [Fact] - public void VisibilityTimeout_ShouldClampToValidRange() + [Fact] + public void VisibilityTimeout_ShouldClampToValidRange() + { + var options = new AzureQueueOptions() { - var options = new AzureQueueOptions() - { - SendContext = { VisibilityTimeout = TimeSpan.FromDays(10) } - }; + SendContext = { VisibilityTimeout = TimeSpan.FromDays(10) } + }; - Assert.Equal(AzureQueueOptions.MaxVisibilityTimeout, options.SendContext.VisibilityTimeout); + Assert.Equal(AzureQueueOptions.MaxVisibilityTimeout, options.SendContext.VisibilityTimeout); - options.SendContext.VisibilityTimeout = TimeSpan.FromMilliseconds(-1); + options.SendContext.VisibilityTimeout = TimeSpan.FromMilliseconds(-1); - Assert.Equal(TimeSpan.Zero, options.SendContext.VisibilityTimeout); - } + Assert.Equal(TimeSpan.Zero, options.SendContext.VisibilityTimeout); } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/Commands/AzureCommandQueueTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/Commands/AzureCommandQueueTest.cs index 787e4879..8466eebe 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/Commands/AzureCommandQueueTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/Commands/AzureCommandQueueTest.cs @@ -17,164 +17,163 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.QueueStorage.Commands +namespace Savvyio.Extensions.QueueStorage.Commands; + +public class AzureCommandQueueTest : Test { - public class AzureCommandQueueTest : Test + private readonly IMarshaller _marshaller; + private readonly AzureQueueOptions _options; + + public AzureCommandQueueTest(ITestOutputHelper output) : base(output) { - private readonly IMarshaller _marshaller; - private readonly AzureQueueOptions _options; + _marshaller = JsonMarshaller.Default; + _options = new AzureQueueOptions { QueueName = "test-queue", StorageAccountName = "test-account" }; + } - public AzureCommandQueueTest(ITestOutputHelper output) : base(output) - { - _marshaller = JsonMarshaller.Default; - _options = new AzureQueueOptions { QueueName = "test-queue", StorageAccountName = "test-account" }; - } + [Fact] + public void Constructor_ShouldThrowArgumentNullException_WhenMarshallerIsNull() + { + Assert.Throws(() => new AzureCommandQueue(null, _options)); + } - [Fact] - public void Constructor_ShouldThrowArgumentNullException_WhenMarshallerIsNull() - { - Assert.Throws(() => new AzureCommandQueue(null, _options)); - } + [Fact] + public void Constructor_ShouldThrowArgumentNullException_WhenOptionsIsNull() + { + Assert.Throws(() => new AzureCommandQueue(_marshaller, null)); + } - [Fact] - public void Constructor_ShouldThrowArgumentNullException_WhenOptionsIsNull() - { - Assert.Throws(() => new AzureCommandQueue(_marshaller, null)); - } + [Fact] + public void Constructor_ShouldThrowArgumentException_WhenOptionsAreInvalid() + { + Assert.Throws(() => new AzureCommandQueue(_marshaller, new AzureQueueOptions { Credential = null })); + } - [Fact] - public void Constructor_ShouldThrowArgumentException_WhenOptionsAreInvalid() - { - Assert.Throws(() => new AzureCommandQueue(_marshaller, new AzureQueueOptions { Credential = null })); - } + [Fact] + public void Constructor_ShouldCreateInstance_WhenArgumentsAreValid() + { + var queue = new AzureCommandQueue(_marshaller, _options); + Assert.NotNull(queue); + } - [Fact] - public void Constructor_ShouldCreateInstance_WhenArgumentsAreValid() - { - var queue = new AzureCommandQueue(_marshaller, _options); - Assert.NotNull(queue); - } + [Fact] + public async Task SendAsync_ShouldThrowArgumentNullException_WhenMessagesAreNull() + { + var queue = new AzureCommandQueue(_marshaller, _options); - [Fact] - public async Task SendAsync_ShouldThrowArgumentNullException_WhenMessagesAreNull() - { - var queue = new AzureCommandQueue(_marshaller, _options); + await Assert.ThrowsAsync(() => queue.SendAsync(null)); + } - await Assert.ThrowsAsync(() => queue.SendAsync(null)); - } + [Fact] + public void ReceiveAsync_ShouldReturnAsyncEnumerable() + { + var queue = new AzureCommandQueue(_marshaller, _options); + + var result = queue.ReceiveAsync(); - [Fact] - public void ReceiveAsync_ShouldReturnAsyncEnumerable() + Assert.NotNull(result); + Assert.IsAssignableFrom>>(result); + } + + [Fact] + public void GetHealthCheckTarget_ShouldReturnQueueServiceClient_ForConnectionString() + { + var queue = new AzureCommandQueue(_marshaller, new AzureQueueOptions { - var queue = new AzureCommandQueue(_marshaller, _options); + ConnectionString = "UseDevelopmentStorage=true", + QueueName = "testqueue" + }); - var result = queue.ReceiveAsync(); + var result = queue.GetHealthCheckTarget(); - Assert.NotNull(result); - Assert.IsAssignableFrom>>(result); - } + Assert.NotNull(result); + Assert.IsType(result); + Assert.StartsWith("http://127.0.0.1:10001/devstoreaccount1", result.Uri.AbsoluteUri, StringComparison.OrdinalIgnoreCase); + } - [Fact] - public void GetHealthCheckTarget_ShouldReturnQueueServiceClient_ForConnectionString() + [Fact] + public void GetHealthCheckTarget_ShouldReturnQueueServiceClient_ForStorageSharedKeyCredential() + { + var queue = new AzureCommandQueue(_marshaller, new AzureQueueOptions { - var queue = new AzureCommandQueue(_marshaller, new AzureQueueOptions - { - ConnectionString = "UseDevelopmentStorage=true", - QueueName = "testqueue" - }); + StorageAccountName = "testaccount", + QueueName = "testqueue", + StorageKeyCredential = new StorageSharedKeyCredential("testaccount", Convert.ToBase64String(new byte[32])) + }); - var result = queue.GetHealthCheckTarget(); + var result = queue.GetHealthCheckTarget(); - Assert.NotNull(result); - Assert.IsType(result); - Assert.StartsWith("http://127.0.0.1:10001/devstoreaccount1", result.Uri.AbsoluteUri, StringComparison.OrdinalIgnoreCase); - } + Assert.Equal(new Uri("https://testaccount.queue.core.windows.net/testqueue"), result.Uri); + } - [Fact] - public void GetHealthCheckTarget_ShouldReturnQueueServiceClient_ForStorageSharedKeyCredential() - { - var queue = new AzureCommandQueue(_marshaller, new AzureQueueOptions - { - StorageAccountName = "testaccount", - QueueName = "testqueue", - StorageKeyCredential = new StorageSharedKeyCredential("testaccount", Convert.ToBase64String(new byte[32])) - }); + [Fact] + public async Task SendMessageAsync_ShouldSendFormattedMessages() + { + var queueClient = new Mock(); + var sent = new List(); + queueClient.Setup(c => c.SendMessageAsync(It.IsAny(), It.IsAny(), It.IsAny(), default)) + .Callback((message, _, _, _) => sent.Add(message)) + .ReturnsAsync(Response.FromValue(QueuesModelFactory.SendReceipt("id", DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), "receipt", DateTimeOffset.UtcNow), Mock.Of())); + var queue = new TestAzureQueue(_marshaller, _options, queueClient.Object); - var result = queue.GetHealthCheckTarget(); + await queue.SendAsync([CreateMessage()]); - Assert.Equal(new Uri("https://testaccount.queue.core.windows.net/testqueue"), result.Uri); - } + Assert.Single(sent); + Assert.Contains(".", sent[0], StringComparison.Ordinal); + } - [Fact] - public async Task SendMessageAsync_ShouldSendFormattedMessages() + [Fact] + public async Task ReceiveMessagesAsync_ShouldYieldMessagesAndDeleteOnAcknowledge() + { + var message = CreateMessage(); + var encodedType = message.GetType().ToFullNameIncludingAssemblyName().ToByteArray().ToBase64String(); + var encodedMessage = _marshaller.Serialize(message).ToByteArray().ToBase64String(); + var raw = QueuesModelFactory.QueueMessage("message-id", "pop-receipt", $"{encodedType}.{encodedMessage}", 1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), DateTimeOffset.UtcNow); + var queueClient = new Mock(); + queueClient.Setup(c => c.ReceiveMessagesAsync(It.IsAny(), It.IsAny(), default)) + .ReturnsAsync(Response.FromValue(new[] { raw }, Mock.Of())); + string deletedMessageId = null; + queueClient.Setup(c => c.DeleteMessageAsync(It.IsAny(), It.IsAny(), default)) + .Callback((messageId, _, _) => deletedMessageId = messageId) + .ReturnsAsync(Mock.Of()); + var queue = new TestAzureQueue(_marshaller, _options, queueClient.Object); + + var received = new List>(); + await foreach (var item in queue.ReceiveAsync()) { - var queueClient = new Mock(); - var sent = new List(); - queueClient.Setup(c => c.SendMessageAsync(It.IsAny(), It.IsAny(), It.IsAny(), default)) - .Callback((message, _, _, _) => sent.Add(message)) - .ReturnsAsync(Response.FromValue(QueuesModelFactory.SendReceipt("id", DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), "receipt", DateTimeOffset.UtcNow), Mock.Of())); - var queue = new TestAzureQueue(_marshaller, _options, queueClient.Object); + received.Add(item); + await item.AcknowledgeAsync(); + } - await queue.SendAsync([CreateMessage()]); + Assert.Single(received); + Assert.Equal(message.Id, received[0].Id); + Assert.Equal("message-id", deletedMessageId); + } - Assert.Single(sent); - Assert.Contains(".", sent[0], StringComparison.Ordinal); - } + private static IMessage CreateMessage() + { + return new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test", + new TestCommand()); + } - [Fact] - public async Task ReceiveMessagesAsync_ShouldYieldMessagesAndDeleteOnAcknowledge() + private sealed class TestAzureQueue : AzureQueue + { + public TestAzureQueue(IMarshaller marshaller, AzureQueueOptions options, QueueClient client) : base(marshaller, options, Mock.Of(), client) { - var message = CreateMessage(); - var encodedType = message.GetType().ToFullNameIncludingAssemblyName().ToByteArray().ToBase64String(); - var encodedMessage = _marshaller.Serialize(message).ToByteArray().ToBase64String(); - var raw = QueuesModelFactory.QueueMessage("message-id", "pop-receipt", $"{encodedType}.{encodedMessage}", 1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), DateTimeOffset.UtcNow); - var queueClient = new Mock(); - queueClient.Setup(c => c.ReceiveMessagesAsync(It.IsAny(), It.IsAny(), default)) - .ReturnsAsync(Response.FromValue(new[] { raw }, Mock.Of())); - string deletedMessageId = null; - queueClient.Setup(c => c.DeleteMessageAsync(It.IsAny(), It.IsAny(), default)) - .Callback((messageId, _, _) => deletedMessageId = messageId) - .ReturnsAsync(Mock.Of()); - var queue = new TestAzureQueue(_marshaller, _options, queueClient.Object); - - var received = new List>(); - await foreach (var item in queue.ReceiveAsync()) - { - received.Add(item); - await item.AcknowledgeAsync(); - } - - Assert.Single(received); - Assert.Equal(message.Id, received[0].Id); - Assert.Equal("message-id", deletedMessageId); } - private static IMessage CreateMessage() + public Task SendAsync(IEnumerable> messages) { - return new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test", - new TestCommand()); + return SendMessageAsync(messages); } - private sealed class TestAzureQueue : AzureQueue + public IAsyncEnumerable> ReceiveAsync() { - public TestAzureQueue(IMarshaller marshaller, AzureQueueOptions options, QueueClient client) : base(marshaller, options, Mock.Of(), client) - { - } - - public Task SendAsync(IEnumerable> messages) - { - return SendMessageAsync(messages); - } - - public IAsyncEnumerable> ReceiveAsync() - { - return ReceiveMessagesAsync(); - } + return ReceiveMessagesAsync(); } - - private record TestCommand : Command { } } + + private record TestCommand : Command { } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusOptionsTest.cs index 05442c07..3d527eea 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusOptionsTest.cs @@ -5,89 +5,88 @@ using Cuemon; using Xunit; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +public class AzureEventBusOptionsTest : Test { - public class AzureEventBusOptionsTest : Test + public AzureEventBusOptionsTest(ITestOutputHelper output) : base(output) { - public AzureEventBusOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Set_Defaults() - { - var sut = new AzureEventBusOptions(); + [Fact] + public void Constructor_Should_Set_Defaults() + { + var sut = new AzureEventBusOptions(); - Assert.NotNull(sut.Credential); - Assert.IsType(sut.Credential); - Assert.Null(sut.TopicEndpoint); - Assert.NotNull(sut.Settings); - Assert.Null(sut.KeyCredential); - Assert.Null(sut.SasCredential); - } + Assert.NotNull(sut.Credential); + Assert.IsType(sut.Credential); + Assert.Null(sut.TopicEndpoint); + Assert.NotNull(sut.Settings); + Assert.Null(sut.KeyCredential); + Assert.Null(sut.SasCredential); + } - [Fact] - public void Credential_Setters_Should_Be_Mutually_Exclusive() + [Fact] + public void Credential_Setters_Should_Be_Mutually_Exclusive() + { + var sut = new AzureEventBusOptions { - var sut = new AzureEventBusOptions - { - KeyCredential = new AzureKeyCredential("key") - }; + KeyCredential = new AzureKeyCredential("key") + }; - Assert.NotNull(sut.KeyCredential); - Assert.Null(sut.Credential); - Assert.Null(sut.SasCredential); + Assert.NotNull(sut.KeyCredential); + Assert.Null(sut.Credential); + Assert.Null(sut.SasCredential); - sut.SasCredential = new AzureSasCredential("sig"); - Assert.NotNull(sut.SasCredential); - Assert.Null(sut.Credential); - Assert.Null(sut.KeyCredential); + sut.SasCredential = new AzureSasCredential("sig"); + Assert.NotNull(sut.SasCredential); + Assert.Null(sut.Credential); + Assert.Null(sut.KeyCredential); - sut.Credential = new DefaultAzureCredential(); - Assert.NotNull(sut.Credential); - Assert.Null(sut.KeyCredential); - Assert.Null(sut.SasCredential); - } + sut.Credential = new DefaultAzureCredential(); + Assert.NotNull(sut.Credential); + Assert.Null(sut.KeyCredential); + Assert.Null(sut.SasCredential); + } - [Fact] - public void ValidateOptions_Should_Throw_When_Topic_Endpoint_Is_Missing() - { - var sut1 = new AzureEventBusOptions(); - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + [Fact] + public void ValidateOptions_Should_Throw_When_Topic_Endpoint_Is_Missing() + { + var sut1 = new AzureEventBusOptions(); + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - Assert.Equal($"A {nameof(AzureEventBusOptions.TopicEndpoint)} is required. (Expression '{nameof(AzureEventBusOptions.TopicEndpoint)} == null')", sut2.Message); - Assert.Equal($"{nameof(AzureEventBusOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Assert.Equal($"A {nameof(AzureEventBusOptions.TopicEndpoint)} is required. (Expression '{nameof(AzureEventBusOptions.TopicEndpoint)} == null')", sut2.Message); + Assert.Equal($"{nameof(AzureEventBusOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - [Fact] - public void ValidateOptions_Should_Throw_When_All_Credentials_Are_Missing() + [Fact] + public void ValidateOptions_Should_Throw_When_All_Credentials_Are_Missing() + { + var sut1 = new AzureEventBusOptions { - var sut1 = new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic") - }; - sut1.Credential = null; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + TopicEndpoint = new Uri("https://test.topic") + }; + sut1.Credential = null; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - Assert.Equal("A credential type has to be specified for Azure authentication. (Expression 'Credential == null && SasCredential == null && KeyCredential == null')", sut2.Message); - Assert.Equal($"{nameof(AzureEventBusOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Assert.Equal("A credential type has to be specified for Azure authentication. (Expression 'Credential == null && SasCredential == null && KeyCredential == null')", sut2.Message); + Assert.Equal($"{nameof(AzureEventBusOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - [Fact] - public void ValidateOptions_Should_Not_Throw_When_Valid() + [Fact] + public void ValidateOptions_Should_Not_Throw_When_Valid() + { + var sut = new AzureEventBusOptions { - var sut = new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic") - }; + TopicEndpoint = new Uri("https://test.topic") + }; - var exception = Record.Exception(() => sut.ValidateOptions()); + var exception = Record.Exception(() => sut.ValidateOptions()); - Assert.Null(exception); - } + Assert.Null(exception); } } diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusTest.cs index 3d757ae7..ddb6b369 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/EventDriven/AzureEventBusTest.cs @@ -24,232 +24,231 @@ using Savvyio.Extensions.Text.Json; using Xunit; -namespace Savvyio.Extensions.QueueStorage.EventDriven +namespace Savvyio.Extensions.QueueStorage.EventDriven; + +/// +/// Unit tests for . +/// +public class AzureEventBusTest : Test { - /// - /// Unit tests for . - /// - public class AzureEventBusTest : Test + public AzureEventBusTest(ITestOutputHelper output) : base(output) { - public AzureEventBusTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_Should_Throw_When_Options_Invalid() - { - var marshaller = new JsonMarshaller(); - var queueOptions = new AzureQueueOptions(); + [Fact] + public void Ctor_Should_Throw_When_Options_Invalid() + { + var marshaller = new JsonMarshaller(); + var queueOptions = new AzureQueueOptions(); - Assert.Throws(() => - new AzureEventBus(marshaller, queueOptions, null)); - } + Assert.Throws(() => + new AzureEventBus(marshaller, queueOptions, null)); + } - [Fact] - public void Ctor_Should_Use_Token_Credential() + [Fact] + public void Ctor_Should_Use_Token_Credential() + { + var marshaller = new JsonMarshaller(); + var queueOptions = new AzureQueueOptions { - var marshaller = new JsonMarshaller(); - var queueOptions = new AzureQueueOptions - { - StorageAccountName = "testaccount", - QueueName = "testqueue", - Credential = new Mock().Object - }; - var eventBusOptions = new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic"), - Credential = new Mock().Object - }; - - var bus = new AzureEventBus(marshaller, queueOptions, eventBusOptions); - Assert.NotNull(bus); - } - - [Fact] - public void Ctor_Should_Use_Sas_And_Key_Credentials() + StorageAccountName = "testaccount", + QueueName = "testqueue", + Credential = new Mock().Object + }; + var eventBusOptions = new AzureEventBusOptions { - var marshaller = new JsonMarshaller(); - var queueOptions = new AzureQueueOptions - { - StorageAccountName = "testaccount", - QueueName = "testqueue", - SasCredential = new AzureSasCredential("sig") - }; - var eventBusOptions = new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic"), - KeyCredential = new AzureKeyCredential("key") - }; - - var bus = new AzureEventBus(marshaller, queueOptions, eventBusOptions); - Assert.NotNull(bus); - } + TopicEndpoint = new Uri("https://test.topic"), + Credential = new Mock().Object + }; - [Fact] - public async Task PublishAsync_Should_Throw_When_Message_Null() - { - var bus = CreateSut(); - await Assert.ThrowsAsync(() => bus.PublishAsync(null)); - } + var bus = new AzureEventBus(marshaller, queueOptions, eventBusOptions); + Assert.NotNull(bus); + } - [Fact] - public async Task PublishAsync_Should_Invoke_EventGridClient() + [Fact] + public void Ctor_Should_Use_Sas_And_Key_Credentials() + { + var marshaller = new JsonMarshaller(); + var queueOptions = new AzureQueueOptions { - var marshaller = new JsonMarshaller(); + StorageAccountName = "testaccount", + QueueName = "testqueue", + SasCredential = new AzureSasCredential("sig") + }; + var eventBusOptions = new AzureEventBusOptions + { + TopicEndpoint = new Uri("https://test.topic"), + KeyCredential = new AzureKeyCredential("key") + }; - var eventGridClient = new Mock(); - eventGridClient - .Setup(c => c.SendEventAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(Mock.Of()) - .Verifiable(); + var bus = new AzureEventBus(marshaller, queueOptions, eventBusOptions); + Assert.NotNull(bus); + } - var bus = CreateSut(marshaller: marshaller); - SetPrivateClient(bus, eventGridClient.Object); + [Fact] + public async Task PublishAsync_Should_Throw_When_Message_Null() + { + var bus = CreateSut(); + await Assert.ThrowsAsync(() => bus.PublishAsync(null)); + } - var message = new Message("id", "https://source".ToUri(), "type", new DummyIntegrationEvent(), DateTime.UtcNow); + [Fact] + public async Task PublishAsync_Should_Invoke_EventGridClient() + { + var marshaller = new JsonMarshaller(); - await bus.PublishAsync(message); + var eventGridClient = new Mock(); + eventGridClient + .Setup(c => c.SendEventAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(Mock.Of()) + .Verifiable(); - eventGridClient.Verify(); - } + var bus = CreateSut(marshaller: marshaller); + SetPrivateClient(bus, eventGridClient.Object); - [Fact] - public async Task PublishAsync_Should_Add_Signature_When_SignedMessage() - { - var marshaller = new JsonMarshaller(); - - var eventGridClient = new Mock(); - eventGridClient - .Setup(c => c.SendEventAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(Mock.Of()) - .Verifiable(); - - var bus = CreateSut(marshaller: marshaller); - SetPrivateClient(bus, eventGridClient.Object); - - // Use a real signed message implementation with non-null data - var signedMessage = new TestSignedMessage( - id: "id", - source: "https://source".ToUri(), - type: "type", - data: new DummyIntegrationEvent(), - time: DateTime.UtcNow, - signature: "signature" - ); - - await bus.PublishAsync(signedMessage); - - eventGridClient.Verify(); - } + var message = new Message("id", "https://source".ToUri(), "type", new DummyIntegrationEvent(), DateTime.UtcNow); - // Dummy event for test - private record DummyIntegrationEvent : IntegrationEvent - { - } + await bus.PublishAsync(message); - // Helper test double for ISignedMessage - private record TestSignedMessage : Message, ISignedMessage - { - public TestSignedMessage(string id, Uri source, string type, IIntegrationEvent data, DateTime? time, string signature) - : base(id, source, type, data, time) - { - Signature = signature; - } + eventGridClient.Verify(); + } - public string Signature { get; } - } + [Fact] + public async Task PublishAsync_Should_Add_Signature_When_SignedMessage() + { + var marshaller = new JsonMarshaller(); + + var eventGridClient = new Mock(); + eventGridClient + .Setup(c => c.SendEventAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(Mock.Of()) + .Verifiable(); + + var bus = CreateSut(marshaller: marshaller); + SetPrivateClient(bus, eventGridClient.Object); + + // Use a real signed message implementation with non-null data + var signedMessage = new TestSignedMessage( + id: "id", + source: "https://source".ToUri(), + type: "type", + data: new DummyIntegrationEvent(), + time: DateTime.UtcNow, + signature: "signature" + ); + + await bus.PublishAsync(signedMessage); + + eventGridClient.Verify(); + } - [Fact] - public async Task SubscribeAsync_Should_Throw_When_Handler_Null() + // Dummy event for test + private record DummyIntegrationEvent : IntegrationEvent + { + } + + // Helper test double for ISignedMessage + private record TestSignedMessage : Message, ISignedMessage + { + public TestSignedMessage(string id, Uri source, string type, IIntegrationEvent data, DateTime? time, string signature) + : base(id, source, type, data, time) { - var bus = CreateSut(); - await Assert.ThrowsAsync(() => bus.SubscribeAsync(null)); + Signature = signature; } - [Fact] - public void GetHealthCheckTarget_Should_Return_Health_Uri() + public string Signature { get; } + } + + [Fact] + public async Task SubscribeAsync_Should_Throw_When_Handler_Null() + { + var bus = CreateSut(); + await Assert.ThrowsAsync(() => bus.SubscribeAsync(null)); + } + + [Fact] + public void GetHealthCheckTarget_Should_Return_Health_Uri() + { + var options = new AzureEventBusOptions { - var options = new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic") - }; - var bus = CreateSut(eventBusOptions: options); + TopicEndpoint = new Uri("https://test.topic") + }; + var bus = CreateSut(eventBusOptions: options); - var uri = bus.GetHealthCheckTarget(); + var uri = bus.GetHealthCheckTarget(); - Assert.Equal(new Uri("https://test.topic/api/health"), uri); - } + Assert.Equal(new Uri("https://test.topic/api/health"), uri); + } - [Fact] - public async Task SubscribeAsync_ShouldReceiveQueuedCloudEventsAndInvokeHandler() + [Fact] + public async Task SubscribeAsync_ShouldReceiveQueuedCloudEventsAndInvokeHandler() + { + var marshaller = new JsonMarshaller(); + var message = new Message("id", "https://source".ToUri(), "type", new DummyIntegrationEvent(), DateTime.UtcNow); + var cloudEvent = message.ToCloudEvent(); + cloudEvent.Add(AzureEventBus.CloudEventTypeExtensionAttribute, message.GetType().ToFullNameIncludingAssemblyName()); + var raw = QueuesModelFactory.QueueMessage("message-id", "pop-receipt", marshaller.Serialize(cloudEvent).ToEncodedString().ToByteArray().ToBase64String(), 1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), DateTimeOffset.UtcNow); + var queueClient = new Mock(); + queueClient.SetupSequence(c => c.ReceiveMessagesAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Response.FromValue(new[] { raw }, Mock.Of())) + .ReturnsAsync(Response.FromValue(Array.Empty(), Mock.Of())); + queueClient.Setup(c => c.DeleteMessageAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Mock.Of()); + var bus = new TestableAzureEventBus(marshaller, queueClient.Object); + IMessage received = null; + + await bus.SubscribeAsync((msg, _) => { - var marshaller = new JsonMarshaller(); - var message = new Message("id", "https://source".ToUri(), "type", new DummyIntegrationEvent(), DateTime.UtcNow); - var cloudEvent = message.ToCloudEvent(); - cloudEvent.Add(AzureEventBus.CloudEventTypeExtensionAttribute, message.GetType().ToFullNameIncludingAssemblyName()); - var raw = QueuesModelFactory.QueueMessage("message-id", "pop-receipt", marshaller.Serialize(cloudEvent).ToEncodedString().ToByteArray().ToBase64String(), 1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1), DateTimeOffset.UtcNow); - var queueClient = new Mock(); - queueClient.SetupSequence(c => c.ReceiveMessagesAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(Response.FromValue(new[] { raw }, Mock.Of())) - .ReturnsAsync(Response.FromValue(Array.Empty(), Mock.Of())); - queueClient.Setup(c => c.DeleteMessageAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(Mock.Of()); - var bus = new TestableAzureEventBus(marshaller, queueClient.Object); - IMessage received = null; - - await bus.SubscribeAsync((msg, _) => - { - received = msg; - return Task.CompletedTask; - }); - - Assert.NotNull(received); - Assert.Equal(message.Id, received.Id); - } + received = msg; + return Task.CompletedTask; + }); + + Assert.NotNull(received); + Assert.Equal(message.Id, received.Id); + } - // --- Helpers --- + // --- Helpers --- - private AzureEventBus CreateSut( - IMarshaller marshaller = null, - AzureEventBusOptions eventBusOptions = null) + private AzureEventBus CreateSut( + IMarshaller marshaller = null, + AzureEventBusOptions eventBusOptions = null) + { + marshaller ??= new JsonMarshaller(); + var queueOptions = new AzureQueueOptions { - marshaller ??= new JsonMarshaller(); - var queueOptions = new AzureQueueOptions - { - StorageAccountName = "testaccount", - QueueName = "testqueue", - Credential = new Mock().Object - }; - eventBusOptions ??= new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic"), - Credential = new Mock().Object - }; - - return new AzureEventBus(marshaller, queueOptions, eventBusOptions); - } - - private void SetPrivateClient(AzureEventBus bus, EventGridPublisherClient client) + StorageAccountName = "testaccount", + QueueName = "testqueue", + Credential = new Mock().Object + }; + eventBusOptions ??= new AzureEventBusOptions { - var field = typeof(AzureEventBus).GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic); - field.SetValue(bus, client); - } + TopicEndpoint = new Uri("https://test.topic"), + Credential = new Mock().Object + }; + + return new AzureEventBus(marshaller, queueOptions, eventBusOptions); + } - private sealed class TestableAzureEventBus : AzureEventBus + private void SetPrivateClient(AzureEventBus bus, EventGridPublisherClient client) + { + var field = typeof(AzureEventBus).GetField("_client", BindingFlags.Instance | BindingFlags.NonPublic); + field.SetValue(bus, client); + } + + private sealed class TestableAzureEventBus : AzureEventBus + { + public TestableAzureEventBus(IMarshaller marshaller, QueueClient queueClient) : base(marshaller, new AzureQueueOptions + { + StorageAccountName = "testaccount", + QueueName = "testqueue", + Credential = new Mock().Object + }, new AzureEventBusOptions + { + TopicEndpoint = new Uri("https://test.topic"), + Credential = new Mock().Object + }, Mock.Of(), queueClient, Mock.Of()) { - public TestableAzureEventBus(IMarshaller marshaller, QueueClient queueClient) : base(marshaller, new AzureQueueOptions - { - StorageAccountName = "testaccount", - QueueName = "testqueue", - Credential = new Mock().Object - }, new AzureEventBusOptions - { - TopicEndpoint = new Uri("https://test.topic"), - Credential = new Mock().Object - }, Mock.Of(), queueClient, Mock.Of()) - { - } } - } -} \ No newline at end of file + +} diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs index 18851b1e..7a106825 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,20 +1,19 @@ using Savvyio.Commands; -namespace Savvyio.Extensions.RabbitMQ.Assets +namespace Savvyio.Extensions.RabbitMQ.Assets; + +internal record CreateMemberCommand : Command { - internal record CreateMemberCommand : Command + public CreateMemberCommand(string name, byte age, string emailAddress) { - public CreateMemberCommand(string name, byte age, string emailAddress) - { - Name = name; - Age = age; - EmailAddress = emailAddress; - } + Name = name; + Age = age; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public byte Age { get; } + public byte Age { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs index 0958bebc..c0347d89 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs @@ -1,17 +1,16 @@ using Savvyio.EventDriven; -namespace Savvyio.Extensions.RabbitMQ.Assets +namespace Savvyio.Extensions.RabbitMQ.Assets; + +public record MemberCreated : IntegrationEvent { - public record MemberCreated : IntegrationEvent + public MemberCreated(string name, string emailAddress) { - public MemberCreated(string name, string emailAddress) - { - Name = name; - EmailAddress = emailAddress; - } + Name = name; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs index 0deddafc..944e5bb9 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs @@ -19,166 +19,165 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +public class RabbitMqCommandQueueJsonSerializerContextTest : Test { - public class RabbitMqCommandQueueJsonSerializerContextTest : Test + public RabbitMqCommandQueueJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public RabbitMqCommandQueueJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.AutoAcknowledge = true; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.AutoAcknowledge = true; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) 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); - } + 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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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 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 receivedMessages = Channel.CreateUnbounded>(); - var count1 = 0; - Task.Run(async () => + var count1 = 0; + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - count1++; - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + count1++; + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - var count2 = 0; - Task.Run(async () => + var count2 = 0; + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - count2++; - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + count2++; + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(messages).ConfigureAwait(false); + await queue.SendAsync(messages).ConfigureAwait(false); - var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); + var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); - TestOutput.WriteLine(count1.ToString()); - TestOutput.WriteLine(count2.ToString()); + TestOutput.WriteLine(count1.ToString()); + TestOutput.WriteLine(count2.ToString()); - TestOutput.WriteLine(received.Count.ToString()); - TestOutput.WriteLines(received.Take(10)); + 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)); - } + 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.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs index af2fda11..1e6531ef 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -19,149 +19,148 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +public class RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest : Test { - public class RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest : Test + public RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(message.Yield()).ConfigureAwait(false); + await queue.SendAsync(message.Yield()).ConfigureAwait(false); - var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = (await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10))) 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); - } + 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() + [Fact] + public async Task ReceiveAndSendAsync_CreateMemberCommand_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageQueue().AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageQueue().AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.QueueName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.QueueName = Generate.RandomString(10); }); + }); - var queue = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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 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 receivedMessages = Channel.CreateUnbounded>(); - Task.Run(async () => + Task.Run(async () => + { + await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) { - await foreach (var msg in queue.ReceiveAsync().ConfigureAwait(false)) - { - await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); - } - }); + await receivedMessages.Writer.WriteAsync(msg).ConfigureAwait(false); + } + }); - await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForCommandSubscriptionAsync(managed.Host.Services); - await queue.SendAsync(messages).ConfigureAwait(false); + await queue.SendAsync(messages).ConfigureAwait(false); - var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); + var received = await MessageTestHelper.ReadAsync(receivedMessages.Reader, messages.Count); - TestOutput.WriteLine(received.Count.ToString()); - TestOutput.WriteLines(received.Take(10)); + 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)); - } + 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.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs index 8a086c8b..4b401a06 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs @@ -21,280 +21,279 @@ using Cuemon.Extensions.IO; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +public class RabbitMqEventBusJsonSerializerContextTest : Test { - public class RabbitMqEventBusJsonSerializerContextTest : Test + public RabbitMqEventBusJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public RabbitMqEventBusJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ICloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedCloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = 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 bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); - var handlerInvocations2 = 0; - Task.Run(async () => + 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) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations2++; - await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); - - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - return bus.PublishAsync(message, o => o.CancellationToken = token); + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); }).ConfigureAwait(false); + }); - var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); - var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); - await Task.WhenAll(received1Task, received2Task); - var received1 = await received1Task; - var received2 = await received2Task; - - 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)); - } + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); + var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); + await Task.WhenAll(received1Task, received2Task); + var received1 = await received1Task; + var received2 = await received2Task; + + 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.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs index f6338a84..c160bd5c 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs @@ -21,280 +21,279 @@ using System.Threading.Tasks; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +public class RabbitMqEventBusNewtonsoftJsonSerializerContextTest : Test { - public class RabbitMqEventBusNewtonsoftJsonSerializerContextTest : Test + public RabbitMqEventBusNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) { - public RabbitMqEventBusNewtonsoftJsonSerializerContextTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); - 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.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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message).ConfigureAwait(false); + await bus.PublishAsync(message).ConfigureAwait(false); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedMessage; - received?.CheckSignature(marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ICloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = Generate.RandomString(10); }); + }); - var bus = managed.Host.Services.GetRequiredService(); - var marshaller = managed.Host.Services.GetRequiredService(); + 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>(); + 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()); + TestOutput.WriteLine(marshaller.Serialize(urn).ToEncodedString()); + TestOutput.WriteLine(marshaller.Serialize(message).ToEncodedString()); - var handlerInvocations = 0; - Task.Run(async () => + var handlerInvocations = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations++; - await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); + handlerInvocations++; + await receivedMessages.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); - await bus.PublishAsync(message); + await bus.PublishAsync(message); - var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) as ISignedCloudEvent; + var received = await receivedMessages.Reader.ReadAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)) 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); - } + 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() + [Fact] + public async Task SubscribeAndPublishAsync_MemberCreated_HundredTimes() + { + var managed = HostTestFactory.Create(services => { - var managed = HostTestFactory.Create(services => + services.AddMarshaller(); + services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => { - services.AddMarshaller(); - services.AddMessageBus(o => o.Lifetime = ServiceLifetime.Singleton).AddConfiguredOptions(o => - { - o.AmqpUrl = RabbitMqTestEnvironment.Url; - o.ExchangeName = Generate.RandomString(10); - }); + o.AmqpUrl = RabbitMqTestEnvironment.Url; + o.ExchangeName = 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 bus = managed.Host.Services.GetRequiredService(); + var marshaller = managed.Host.Services.GetRequiredService(); - var handlerInvocations2 = 0; - Task.Run(async () => + 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) => { - await bus.SubscribeAsync(async (msg, token) => - { - handlerInvocations2++; - await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); - }).ConfigureAwait(false); - }); - - await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + handlerInvocations1++; + await receivedMessages1.Writer.WriteAsync(msg, token).ConfigureAwait(false); + }).ConfigureAwait(false); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => + var handlerInvocations2 = 0; + Task.Run(async () => + { + await bus.SubscribeAsync(async (msg, token) => { - return bus.PublishAsync(message, o => o.CancellationToken = token); + handlerInvocations2++; + await receivedMessages2.Writer.WriteAsync(msg, token).ConfigureAwait(false); }).ConfigureAwait(false); + }); - var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); - var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); - await Task.WhenAll(received1Task, received2Task); - var received1 = await received1Task; - var received2 = await received2Task; - - 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)); - } + await RabbitMqTestEnvironment.WaitForEventSubscriptionAsync(managed.Host.Services); + + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + return bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + + var received1Task = MessageTestHelper.ReadAsync(receivedMessages1.Reader, messages.Count); + var received2Task = MessageTestHelper.ReadAsync(receivedMessages2.Reader, messages.Count); + await Task.WhenAll(received1Task, received2Task); + var received1 = await received1Task; + var received2 = await received2Task; + + 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.RabbitMQ.FunctionalTests/MessageTestHelper.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/MessageTestHelper.cs index 341599d2..fd711fb3 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/MessageTestHelper.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/MessageTestHelper.cs @@ -4,19 +4,18 @@ using System.Threading.Channels; using System.Threading.Tasks; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +internal static class MessageTestHelper { - internal static class MessageTestHelper + internal static async Task> ReadAsync(ChannelReader reader, int count) { - internal static async Task> ReadAsync(ChannelReader reader, int count) + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + var messages = new List(count); + while (messages.Count < count) { - using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - var messages = new List(count); - while (messages.Count < count) - { - messages.Add(await reader.ReadAsync(timeout.Token)); - } - return messages; + messages.Add(await reader.ReadAsync(timeout.Token)); } + return messages; } } diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/RabbitMqTestEnvironment.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/RabbitMqTestEnvironment.cs index 2d721842..57c4dcee 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/RabbitMqTestEnvironment.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/RabbitMqTestEnvironment.cs @@ -10,77 +10,76 @@ using Savvyio.Extensions.RabbitMQ.Commands; using Savvyio.Extensions.RabbitMQ.EventDriven; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +internal static class RabbitMqTestEnvironment { - internal static class RabbitMqTestEnvironment - { - internal static Uri Url { get; } = new(Environment.GetEnvironmentVariable("SAVVYIO_RABBITMQ_URL") ?? "amqp://localhost:5672"); + internal static Uri Url { get; } = new(Environment.GetEnvironmentVariable("SAVVYIO_RABBITMQ_URL") ?? "amqp://localhost:5672"); - private static Uri ManagementUrl { get; } = CreateManagementUrl(); + private static Uri ManagementUrl { get; } = CreateManagementUrl(); - internal static Task WaitForCommandSubscriptionAsync(IServiceProvider services) - { - var queueName = services.GetRequiredService().QueueName; - return WaitUntilAsync("api/queues", root => root.EnumerateArray().Any(queue => - queue.TryGetProperty("name", out var name) && name.GetString() == queueName && - queue.TryGetProperty("consumers", out var consumers) && consumers.GetInt32() > 0), queueName); - } + internal static Task WaitForCommandSubscriptionAsync(IServiceProvider services) + { + var queueName = services.GetRequiredService().QueueName; + return WaitUntilAsync("api/queues", root => root.EnumerateArray().Any(queue => + queue.TryGetProperty("name", out var name) && name.GetString() == queueName && + queue.TryGetProperty("consumers", out var consumers) && consumers.GetInt32() > 0), queueName); + } - internal static Task WaitForEventSubscriptionAsync(IServiceProvider services) - { - var exchangeName = services.GetRequiredService().ExchangeName; - return WaitUntilAsync("api/bindings", root => root.EnumerateArray().Any(binding => - binding.TryGetProperty("source", out var source) && source.GetString() == exchangeName), exchangeName); - } + internal static Task WaitForEventSubscriptionAsync(IServiceProvider services) + { + var exchangeName = services.GetRequiredService().ExchangeName; + return WaitUntilAsync("api/bindings", root => root.EnumerateArray().Any(binding => + binding.TryGetProperty("source", out var source) && source.GetString() == exchangeName), exchangeName); + } + + private static Uri CreateManagementUrl() + { + var configured = Environment.GetEnvironmentVariable("SAVVYIO_RABBITMQ_MANAGEMENT_URL"); + if (!string.IsNullOrWhiteSpace(configured)) { return new Uri(configured.TrimEnd('/') + "/"); } - private static Uri CreateManagementUrl() + return new UriBuilder(Url) { - var configured = Environment.GetEnvironmentVariable("SAVVYIO_RABBITMQ_MANAGEMENT_URL"); - if (!string.IsNullOrWhiteSpace(configured)) { return new Uri(configured.TrimEnd('/') + "/"); } + Scheme = Uri.UriSchemeHttp, + Port = 15672, + Path = "/", + UserName = "", + Password = "" + }.Uri; + } - return new UriBuilder(Url) - { - Scheme = Uri.UriSchemeHttp, - Port = 15672, - Path = "/", - UserName = "", - Password = "" - }.Uri; - } + private static async Task WaitUntilAsync(string relativePath, Func predicate, string resourceName) + { + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + using var client = new HttpClient { BaseAddress = ManagementUrl }; + var credentials = string.IsNullOrWhiteSpace(Url.UserInfo) ? "guest:guest" : Uri.UnescapeDataString(Url.UserInfo); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials))); - private static async Task WaitUntilAsync(string relativePath, Func predicate, string resourceName) + try { - using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - using var client = new HttpClient { BaseAddress = ManagementUrl }; - var credentials = string.IsNullOrWhiteSpace(Url.UserInfo) ? "guest:guest" : Uri.UnescapeDataString(Url.UserInfo); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials))); - - try + while (!timeout.IsCancellationRequested) { - while (!timeout.IsCancellationRequested) + try { - try - { - using var response = await client.GetAsync(relativePath, timeout.Token).ConfigureAwait(false); - if (response.IsSuccessStatusCode) - { - await using var content = await response.Content.ReadAsStreamAsync(timeout.Token).ConfigureAwait(false); - using var document = await JsonDocument.ParseAsync(content, cancellationToken: timeout.Token).ConfigureAwait(false); - if (predicate(document.RootElement)) { return; } - } - } - catch (HttpRequestException) when (!timeout.IsCancellationRequested) + using var response = await client.GetAsync(relativePath, timeout.Token).ConfigureAwait(false); + if (response.IsSuccessStatusCode) { + await using var content = await response.Content.ReadAsStreamAsync(timeout.Token).ConfigureAwait(false); + using var document = await JsonDocument.ParseAsync(content, cancellationToken: timeout.Token).ConfigureAwait(false); + if (predicate(document.RootElement)) { return; } } - - await Task.Delay(50, timeout.Token).ConfigureAwait(false); } - } - catch (OperationCanceledException) when (timeout.IsCancellationRequested) - { - } + catch (HttpRequestException) when (!timeout.IsCancellationRequested) + { + } - throw new TimeoutException($"RabbitMQ subscription for '{resourceName}' was not ready within 10 seconds."); + await Task.Delay(50, timeout.Token).ConfigureAwait(false); + } } + catch (OperationCanceledException) when (timeout.IsCancellationRequested) + { + } + + throw new TimeoutException($"RabbitMQ subscription for '{resourceName}' was not ready within 10 seconds."); } } diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs index 99110cda..0cdbead6 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs @@ -2,60 +2,59 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +public class RabbitMqCommandQueueOptionsTest : Test { - public class RabbitMqCommandQueueOptionsTest : Test + public RabbitMqCommandQueueOptionsTest(ITestOutputHelper output) : base(output) { - public RabbitMqCommandQueueOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Set_Defaults() - { - var options = new RabbitMqCommandQueueOptions(); - - Assert.Null(options.QueueName); - Assert.False(options.AutoAcknowledge); - Assert.True(options.Durable); - Assert.False(options.Exclusive); - Assert.False(options.AutoDelete); - Assert.NotNull(options.AmqpUrl); - } - - [Fact] - public void ValidateOptions_Should_Throw_When_QueueName_Is_Null_Or_Empty() - { - var options = new RabbitMqCommandQueueOptions(); + [Fact] + public void Constructor_Should_Set_Defaults() + { + var options = new RabbitMqCommandQueueOptions(); + + Assert.Null(options.QueueName); + Assert.False(options.AutoAcknowledge); + Assert.True(options.Durable); + Assert.False(options.Exclusive); + Assert.False(options.AutoDelete); + Assert.NotNull(options.AmqpUrl); + } - Assert.Throws(() => options.ValidateOptions()); + [Fact] + public void ValidateOptions_Should_Throw_When_QueueName_Is_Null_Or_Empty() + { + var options = new RabbitMqCommandQueueOptions(); + + Assert.Throws(() => options.ValidateOptions()); - options.QueueName = ""; - Assert.Throws(() => options.ValidateOptions()); - } + options.QueueName = ""; + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_Should_Also_Throw_When_AmqpUrl_Is_Null() + [Fact] + public void ValidateOptions_Should_Also_Throw_When_AmqpUrl_Is_Null() + { + var options = new RabbitMqCommandQueueOptions { - var options = new RabbitMqCommandQueueOptions - { - QueueName = "test-queue", - AmqpUrl = null - }; + QueueName = "test-queue", + AmqpUrl = null + }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_Should_Not_Throw_When_QueueName_Is_Set() + [Fact] + public void ValidateOptions_Should_Not_Throw_When_QueueName_Is_Set() + { + var options = new RabbitMqCommandQueueOptions { - var options = new RabbitMqCommandQueueOptions - { - QueueName = "test-queue" - }; - - var exception = Record.Exception(() => options.ValidateOptions()); - Assert.Null(exception); - } + QueueName = "test-queue" + }; + + var exception = Record.Exception(() => options.ValidateOptions()); + Assert.Null(exception); } } diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueTest.cs index 747c099d..0b8312c9 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueTest.cs @@ -14,154 +14,153 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.Commands +namespace Savvyio.Extensions.RabbitMQ.Commands; + +public class RabbitMqCommandQueueTest : Test { - public class RabbitMqCommandQueueTest : Test + public RabbitMqCommandQueueTest(ITestOutputHelper output) : base(output) { - public RabbitMqCommandQueueTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void Constructor_Should_Throw_When_Marshaller_Is_Null() - { - Assert.Throws(() => new RabbitMqCommandQueue(null, CreateOptions())); - } - - [Fact] - public void Constructor_Should_Throw_When_Options_Are_Invalid() - { - Assert.Throws(() => new RabbitMqCommandQueue(JsonMarshaller.Default, new RabbitMqCommandQueueOptions())); - } - - [Fact] - public async Task SendAsync_Should_Declare_Queue_And_Publish_Each_Message() - { - var options = CreateOptions(o => o.Persistent = true); - var channel = new Mock(); - BasicProperties publishedProperties = null; - - channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); - channel.Setup(c => c.BasicPublishAsync("", options.QueueName, true, It.IsAny(), It.IsAny>(), It.IsAny())) - .Callback, CancellationToken>((_, _, _, properties, _, _) => publishedProperties = properties) - .Returns(ValueTask.CompletedTask); - - var sut = CreateSut(channel.Object, options); - var messages = new IMessage[] - { - new Message("id-1", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), - new Message("id-2", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow) - }; + } - await sut.SendAsync(messages); + [Fact] + public void Constructor_Should_Throw_When_Marshaller_Is_Null() + { + Assert.Throws(() => new RabbitMqCommandQueue(null, CreateOptions())); + } - channel.Verify(c => c.QueueDeclareAsync(options.QueueName, options.Durable, options.Exclusive, options.AutoDelete, null, false, false, It.IsAny()), Times.Once); - channel.Verify(c => c.BasicPublishAsync("", options.QueueName, true, It.IsAny(), It.IsAny>(), It.IsAny()), Times.Exactly(2)); - Assert.True(publishedProperties.Persistent); - Assert.Equal($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}", publishedProperties.Headers["type"]); - } + [Fact] + public void Constructor_Should_Throw_When_Options_Are_Invalid() + { + Assert.Throws(() => new RabbitMqCommandQueue(JsonMarshaller.Default, new RabbitMqCommandQueueOptions())); + } - [Fact] - public async Task ReceiveAsync_Should_Acknowledge_Message_When_Requested() + [Fact] + public async Task SendAsync_Should_Declare_Queue_And_Publish_Each_Message() + { + var options = CreateOptions(o => o.Persistent = true); + var channel = new Mock(); + BasicProperties publishedProperties = null; + + channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); + channel.Setup(c => c.BasicPublishAsync("", options.QueueName, true, It.IsAny(), It.IsAny>(), It.IsAny())) + .Callback, CancellationToken>((_, _, _, properties, _, _) => publishedProperties = properties) + .Returns(ValueTask.CompletedTask); + + var sut = CreateSut(channel.Object, options); + var messages = new IMessage[] { - var options = CreateOptions(); - var channel = new Mock(); - var consumerSource = new TaskCompletionSource(); - - channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); - channel.Setup(c => c.BasicConsumeAsync(options.QueueName, false, string.Empty, false, false, null, It.IsAny(), It.IsAny())) - .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) - .ReturnsAsync("consumer-tag"); - channel.Setup(c => c.BasicAckAsync(77UL, false, It.IsAny())).Returns(ValueTask.CompletedTask); + new Message("id-1", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), + new Message("id-2", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow) + }; - var sut = CreateSut(channel.Object, options); - await using var enumerator = sut.ReceiveAsync().GetAsyncEnumerator(); - var moveNext = enumerator.MoveNextAsync().AsTask(); - var consumer = await consumerSource.Task.ConfigureAwait(false); + await sut.SendAsync(messages); - await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-1", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), 77UL, options.QueueName).ConfigureAwait(false); + channel.Verify(c => c.QueueDeclareAsync(options.QueueName, options.Durable, options.Exclusive, options.AutoDelete, null, false, false, It.IsAny()), Times.Once); + channel.Verify(c => c.BasicPublishAsync("", options.QueueName, true, It.IsAny(), It.IsAny>(), It.IsAny()), Times.Exactly(2)); + Assert.True(publishedProperties.Persistent); + Assert.Equal($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}", publishedProperties.Headers["type"]); + } - Assert.True(await moveNext.ConfigureAwait(false)); - var message = enumerator.Current; + [Fact] + public async Task ReceiveAsync_Should_Acknowledge_Message_When_Requested() + { + var options = CreateOptions(); + var channel = new Mock(); + var consumerSource = new TaskCompletionSource(); - Assert.Equal(77UL, message.Properties[nameof(BasicDeliverEventArgs.DeliveryTag)]); - Assert.Equal(options.QueueName, message.Properties[nameof(QueueDeclareOk.QueueName)]); + channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); + channel.Setup(c => c.BasicConsumeAsync(options.QueueName, false, string.Empty, false, false, null, It.IsAny(), It.IsAny())) + .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) + .ReturnsAsync("consumer-tag"); + channel.Setup(c => c.BasicAckAsync(77UL, false, It.IsAny())).Returns(ValueTask.CompletedTask); - await message.AcknowledgeAsync().ConfigureAwait(false); + var sut = CreateSut(channel.Object, options); + await using var enumerator = sut.ReceiveAsync().GetAsyncEnumerator(); + var moveNext = enumerator.MoveNextAsync().AsTask(); + var consumer = await consumerSource.Task.ConfigureAwait(false); - channel.Verify(c => c.BasicAckAsync(77UL, false, It.IsAny()), Times.Once); - channel.Verify(c => c.QueueDeclareAsync(options.QueueName, options.Durable, options.Exclusive, options.AutoDelete, null, false, false, It.IsAny()), Times.Exactly(2)); - } + await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-1", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), 77UL, options.QueueName).ConfigureAwait(false); - [Fact] - public async Task ReceiveAsync_Should_Auto_Acknowledge_Message_When_Configured() - { - var options = CreateOptions(o => o.AutoAcknowledge = true); - var channel = new Mock(); - var consumerSource = new TaskCompletionSource(); + Assert.True(await moveNext.ConfigureAwait(false)); + var message = enumerator.Current; - channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); - channel.Setup(c => c.BasicConsumeAsync(options.QueueName, false, string.Empty, false, false, null, It.IsAny(), It.IsAny())) - .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) - .ReturnsAsync("consumer-tag"); - channel.Setup(c => c.BasicAckAsync(88UL, false, It.IsAny())).Returns(ValueTask.CompletedTask); + Assert.Equal(77UL, message.Properties[nameof(BasicDeliverEventArgs.DeliveryTag)]); + Assert.Equal(options.QueueName, message.Properties[nameof(QueueDeclareOk.QueueName)]); - var sut = CreateSut(channel.Object, options); - await using var enumerator = sut.ReceiveAsync().GetAsyncEnumerator(); - var moveNext = enumerator.MoveNextAsync().AsTask(); - var consumer = await consumerSource.Task.ConfigureAwait(false); + await message.AcknowledgeAsync().ConfigureAwait(false); - await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-2", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), 88UL, options.QueueName).ConfigureAwait(false); + channel.Verify(c => c.BasicAckAsync(77UL, false, It.IsAny()), Times.Once); + channel.Verify(c => c.QueueDeclareAsync(options.QueueName, options.Durable, options.Exclusive, options.AutoDelete, null, false, false, It.IsAny()), Times.Exactly(2)); + } - Assert.True(await moveNext.ConfigureAwait(false)); - channel.Verify(c => c.BasicAckAsync(88UL, false, It.IsAny()), Times.Once); - } + [Fact] + public async Task ReceiveAsync_Should_Auto_Acknowledge_Message_When_Configured() + { + var options = CreateOptions(o => o.AutoAcknowledge = true); + var channel = new Mock(); + var consumerSource = new TaskCompletionSource(); + + channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new QueueDeclareOk(options.QueueName, 0, 0)); + channel.Setup(c => c.BasicConsumeAsync(options.QueueName, false, string.Empty, false, false, null, It.IsAny(), It.IsAny())) + .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) + .ReturnsAsync("consumer-tag"); + channel.Setup(c => c.BasicAckAsync(88UL, false, It.IsAny())).Returns(ValueTask.CompletedTask); + + var sut = CreateSut(channel.Object, options); + await using var enumerator = sut.ReceiveAsync().GetAsyncEnumerator(); + var moveNext = enumerator.MoveNextAsync().AsTask(); + var consumer = await consumerSource.Task.ConfigureAwait(false); + + await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-2", new Uri("urn:command:test"), "command.test", new TestCommand(), DateTime.UtcNow), 88UL, options.QueueName).ConfigureAwait(false); + + Assert.True(await moveNext.ConfigureAwait(false)); + channel.Verify(c => c.BasicAckAsync(88UL, false, It.IsAny()), Times.Once); + } - private static RabbitMqCommandQueue CreateSut(IChannel channel, RabbitMqCommandQueueOptions options) - { - var connection = new Mock(); - connection.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channel); + private static RabbitMqCommandQueue CreateSut(IChannel channel, RabbitMqCommandQueueOptions options) + { + var connection = new Mock(); + connection.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channel); - var factory = new Mock(); - factory.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connection.Object); + var factory = new Mock(); + factory.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connection.Object); - var sut = new RabbitMqCommandQueue(JsonMarshaller.Default, options); - typeof(RabbitMqMessage) - .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)! - .SetValue(sut, factory.Object); - return sut; - } + var sut = new RabbitMqCommandQueue(JsonMarshaller.Default, options); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)! + .SetValue(sut, factory.Object); + return sut; + } - private static RabbitMqCommandQueueOptions CreateOptions(Action setup = null) + private static RabbitMqCommandQueueOptions CreateOptions(Action setup = null) + { + var options = new RabbitMqCommandQueueOptions { - var options = new RabbitMqCommandQueueOptions - { - QueueName = "orders" - }; - setup?.Invoke(options); - return options; - } + QueueName = "orders" + }; + setup?.Invoke(options); + return options; + } - private static async Task PublishDeliveredMessageAsync(AsyncEventingBasicConsumer consumer, Message message, ulong deliveryTag, string queueName) + private static async Task PublishDeliveredMessageAsync(AsyncEventingBasicConsumer consumer, Message message, ulong deliveryTag, string queueName) + { + var body = await JsonMarshaller.Default.Serialize(message).ToByteArrayAsync().ConfigureAwait(false); + var properties = new BasicProperties { - var body = await JsonMarshaller.Default.Serialize(message).ToByteArrayAsync().ConfigureAwait(false); - var properties = new BasicProperties + Headers = new Dictionary { - Headers = new Dictionary - { - ["type"] = Encoding.UTF8.GetBytes($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}") - } - }; + ["type"] = Encoding.UTF8.GetBytes($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}") + } + }; - await consumer.HandleBasicDeliverAsync("consumer-tag", deliveryTag, false, string.Empty, queueName, properties, body, CancellationToken.None).ConfigureAwait(false); - } + await consumer.HandleBasicDeliverAsync("consumer-tag", deliveryTag, false, string.Empty, queueName, properties, body, CancellationToken.None).ConfigureAwait(false); + } - private sealed class TestCommand : ICommand - { - public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); - } + private sealed class TestCommand : ICommand + { + public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); } } diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs index e3775f39..8010f127 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs @@ -2,57 +2,56 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +public class RabbitMqEventBusOptionsTest : Test { - public class RabbitMqEventBusOptionsTest : Test + public RabbitMqEventBusOptionsTest(ITestOutputHelper output) : base(output) { - public RabbitMqEventBusOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Set_Defaults() - { - var options = new RabbitMqEventBusOptions(); + [Fact] + public void Constructor_Should_Set_Defaults() + { + var options = new RabbitMqEventBusOptions(); - Assert.Null(options.ExchangeName); - Assert.NotNull(options.AmqpUrl); - Assert.Equal(new Uri("amqp://localhost:5672"), options.AmqpUrl); - } + Assert.Null(options.ExchangeName); + Assert.NotNull(options.AmqpUrl); + Assert.Equal(new Uri("amqp://localhost:5672"), options.AmqpUrl); + } - [Fact] - public void ValidateOptions_Should_Throw_When_ExchangeName_Is_Null_Or_Empty() - { - var options = new RabbitMqEventBusOptions(); + [Fact] + public void ValidateOptions_Should_Throw_When_ExchangeName_Is_Null_Or_Empty() + { + var options = new RabbitMqEventBusOptions(); - Assert.Throws(() => options.ValidateOptions()); + Assert.Throws(() => options.ValidateOptions()); - options.ExchangeName = ""; - Assert.Throws(() => options.ValidateOptions()); - } + options.ExchangeName = ""; + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_Should_Also_Throw_When_AmqpUrl_Is_Null() + [Fact] + public void ValidateOptions_Should_Also_Throw_When_AmqpUrl_Is_Null() + { + var options = new RabbitMqEventBusOptions { - var options = new RabbitMqEventBusOptions - { - ExchangeName = "test-exchange", - AmqpUrl = null - }; + ExchangeName = "test-exchange", + AmqpUrl = null + }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_Should_Not_Throw_When_ExchangeName_Is_Set() + [Fact] + public void ValidateOptions_Should_Not_Throw_When_ExchangeName_Is_Set() + { + var options = new RabbitMqEventBusOptions { - var options = new RabbitMqEventBusOptions - { - ExchangeName = "test-exchange" - }; - - var exception = Record.Exception(() => options.ValidateOptions()); - Assert.Null(exception); - } + ExchangeName = "test-exchange" + }; + + var exception = Record.Exception(() => options.ValidateOptions()); + Assert.Null(exception); } -} \ No newline at end of file +} diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusTest.cs index b6b4f504..afe62393 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusTest.cs @@ -14,139 +14,138 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.RabbitMQ.EventDriven +namespace Savvyio.Extensions.RabbitMQ.EventDriven; + +public class RabbitMqEventBusTest : Test { - public class RabbitMqEventBusTest : Test + public RabbitMqEventBusTest(ITestOutputHelper output) : base(output) { - public RabbitMqEventBusTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Throw_When_Marshaller_Is_Null() - { - Assert.Throws(() => new RabbitMqEventBus(null, CreateOptions())); - } + [Fact] + public void Constructor_Should_Throw_When_Marshaller_Is_Null() + { + Assert.Throws(() => new RabbitMqEventBus(null, CreateOptions())); + } - [Fact] - public void Constructor_Should_Throw_When_Options_Are_Invalid() - { - Assert.Throws(() => new RabbitMqEventBus(JsonMarshaller.Default, new RabbitMqEventBusOptions())); - } + [Fact] + public void Constructor_Should_Throw_When_Options_Are_Invalid() + { + Assert.Throws(() => new RabbitMqEventBus(JsonMarshaller.Default, new RabbitMqEventBusOptions())); + } - [Fact] - public async Task PublishAsync_Should_Declare_Exchange_And_Publish_Message() - { - var options = CreateOptions(o => o.Persistent = true); - var channel = new Mock(); - BasicProperties publishedProperties = null; + [Fact] + public async Task PublishAsync_Should_Declare_Exchange_And_Publish_Message() + { + var options = CreateOptions(o => o.Persistent = true); + var channel = new Mock(); + BasicProperties publishedProperties = null; - channel.Setup(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny())) - .Returns(Task.CompletedTask); - channel.Setup(c => c.BasicPublishAsync(options.ExchangeName, string.Empty, false, It.IsAny(), It.IsAny>(), It.IsAny())) - .Callback, CancellationToken>((_, _, _, properties, _, _) => publishedProperties = properties) - .Returns(ValueTask.CompletedTask); + channel.Setup(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny())) + .Returns(Task.CompletedTask); + channel.Setup(c => c.BasicPublishAsync(options.ExchangeName, string.Empty, false, It.IsAny(), It.IsAny>(), It.IsAny())) + .Callback, CancellationToken>((_, _, _, properties, _, _) => publishedProperties = properties) + .Returns(ValueTask.CompletedTask); - var sut = CreateSut(channel.Object, options); - var message = new Message("id-1", new Uri("urn:event:test"), "event.test", new TestIntegrationEvent(), DateTime.UtcNow); + var sut = CreateSut(channel.Object, options); + var message = new Message("id-1", new Uri("urn:event:test"), "event.test", new TestIntegrationEvent(), DateTime.UtcNow); - await sut.PublishAsync(message); + await sut.PublishAsync(message); - channel.Verify(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny()), Times.Once); - channel.Verify(c => c.BasicPublishAsync(options.ExchangeName, string.Empty, false, It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); - Assert.True(publishedProperties.Persistent); - Assert.Equal($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}", publishedProperties.Headers["type"]); - } + channel.Verify(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny()), Times.Once); + channel.Verify(c => c.BasicPublishAsync(options.ExchangeName, string.Empty, false, It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); + Assert.True(publishedProperties.Persistent); + Assert.Equal($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}", publishedProperties.Headers["type"]); + } - [Fact] - public async Task SubscribeAsync_Should_Invoke_Handler_For_Received_Message() + [Fact] + public async Task SubscribeAsync_Should_Invoke_Handler_For_Received_Message() + { + var options = CreateOptions(); + var channel = new Mock(); + var consumerSource = new TaskCompletionSource(); + var handled = 0; + IMessage received = null; + using var cts = new CancellationTokenSource(); + + channel.Setup(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny())) + .Returns(Task.CompletedTask); + channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new QueueDeclareOk("events-queue", 0, 0)); + channel.Setup(c => c.QueueBindAsync("events-queue", options.ExchangeName, string.Empty, null, false, It.IsAny())) + .Returns(Task.CompletedTask); + channel.Setup(c => c.BasicConsumeAsync("events-queue", true, string.Empty, false, false, null, It.IsAny(), It.IsAny())) + .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) + .ReturnsAsync("consumer-tag"); + + var sut = CreateSut(channel.Object, options); + var subscribeTask = sut.SubscribeAsync((message, token) => { - var options = CreateOptions(); - var channel = new Mock(); - var consumerSource = new TaskCompletionSource(); - var handled = 0; - IMessage received = null; - using var cts = new CancellationTokenSource(); - - channel.Setup(c => c.ExchangeDeclareAsync(options.ExchangeName, ExchangeType.Fanout, false, false, null, false, false, It.IsAny())) - .Returns(Task.CompletedTask); - channel.Setup(c => c.QueueDeclareAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(new QueueDeclareOk("events-queue", 0, 0)); - channel.Setup(c => c.QueueBindAsync("events-queue", options.ExchangeName, string.Empty, null, false, It.IsAny())) - .Returns(Task.CompletedTask); - channel.Setup(c => c.BasicConsumeAsync("events-queue", true, string.Empty, false, false, null, It.IsAny(), It.IsAny())) - .Callback, IAsyncBasicConsumer, CancellationToken>((_, _, _, _, _, _, consumer, _) => consumerSource.TrySetResult(consumer)) - .ReturnsAsync("consumer-tag"); - - var sut = CreateSut(channel.Object, options); - var subscribeTask = sut.SubscribeAsync((message, token) => - { - handled++; - received = message; - cts.Cancel(); - return Task.CompletedTask; - }, o => o.CancellationToken = cts.Token); + handled++; + received = message; + cts.Cancel(); + return Task.CompletedTask; + }, o => o.CancellationToken = cts.Token); - var consumer = await consumerSource.Task.ConfigureAwait(false); - await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-2", new Uri("urn:event:test"), "event.test", new TestIntegrationEvent(), DateTime.UtcNow), 91UL).ConfigureAwait(false); + var consumer = await consumerSource.Task.ConfigureAwait(false); + await PublishDeliveredMessageAsync((AsyncEventingBasicConsumer)consumer, new Message("id-2", new Uri("urn:event:test"), "event.test", new TestIntegrationEvent(), DateTime.UtcNow), 91UL).ConfigureAwait(false); - try - { - await subscribeTask.ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // expected: the subscription loop exits when the token is cancelled inside the handler - } - - Assert.Equal(1, handled); - Assert.NotNull(received); - Assert.Equal(91UL, received.Properties[nameof(BasicDeliverEventArgs.DeliveryTag)]); - Assert.Equal("events-queue", received.Properties[nameof(QueueDeclareOk.QueueName)]); + try + { + await subscribeTask.ConfigureAwait(false); } - - private static RabbitMqEventBus CreateSut(IChannel channel, RabbitMqEventBusOptions options) + catch (OperationCanceledException) { - var connection = new Mock(); - connection.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channel); + // expected: the subscription loop exits when the token is cancelled inside the handler + } - var factory = new Mock(); - factory.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connection.Object); + Assert.Equal(1, handled); + Assert.NotNull(received); + Assert.Equal(91UL, received.Properties[nameof(BasicDeliverEventArgs.DeliveryTag)]); + Assert.Equal("events-queue", received.Properties[nameof(QueueDeclareOk.QueueName)]); + } - var sut = new RabbitMqEventBus(JsonMarshaller.Default, options); - typeof(RabbitMqMessage) - .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)! - .SetValue(sut, factory.Object); - return sut; - } + private static RabbitMqEventBus CreateSut(IChannel channel, RabbitMqEventBusOptions options) + { + var connection = new Mock(); + connection.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channel); + + var factory = new Mock(); + factory.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connection.Object); - private static RabbitMqEventBusOptions CreateOptions(Action setup = null) + var sut = new RabbitMqEventBus(JsonMarshaller.Default, options); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)! + .SetValue(sut, factory.Object); + return sut; + } + + private static RabbitMqEventBusOptions CreateOptions(Action setup = null) + { + var options = new RabbitMqEventBusOptions { - var options = new RabbitMqEventBusOptions - { - ExchangeName = "events" - }; - setup?.Invoke(options); - return options; - } + ExchangeName = "events" + }; + setup?.Invoke(options); + return options; + } - private static async Task PublishDeliveredMessageAsync(AsyncEventingBasicConsumer consumer, Message message, ulong deliveryTag) + private static async Task PublishDeliveredMessageAsync(AsyncEventingBasicConsumer consumer, Message message, ulong deliveryTag) + { + var body = await JsonMarshaller.Default.Serialize(message).ToByteArrayAsync().ConfigureAwait(false); + var properties = new BasicProperties { - var body = await JsonMarshaller.Default.Serialize(message).ToByteArrayAsync().ConfigureAwait(false); - var properties = new BasicProperties + Headers = new Dictionary { - Headers = new Dictionary - { - ["type"] = Encoding.UTF8.GetBytes($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}") - } - }; + ["type"] = Encoding.UTF8.GetBytes($"{typeof(Message).FullName}, {typeof(Message).Assembly.GetName().Name}") + } + }; - await consumer.HandleBasicDeliverAsync("consumer-tag", deliveryTag, false, string.Empty, string.Empty, properties, body, CancellationToken.None).ConfigureAwait(false); - } + await consumer.HandleBasicDeliverAsync("consumer-tag", deliveryTag, false, string.Empty, string.Empty, properties, body, CancellationToken.None).ConfigureAwait(false); + } - private sealed class TestIntegrationEvent : IIntegrationEvent - { - public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); - } + private sealed class TestIntegrationEvent : IIntegrationEvent + { + public IMetadataDictionary Metadata { get; } = new MetadataDictionary(); } } diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs index 4e7a5201..0715c7de 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs @@ -2,56 +2,55 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +public class RabbitMqMessageOptionsTest : Test { - public class RabbitMqMessageOptionsTest : Test + public RabbitMqMessageOptionsTest(ITestOutputHelper output) : base(output) { - public RabbitMqMessageOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Set_Default_AmqpUrl() - { - var options = new RabbitMqMessageOptions(); + [Fact] + public void Constructor_Should_Set_Default_AmqpUrl() + { + var options = new RabbitMqMessageOptions(); - Assert.NotNull(options.AmqpUrl); - Assert.False(options.Persistent); - Assert.Equal(new Uri("amqp://localhost:5672"), options.AmqpUrl); - } + Assert.NotNull(options.AmqpUrl); + Assert.False(options.Persistent); + Assert.Equal(new Uri("amqp://localhost:5672"), options.AmqpUrl); + } - [Fact] - public void Persistent_Should_Be_Settable() + [Fact] + public void Persistent_Should_Be_Settable() + { + var options = new RabbitMqMessageOptions { - var options = new RabbitMqMessageOptions - { - Persistent = true - }; + Persistent = true + }; - Assert.True(options.Persistent); - } + Assert.True(options.Persistent); + } - [Fact] - public void ValidateOptions_Should_Throw_When_AmqpUrl_Is_Null() + [Fact] + public void ValidateOptions_Should_Throw_When_AmqpUrl_Is_Null() + { + var options = new RabbitMqMessageOptions { - var options = new RabbitMqMessageOptions - { - AmqpUrl = null - }; + AmqpUrl = null + }; - Assert.Throws(() => options.ValidateOptions()); - } + Assert.Throws(() => options.ValidateOptions()); + } - [Fact] - public void ValidateOptions_Should_Not_Throw_When_AmqpUrl_Is_Set() + [Fact] + public void ValidateOptions_Should_Not_Throw_When_AmqpUrl_Is_Set() + { + var options = new RabbitMqMessageOptions { - var options = new RabbitMqMessageOptions - { - AmqpUrl = new Uri("amqp://localhost:5672") - }; - - var exception = Record.Exception(() => options.ValidateOptions()); - Assert.Null(exception); - } + AmqpUrl = new Uri("amqp://localhost:5672") + }; + + var exception = Record.Exception(() => options.ValidateOptions()); + Assert.Null(exception); } } diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs index 4723f6c1..2f58d57f 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs @@ -7,155 +7,154 @@ using System.Threading.Tasks; using Xunit; -namespace Savvyio.Extensions.RabbitMQ +namespace Savvyio.Extensions.RabbitMQ; + +public class RabbitMqMessageTest : Test { - public class RabbitMqMessageTest : Test + public RabbitMqMessageTest(ITestOutputHelper output) : base(output) { - public RabbitMqMessageTest(ITestOutputHelper output) : base(output) - { - } + } - private sealed class TestRabbitMqMessage : RabbitMqMessage + private sealed class TestRabbitMqMessage : RabbitMqMessage + { + public TestRabbitMqMessage(IMarshaller marshaller, RabbitMqMessageOptions options) : base(marshaller, options) { - public TestRabbitMqMessage(IMarshaller marshaller, RabbitMqMessageOptions options) : base(marshaller, options) - { - } - - public Task CallEnsureConnectivityAsync(CancellationToken ct = default) => EnsureConnectivityAsync(ct); - - public ValueTask CallOnDisposeManagedResourcesAsync() => OnDisposeManagedResourcesAsync(); - - public void SetConnection(IConnection connection) - { - typeof(RabbitMqMessage) - .GetProperty("RabbitMqConnection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .SetValue(this, connection); - } - - public void SetChannel(IChannel channel) - { - typeof(RabbitMqMessage) - .GetProperty("RabbitMqChannel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .SetValue(this, channel); - } } - [Fact] - public void Constructor_Throws_WhenMarshallerIsNull() + public Task CallEnsureConnectivityAsync(CancellationToken ct = default) => EnsureConnectivityAsync(ct); + + public ValueTask CallOnDisposeManagedResourcesAsync() => OnDisposeManagedResourcesAsync(); + + public void SetConnection(IConnection connection) { - var options = new RabbitMqMessageOptions(); - Assert.Throws(() => new TestRabbitMqMessage(null, options)); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqConnection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! + .SetValue(this, connection); } - [Fact] - public void Constructor_Throws_WhenOptionsIsNull() + public void SetChannel(IChannel channel) { - Assert.Throws(() => new TestRabbitMqMessage(JsonMarshaller.Default, null)); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqChannel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! + .SetValue(this, channel); } + } - [Fact] - public void Constructor_SetsProperties() - { - var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); + [Fact] + public void Constructor_Throws_WhenMarshallerIsNull() + { + var options = new RabbitMqMessageOptions(); + Assert.Throws(() => new TestRabbitMqMessage(null, options)); + } - Assert.NotNull(sut); - Assert.NotNull(typeof(RabbitMqMessage).GetProperty("Marshaller", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); - Assert.NotNull(typeof(RabbitMqMessage).GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); - } + [Fact] + public void Constructor_Throws_WhenOptionsIsNull() + { + Assert.Throws(() => new TestRabbitMqMessage(JsonMarshaller.Default, null)); + } - [Fact] - public async Task EnsureConnectivityAsync_InitializesConnectionAndChannel_Once() - { - var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; - var connectionMock = new Mock(); - var channelMock = new Mock(); - connectionMock.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channelMock.Object); + [Fact] + public void Constructor_SetsProperties() + { + var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); - var factoryMock = new Mock(); - factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock.Object); + Assert.NotNull(sut); + Assert.NotNull(typeof(RabbitMqMessage).GetProperty("Marshaller", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); + Assert.NotNull(typeof(RabbitMqMessage).GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); + } - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); - typeof(RabbitMqMessage) - .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .SetValue(sut, factoryMock.Object); + [Fact] + public async Task EnsureConnectivityAsync_InitializesConnectionAndChannel_Once() + { + var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; + var connectionMock = new Mock(); + var channelMock = new Mock(); + connectionMock.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channelMock.Object); - await sut.CallEnsureConnectivityAsync(); - await sut.CallEnsureConnectivityAsync(); + var factoryMock = new Mock(); + factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock.Object); - Assert.Same(connectionMock.Object, typeof(RabbitMqMessage).GetProperty("RabbitMqConnection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); - Assert.Same(channelMock.Object, typeof(RabbitMqMessage).GetProperty("RabbitMqChannel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); - factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); - } + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! + .SetValue(sut, factoryMock.Object); - [Fact] - public async Task EnsureConnectivityAsync_IsThreadSafe_WhenCalledConcurrently() - { - var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; - var connectionMock = new Mock(); - var channelMock = new Mock(); - connectionMock.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channelMock.Object); + await sut.CallEnsureConnectivityAsync(); + await sut.CallEnsureConnectivityAsync(); - var factoryMock = new Mock(); - factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock.Object); + Assert.Same(connectionMock.Object, typeof(RabbitMqMessage).GetProperty("RabbitMqConnection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); + Assert.Same(channelMock.Object, typeof(RabbitMqMessage).GetProperty("RabbitMqChannel", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!.GetValue(sut)); + factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); + } - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); - typeof(RabbitMqMessage) - .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .SetValue(sut, factoryMock.Object); + [Fact] + public async Task EnsureConnectivityAsync_IsThreadSafe_WhenCalledConcurrently() + { + var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; + var connectionMock = new Mock(); + var channelMock = new Mock(); + connectionMock.Setup(c => c.CreateChannelAsync(It.IsAny(), It.IsAny())).ReturnsAsync(channelMock.Object); - await Task.WhenAll(sut.CallEnsureConnectivityAsync(), sut.CallEnsureConnectivityAsync()); + var factoryMock = new Mock(); + factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock.Object); - factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); - } + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, options); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! + .SetValue(sut, factoryMock.Object); - [Fact] - public async Task OnDisposeManagedResourcesAsync_DisposesChannelAndConnection() - { - var channelMock = new Mock(); - channelMock.Setup(c => c.DisposeAsync()).Returns(ValueTask.CompletedTask).Verifiable(); + await Task.WhenAll(sut.CallEnsureConnectivityAsync(), sut.CallEnsureConnectivityAsync()); - var connectionMock = new Mock(); - connectionMock.Setup(c => c.DisposeAsync()).Returns(ValueTask.CompletedTask).Verifiable(); + factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); + } - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); - sut.SetChannel(channelMock.Object); - sut.SetConnection(connectionMock.Object); + [Fact] + public async Task OnDisposeManagedResourcesAsync_DisposesChannelAndConnection() + { + var channelMock = new Mock(); + channelMock.Setup(c => c.DisposeAsync()).Returns(ValueTask.CompletedTask).Verifiable(); - await sut.CallOnDisposeManagedResourcesAsync(); + var connectionMock = new Mock(); + connectionMock.Setup(c => c.DisposeAsync()).Returns(ValueTask.CompletedTask).Verifiable(); - channelMock.Verify(c => c.DisposeAsync(), Times.Once); - connectionMock.Verify(c => c.DisposeAsync(), Times.Once); - } + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); + sut.SetChannel(channelMock.Object); + sut.SetConnection(connectionMock.Object); - [Fact] - public async Task GetHealthCheckTargetAsync_ReturnsExistingConnection_IfInitialized() - { - var connectionMock = new Mock().Object; - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); - sut.SetConnection(connectionMock); + await sut.CallOnDisposeManagedResourcesAsync(); - var result = await sut.GetHealthCheckTargetAsync(); + channelMock.Verify(c => c.DisposeAsync(), Times.Once); + connectionMock.Verify(c => c.DisposeAsync(), Times.Once); + } - Assert.Same(connectionMock, result); - } + [Fact] + public async Task GetHealthCheckTargetAsync_ReturnsExistingConnection_IfInitialized() + { + var connectionMock = new Mock().Object; + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); + sut.SetConnection(connectionMock); - [Fact] - public async Task GetHealthCheckTargetAsync_CreatesConnection_IfNotInitialized() - { - var connectionMock = new Mock().Object; - var factoryMock = new Mock(); - factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock); + var result = await sut.GetHealthCheckTargetAsync(); - var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); - typeof(RabbitMqMessage) - .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .SetValue(sut, factoryMock.Object); + Assert.Same(connectionMock, result); + } - var result = await sut.GetHealthCheckTargetAsync(); + [Fact] + public async Task GetHealthCheckTargetAsync_CreatesConnection_IfNotInitialized() + { + var connectionMock = new Mock().Object; + var factoryMock = new Mock(); + factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny())).ReturnsAsync(connectionMock); - Assert.Same(connectionMock, result); - factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); - } + var sut = new TestRabbitMqMessage(JsonMarshaller.Default, new RabbitMqMessageOptions()); + typeof(RabbitMqMessage) + .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! + .SetValue(sut, factoryMock.Object); + + var result = await sut.GetHealthCheckTargetAsync(); + + Assert.Same(connectionMock, result); + factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny()), Times.Once); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs index d3fa9beb..9619af17 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,20 +1,19 @@ using Savvyio.Commands; -namespace Savvyio.Extensions.SimpleQueueService.Assets +namespace Savvyio.Extensions.SimpleQueueService.Assets; + +internal record CreateMemberCommand : Command { - internal record CreateMemberCommand : Command + public CreateMemberCommand(string name, byte age, string emailAddress) { - public CreateMemberCommand(string name, byte age, string emailAddress) - { - Name = name; - Age = age; - EmailAddress = emailAddress; - } + Name = name; + Age = age; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public byte Age { get; } + public byte Age { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs index 66336e24..4a6ac4e2 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs @@ -1,17 +1,16 @@ using Savvyio.EventDriven; -namespace Savvyio.Extensions.SimpleQueueService.Assets +namespace Savvyio.Extensions.SimpleQueueService.Assets; + +public record MemberCreated : IntegrationEvent { - public record MemberCreated : IntegrationEvent + public MemberCreated(string name, string emailAddress) { - public MemberCreated(string name, string emailAddress) - { - Name = name; - EmailAddress = emailAddress; - } + Name = name; + EmailAddress = emailAddress; + } - public string Name { get; } + public string Name { get; } - public string EmailAddress { get; } - } + public string EmailAddress { get; } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs index 0bba7769..9cbdf692 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs @@ -25,154 +25,153 @@ using Savvyio.Messaging.Cryptography; using Xunit.v3.Priority; -namespace Savvyio.Extensions.SimpleQueueService.Commands +namespace Savvyio.Extensions.SimpleQueueService.Commands; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AmazonCommandQueueJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AmazonCommandQueueJsonSerializerContextTest : HostTest + private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + private readonly AmazonCommandQueue _queue; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly IMarshaller _marshaller; + + public AmazonCommandQueueJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - private readonly AmazonCommandQueue _queue; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly IMarshaller _marshaller; + _queue = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AmazonCommandQueueJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _queue = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + IMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - IMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); - } - - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); } - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members/signed".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members/signed".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); - } + Comparer.Add(sut3); - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); + await _queue.SendAsync(sut3.Yield()).ConfigureAwait(false); + } - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - ISignedMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; - sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - } + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + ISignedMessage sut2 = null; + while (sut2 == null) + { + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; + sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); } - [Fact, Priority(4)] - public async Task SendAsync_CreateMemberCommand_HundredTimes() + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } + + [Fact, Priority(4)] + public async Task SendAsync_CreateMemberCommand_HundredTimes() + { + var messages = Generate.RangeOf(100, i => { - 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)); - Comparer.Add(message); - return message; - }).ToList(); + 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)); + Comparer.Add(message); + return message; + }).ToList(); - var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); + var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); - TestOutput.WriteLine(profiler.ToString()); - } + TestOutput.WriteLine(profiler.ToString()); + } - [Fact, Priority(5)] - public async Task ReceiveAsync_CreateMemberCommand_All() - { - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; - var realizedCommands = new List>(); - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + [Fact, Priority(5)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; + var realizedCommands = new List>(); + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - while (realizedCommands.Count < sut1.Count) - { - realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).ToListAsync(ct).ConfigureAwait(false)); - } + while (realizedCommands.Count < sut1.Count) + { + realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).ToListAsync(ct).ConfigureAwait(false)); + } - TestOutput.WriteLine(realizedCommands.Count.ToString()); - TestOutput.WriteLines(realizedCommands.Take(10)); + TestOutput.WriteLine(realizedCommands.Count.ToString()); + TestOutput.WriteLines(realizedCommands.Take(10)); - Assert.Equivalent(sut1.Count, realizedCommands.Count); - Assert.Equivalent(sut1, realizedCommands); - Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); - } + Assert.Equivalent(sut1.Count, realizedCommands.Count); + Assert.Equivalent(sut1, realizedCommands); + Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + } - public override void ConfigureServices(IServiceCollection services) + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller(); + services.AddAmazonCommandQueue(o => { - services.AddMarshaller(); - services.AddAmazonCommandQueue(o => + var queue = IsLinux ? "savvyio-commands" : "savvyio-commands.fifo"; + o.Endpoint = RegionEndpoint.EUWest1; + if (Configuration["AWS:LocalStack"] != null) { - var queue = IsLinux ? "savvyio-commands" : "savvyio-commands.fifo"; - o.Endpoint = RegionEndpoint.EUWest1; - if (Configuration["AWS:LocalStack"] != null) + o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); + o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); + o.ConfigureClient(client => { - o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); - o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); - o.ConfigureClient(client => - { - client.ServiceURL = Configuration["AWS:LocalStack"]; - client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); - } - else - { - o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); - } - o.ReceiveContext.UseApproximateNumberOfMessages = true; - }); - } + client.ServiceURL = Configuration["AWS:LocalStack"]; + client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); + } + else + { + o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); + } + o.ReceiveContext.UseApproximateNumberOfMessages = true; + }); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs index 4488ba9a..3aecab51 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -25,154 +25,153 @@ using Savvyio.Messaging.Cryptography; using Xunit.v3.Priority; -namespace Savvyio.Extensions.SimpleQueueService.Commands +namespace Savvyio.Extensions.SimpleQueueService.Commands; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AmazonCommandQueueNewtonsoftJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AmazonCommandQueueNewtonsoftJsonSerializerContextTest : HostTest + private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + private readonly AmazonCommandQueue _queue; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly IMarshaller _marshaller; + + public AmazonCommandQueueNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - private readonly AmazonCommandQueue _queue; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly IMarshaller _marshaller; + _queue = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AmazonCommandQueueNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _queue = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _queue.SendAsync(sut3.Yield()); + } - await _queue.SendAsync(sut3.Yield()); - } + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + IMessage sut2 = null; + while (sut2 == null) { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - IMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); - } - - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false); } - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members/signed".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members/signed".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)).Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + TestOutput.WriteLine(_marshaller.Serialize(sut2).ToEncodedString()); - await _queue.SendAsync(sut3.Yield()); - } + Comparer.Add(sut3); - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() - { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); + await _queue.SendAsync(sut3.Yield()); + } - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; - ISignedMessage sut2 = null; - while (sut2 == null) - { - sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; - sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - } + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime_Signed() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members/signed").Single(); - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; + ISignedMessage sut2 = null; + while (sut2 == null) + { + sut2 = await _queue.ReceiveAsync().SingleOrDefaultAsync(ct).ConfigureAwait(false) as ISignedMessage; + sut2?.CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); } - [Fact, Priority(5)] - public async Task SendAsync_CreateMemberCommand_HundredTimes() + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + } + + [Fact, Priority(5)] + public async Task SendAsync_CreateMemberCommand_HundredTimes() + { + var messages = Generate.RangeOf(100, i => { - 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)); - Comparer.Add(message); - return message; - }).ToList(); + 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)); + Comparer.Add(message); + return message; + }).ToList(); - var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); + var profiler = await TimeMeasure.WithActionAsync(_ => _queue.SendAsync(messages)).ConfigureAwait(false); - TestOutput.WriteLine(profiler.ToString()); - } + TestOutput.WriteLine(profiler.ToString()); + } - [Fact, Priority(6)] - public async Task ReceiveAsync_CreateMemberCommand_All() - { - var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; - var realizedCommands = new List>(); - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + [Fact, Priority(6)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var ct = new CancellationTokenSource(TimeSpan.FromSeconds(90)).Token; + var realizedCommands = new List>(); + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - while (realizedCommands.Count < sut1.Count) - { - realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).ToListAsync(ct).ConfigureAwait(false)); - } + while (realizedCommands.Count < sut1.Count) + { + realizedCommands.AddRange(await _queue.ReceiveAsync(o => o.CancellationToken = ct).ToListAsync(ct).ConfigureAwait(false)); + } - TestOutput.WriteLine(realizedCommands.Count.ToString()); - TestOutput.WriteLines(realizedCommands.Take(10)); + TestOutput.WriteLine(realizedCommands.Count.ToString()); + TestOutput.WriteLines(realizedCommands.Take(10)); - Assert.Equivalent(sut1.Count, realizedCommands.Count); - Assert.Equivalent(sut1, realizedCommands); - Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); - } + Assert.Equivalent(sut1.Count, realizedCommands.Count); + Assert.Equivalent(sut1, realizedCommands); + Assert.Equivalent(sut1.Select(message => message.Data), realizedCommands.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), realizedCommands.Select(message => message.Data.Metadata)); + } - public override void ConfigureServices(IServiceCollection services) + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller(); + services.AddAmazonCommandQueue(o => { - services.AddMarshaller(); - services.AddAmazonCommandQueue(o => + var queue = IsLinux ? "newtonsoft-savvyio-commands" : "newtonsoft-savvyio-commands.fifo"; + o.Endpoint = RegionEndpoint.EUWest1; + if (Configuration["AWS:LocalStack"] != null) { - var queue = IsLinux ? "newtonsoft-savvyio-commands" : "newtonsoft-savvyio-commands.fifo"; - o.Endpoint = RegionEndpoint.EUWest1; - if (Configuration["AWS:LocalStack"] != null) + o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); + o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); + o.ConfigureClient(client => { - o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); - o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); - o.ConfigureClient(client => - { - client.ServiceURL = Configuration["AWS:LocalStack"]; - client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); - } - else - { - o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); - } - o.ReceiveContext.UseApproximateNumberOfMessages = true; - }); - } + client.ServiceURL = Configuration["AWS:LocalStack"]; + client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); + } + else + { + o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); + } + o.ReceiveContext.UseApproximateNumberOfMessages = true; + }); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs index 927e4162..6e9ed9c4 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs @@ -24,225 +24,224 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AmazonEventBusJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AmazonEventBusJsonSerializerContextTest : HostTest + private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + private readonly AmazonEventBus _bus; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly IMarshaller _marshaller; + private static readonly string UniqueType = $"{Guid.NewGuid():N}"; + + public AmazonEventBusJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - private readonly AmazonEventBus _bus; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly IMarshaller _marshaller; - private static readonly string UniqueType = $"{Guid.NewGuid():N}"; + _bus = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AmazonEventBusJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _bus = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task PublishAsync_MemberCreated_OneTime() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event"); - [Fact, Priority(0)] - public async Task PublishAsync_MemberCreated_OneTime() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event"); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); + Comparer.Add(sut3); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut3, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + await _bus.PublishAsync(sut3); + } - await _bus.PublishAsync(sut3); - } + [Fact, Priority(1)] + public async Task SubscribeAsync_MemberCreated_OneTime() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event")).Single(); - [Fact, Priority(1)] - public async Task SubscribeAsync_MemberCreated_OneTime() + await _bus.SubscribeAsync((sut2, _) => { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event")).Single(); + if (!sut2.Type.Contains($"{UniqueType}.updated-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(2)] - public async Task PublishAsync_MemberCreated_OneTime_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + [Fact, Priority(2)] + public async Task PublishAsync_MemberCreated_OneTime_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(3)] - public async Task SubscribeAsync_MemberCreated_OneTime_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed")).Single(); + [Fact, Priority(3)] + public async Task SubscribeAsync_MemberCreated_OneTime_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed")).Single(); - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed")) { return Task.CompletedTask; } - ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(4)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + await _bus.SubscribeAsync((sut2, _) => { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.cloud-event").ToCloudEvent(); + if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed")) { return Task.CompletedTask; } + ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(4)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.cloud-event").ToCloudEvent(); - Comparer.Add(sut3); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(5)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.cloud-event")).Single() as ICloudEvent; + await _bus.PublishAsync(sut3); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.cloud-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(6)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + [Fact, Priority(5)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.cloud-event")).Single() as ICloudEvent; + + await _bus.SubscribeAsync((sut2, _) => { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + if (!sut2.Type.Contains($"{UniqueType}.updated-event.cloud-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(6)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "member-events-one" : "member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - Comparer.Add(sut3); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(7)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")).Single(); + await _bus.PublishAsync(sut3); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } - ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(8)] - public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) - { - var messages = Generate.RangeOf(100, _ => - { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new MemberCreated(Generate.RandomString(10), email).ToMessage((IsLinux ? "member-events-many" : "member-events-many.fifo").ToSnsUri(), $"{nameof(MemberCreated)}.{UniqueType}"); - }); + [Fact, Priority(7)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")).Single(); - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return _bus.PublishAsync(message, o => o.CancellationToken = token); - }).ConfigureAwait(false); - } + await _bus.SubscribeAsync((sut2, _) => + { + if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } + ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(9)] - public async Task SubscribeAsync_MemberCreated_All() + [Fact, Priority(8)] + public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + { + var messages = Generate.RangeOf(100, _ => { - var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{UniqueType}")).ToList(); - var sut2 = new List>(); - var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage((IsLinux ? "member-events-many" : "member-events-many.fifo").ToSnsUri(), $"{nameof(MemberCreated)}.{UniqueType}"); + }); - await _bus.SubscribeAsync((message, _) => - { - if (!message.Type.Contains($"{UniqueType}")) { return Task.CompletedTask; } - sut2.Add(message); - return Task.CompletedTask; - }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + Comparer.Add(message); + return _bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + } - TestOutput.WriteLine(sut2.Count.ToString()); - TestOutput.WriteLines(sut2.Take(10)); + [Fact, Priority(9)] + public async Task SubscribeAsync_MemberCreated_All() + { + var sut1 = Comparer.Query(message => message.Source.Contains("member-events-many") && message.Type.Contains($"{UniqueType}")).ToList(); + var sut2 = new List>(); + var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - Assert.Equivalent(sut1.Count, sut2.Count); - Assert.Equivalent(sut1, sut2); - Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + await _bus.SubscribeAsync((message, _) => + { + if (!message.Type.Contains($"{UniqueType}")) { return Task.CompletedTask; } + sut2.Add(message); + return Task.CompletedTask; + }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + + TestOutput.WriteLine(sut2.Count.ToString()); + TestOutput.WriteLines(sut2.Take(10)); + + Assert.Equivalent(sut1.Count, sut2.Count); + Assert.Equivalent(sut1, sut2); + Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); + } - public override void ConfigureServices(IServiceCollection services) + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller(); + services.AddAmazonEventBus(o => { - services.AddMarshaller(); - services.AddAmazonEventBus(o => + var queue = IsLinux ? "savvyio-events" : "savvyio-events.fifo"; + o.Endpoint = RegionEndpoint.EUWest1; + if (Configuration["AWS:LocalStack"] != null) { - var queue = IsLinux ? "savvyio-events" : "savvyio-events.fifo"; - o.Endpoint = RegionEndpoint.EUWest1; - if (Configuration["AWS:LocalStack"] != null) + o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); + o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); + o.ConfigureClient(client => { - o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); - o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); - o.ConfigureClient(client => - { - client.ServiceURL = Configuration["AWS:LocalStack"]; - client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); - } - else - { - AmazonResourceNameOptions.DefaultAccountId = Configuration["AWS:CallerIdentity"]; - o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); - } - }); - } + client.ServiceURL = Configuration["AWS:LocalStack"]; + client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); + } + else + { + AmazonResourceNameOptions.DefaultAccountId = Configuration["AWS:CallerIdentity"]; + o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); + } + }); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs index 2c400d6c..9849add1 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs @@ -24,225 +24,224 @@ using Savvyio.Extensions.DependencyInjection; using Xunit.v3.Priority; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class AmazonEventBusNewtonsoftJsonSerializerContextTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class AmazonEventBusNewtonsoftJsonSerializerContextTest : HostTest + private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + private readonly AmazonEventBus _bus; + private static readonly InMemoryTestStore> Comparer = new(); + private readonly IMarshaller _marshaller; + private static readonly string UniqueType = $"{Guid.NewGuid():N}"; + + public AmazonEventBusNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { - private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - private readonly AmazonEventBus _bus; - private static readonly InMemoryTestStore> Comparer = new(); - private readonly IMarshaller _marshaller; - private static readonly string UniqueType = $"{Guid.NewGuid():N}"; + _bus = fixture.Host.Services.GetRequiredService(); + _marshaller = fixture.Host.Services.GetRequiredService(); + } - public AmazonEventBusNewtonsoftJsonSerializerContextTest(ManagedHostFixture fixture, ITestOutputHelper output) : base(fixture, output) - { - _bus = fixture.Host.Services.GetRequiredService(); - _marshaller = fixture.Host.Services.GetRequiredService(); - } + [Fact, Priority(0)] + public async Task PublishAsync_MemberCreated_OneTime() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event"); - [Fact, Priority(0)] - public async Task PublishAsync_MemberCreated_OneTime() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event"); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + Comparer.Add(sut3); - Comparer.Add(sut3); + await _bus.PublishAsync(sut3); + } - await _bus.PublishAsync(sut3); - } + [Fact, Priority(1)] + public async Task SubscribeAsync_MemberCreated_OneTime() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event")).Single(); - [Fact, Priority(1)] - public async Task SubscribeAsync_MemberCreated_OneTime() + await _bus.SubscribeAsync((sut2, _) => { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event")).Single(); + if (!sut2.Type.Contains($"{UniqueType}.updated-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(2)] - public async Task PublishAsync_MemberCreated_OneTime_Signed() - { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + [Fact, Priority(2)] + public async Task PublishAsync_MemberCreated_OneTime_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed").Sign(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - Comparer.Add(sut3); + Comparer.Add(sut3); - await _bus.PublishAsync(sut3); - } + await _bus.PublishAsync(sut3); + } - [Fact, Priority(3)] - public async Task SubscribeAsync_MemberCreated_OneTime_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed")).Single(); + [Fact, Priority(3)] + public async Task SubscribeAsync_MemberCreated_OneTime_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed")).Single(); - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed")) { return Task.CompletedTask; } - ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(4)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + await _bus.SubscribeAsync((sut2, _) => { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.cloud-event").ToCloudEvent(); + if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed")) { return Task.CompletedTask; } + ((ISignedMessage)sut2).CheckSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(4)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.cloud-event").ToCloudEvent(); - Comparer.Add(sut3); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(5)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.cloud-event")).Single() as ICloudEvent; + await _bus.PublishAsync(sut3); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.cloud-event")) { return Task.CompletedTask; } - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(6)] - public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + [Fact, Priority(5)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.cloud-event")).Single() as ICloudEvent; + + await _bus.SubscribeAsync((sut2, _) => { - var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); - var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); - var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + if (!sut2.Type.Contains($"{UniqueType}.updated-event.cloud-event")) { return Task.CompletedTask; } + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + Assert.Equivalent(sut1.Specversion, ((ICloudEvent)sut2).Specversion); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); + [Fact, Priority(6)] + public async Task PublishAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var sut1 = new MemberCreated("John Doe", "jd@outlook.com"); + var sut2 = (IsLinux ? "newtonsoft-member-events-one" : "newtonsoft-member-events-one.fifo").ToSnsUri(); + var sut3 = sut1.ToMessage(sut2, $"{nameof(MemberCreated)}.{UniqueType}.updated-event.signed-cloud-event").ToCloudEvent().SignCloudEvent(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - Comparer.Add(sut3); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = System.Environment.NewLine)); - await _bus.PublishAsync(sut3); - } + Comparer.Add(sut3); - [Fact, Priority(7)] - public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() - { - var handlerInvocations = 0; - var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")).Single(); + await _bus.PublishAsync(sut3); + } - await _bus.SubscribeAsync((sut2, _) => - { - if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } - ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - handlerInvocations++; - Assert.Equivalent(sut1.Data, sut2.Data); - Assert.Equivalent(sut1.Time, sut2.Time); - Assert.Equivalent(sut1.Source, sut2.Source); - Assert.Equivalent(sut1.Id, sut2.Id); - Assert.Equivalent(sut1.Type, sut2.Type); - return Task.CompletedTask; - }).ConfigureAwait(false); - Assert.Equal(1, handlerInvocations); - } - - [Fact, Priority(8)] - public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) - { - var messages = Generate.RangeOf(100, _ => - { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new MemberCreated(Generate.RandomString(10), email).ToMessage((IsLinux ? "newtonsoft-member-events-many" : "newtonsoft-member-events-many.fifo").ToSnsUri(), $"{nameof(MemberCreated)}.{UniqueType}"); - }); + [Fact, Priority(7)] + public async Task SubscribeAsync_MemberCreated_OneTime_CloudEvent_Signed() + { + var handlerInvocations = 0; + var sut1 = Comparer.Query(message => message.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")).Single(); - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return _bus.PublishAsync(message, o => o.CancellationToken = token); - }).ConfigureAwait(false); - } + await _bus.SubscribeAsync((sut2, _) => + { + if (!sut2.Type.Contains($"{UniqueType}.updated-event.signed-cloud-event")) { return Task.CompletedTask; } + ((ISignedCloudEvent)sut2).CheckCloudEventSignature(_marshaller, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + handlerInvocations++; + Assert.Equivalent(sut1.Data, sut2.Data); + Assert.Equivalent(sut1.Time, sut2.Time); + Assert.Equivalent(sut1.Source, sut2.Source); + Assert.Equivalent(sut1.Id, sut2.Id); + Assert.Equivalent(sut1.Type, sut2.Type); + return Task.CompletedTask; + }).ConfigureAwait(false); + Assert.Equal(1, handlerInvocations); + } - [Fact, Priority(9)] - public async Task SubscribeAsync_MemberCreated_All() + [Fact, Priority(8)] + public async Task PublishAsync_MemberCreated_HundredTimes() // reduced as SNS is not part of free tier (FIFO) + { + var messages = Generate.RangeOf(100, _ => { - var sut1 = Comparer.Query(message => message.Source.Contains("newtonsoft-member-events-many") && message.Type.Contains($"{UniqueType}")).ToList(); - var sut2 = new List>(); - var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new MemberCreated(Generate.RandomString(10), email).ToMessage((IsLinux ? "newtonsoft-member-events-many" : "newtonsoft-member-events-many.fifo").ToSnsUri(), $"{nameof(MemberCreated)}.{UniqueType}"); + }); - await _bus.SubscribeAsync((message, _) => - { - if (!message.Type.Contains($"{UniqueType}")) { return Task.CompletedTask; } - sut2.Add(message); - return Task.CompletedTask; - }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + await ParallelFactory.ForEachAsync(messages, (message, token) => + { + Comparer.Add(message); + return _bus.PublishAsync(message, o => o.CancellationToken = token); + }).ConfigureAwait(false); + } - TestOutput.WriteLine(sut2.Count.ToString()); - TestOutput.WriteLines(sut2.Take(10)); + [Fact, Priority(9)] + public async Task SubscribeAsync_MemberCreated_All() + { + var sut1 = Comparer.Query(message => message.Source.Contains("newtonsoft-member-events-many") && message.Type.Contains($"{UniqueType}")).ToList(); + var sut2 = new List>(); + var sut3 = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - Assert.Equivalent(sut1.Count, sut2.Count); - Assert.Equivalent(sut1, sut2); - Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + await _bus.SubscribeAsync((message, _) => + { + if (!message.Type.Contains($"{UniqueType}")) { return Task.CompletedTask; } + sut2.Add(message); + return Task.CompletedTask; + }, o => o.CancellationToken = sut3.Token).ConfigureAwait(false); + + TestOutput.WriteLine(sut2.Count.ToString()); + TestOutput.WriteLines(sut2.Take(10)); + + Assert.Equivalent(sut1.Count, sut2.Count); + Assert.Equivalent(sut1, sut2); + Assert.Equivalent(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equivalent(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); + } - public override void ConfigureServices(IServiceCollection services) + public override void ConfigureServices(IServiceCollection services) + { + services.AddMarshaller(); + services.AddAmazonEventBus(o => { - services.AddMarshaller(); - services.AddAmazonEventBus(o => + var queue = IsLinux ? "newtonsoft-savvyio-events" : "newtonsoft-savvyio-events.fifo"; + o.Endpoint = RegionEndpoint.EUWest1; + if (Configuration["AWS:LocalStack"] != null) { - var queue = IsLinux ? "newtonsoft-savvyio-events" : "newtonsoft-savvyio-events.fifo"; - o.Endpoint = RegionEndpoint.EUWest1; - if (Configuration["AWS:LocalStack"] != null) + o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); + o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); + o.ConfigureClient(client => { - o.Credentials = new BasicAWSCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"); - o.SourceQueue = new Uri($"http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/{queue}"); - o.ConfigureClient(client => - { - client.ServiceURL = Configuration["AWS:LocalStack"]; - client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); - } - else - { - AmazonResourceNameOptions.DefaultAccountId = Configuration["AWS:CallerIdentity"]; - o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); - } - }); - } + client.ServiceURL = Configuration["AWS:LocalStack"]; + client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); + } + else + { + AmazonResourceNameOptions.DefaultAccountId = Configuration["AWS:CallerIdentity"]; + o.Credentials = new BasicAWSCredentials(Configuration["AWS:IAM:AccessKey"], Configuration["AWS:IAM:SecretKey"]); + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{Configuration["AWS:CallerIdentity"]}/{queue}"); + } + }); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs index a530012c..4f7b8d35 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs @@ -9,146 +9,145 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +public class AmazonMessageOptionsTest : Test { - public class AmazonMessageOptionsTest : Test + public AmazonMessageOptionsTest(ITestOutputHelper output) : base(output) { - public AmazonMessageOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_ShouldHaveDefaultValues() - { - var sut = new AmazonMessageOptions(); + [Fact] + public void Ctor_ShouldHaveDefaultValues() + { + var sut = new AmazonMessageOptions(); - Assert.Null(sut.Endpoint); - Assert.Null(sut.SourceQueue); - Assert.Null(sut.Credentials); - Assert.Empty(sut.ClientConfigurations); - } + Assert.Null(sut.Endpoint); + Assert.Null(sut.SourceQueue); + Assert.Null(sut.Credentials); + Assert.Empty(sut.ClientConfigurations); + } - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenEndpointIsNull() + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenEndpointIsNull() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - SourceQueue = new Uri("urn:null"), - Credentials = new AnonymousAWSCredentials() - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.Endpoint)} == null')", sut2.Message); - Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenSourceQueueIsNull() + SourceQueue = new Uri("urn:null"), + Credentials = new AnonymousAWSCredentials() + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.Endpoint)} == null')", sut2.Message); + Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } + + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenSourceQueueIsNull() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - Endpoint = RegionEndpoint.EUWest1, - Credentials = new AnonymousAWSCredentials() - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.SourceQueue)} == null')", sut2.Message); - Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenCredentialsIsNull() + Endpoint = RegionEndpoint.EUWest1, + Credentials = new AnonymousAWSCredentials() + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.SourceQueue)} == null')", sut2.Message); + Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } + + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenCredentialsIsNull() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("urn:null"), - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.Credentials)} == null')", sut2.Message); - Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } - - [Fact] - public void ValidateOptions_ShouldPass() + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("urn:null"), + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.Credentials)} == null')", sut2.Message); + Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } + + [Fact] + public void ValidateOptions_ShouldPass() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("urn:null") - }; - - sut1.ValidateOptions(); - - Assert.Equivalent(new AnonymousAWSCredentials(), sut1.Credentials, true); - Assert.Equal(RegionEndpoint.EUWest1, sut1.Endpoint); - Assert.Equal(new Uri("urn:null"), sut1.SourceQueue); - Assert.Equal(0, sut1.ClientConfigurations.Length); - } - - [Fact] - public void ValidateOptions_ShouldPassWithConfiguredClient() + Credentials = new AnonymousAWSCredentials(), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("urn:null") + }; + + sut1.ValidateOptions(); + + Assert.Equivalent(new AnonymousAWSCredentials(), sut1.Credentials, true); + Assert.Equal(RegionEndpoint.EUWest1, sut1.Endpoint); + Assert.Equal(new Uri("urn:null"), sut1.SourceQueue); + Assert.Equal(0, sut1.ClientConfigurations.Length); + } + + [Fact] + public void ValidateOptions_ShouldPassWithConfiguredClient() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("urn:null") - }.ConfigureClient(client => - { - client.ServiceURL = "http://localhost:4566"; - client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); - - sut1.ValidateOptions(); - - Assert.Equivalent(new AnonymousAWSCredentials(), sut1.Credentials, true); - Assert.Equal(RegionEndpoint.EUWest1, sut1.Endpoint); - Assert.Equal(new Uri("urn:null"), sut1.SourceQueue); - Assert.True(sut1.ClientConfigurations.All(config => config is AmazonSQSConfig || config is AmazonSimpleNotificationServiceConfig)); - Assert.Equal(2, sut1.ClientConfigurations.Length); - Assert.Equal("http://localhost:4566/", sut1.ClientConfigurations.SimpleQueueService().ServiceURL); - Assert.Equal("eu-west-1", sut1.ClientConfigurations.SimpleQueueService().AuthenticationRegion); - Assert.Equal(sut1.ClientConfigurations.SimpleQueueService().ServiceURL, sut1.ClientConfigurations.SimpleNotificationService().ServiceURL); - Assert.Equal(sut1.ClientConfigurations.SimpleQueueService().AuthenticationRegion, sut1.ClientConfigurations.SimpleNotificationService().AuthenticationRegion); - } - - [Fact] - public void ConfigureClient_Should_Throw_When_Setup_Is_Null() + Credentials = new AnonymousAWSCredentials(), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("urn:null") + }.ConfigureClient(client => { - var sut = new AmazonMessageOptions(); + client.ServiceURL = "http://localhost:4566"; + client.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); + + sut1.ValidateOptions(); + + Assert.Equivalent(new AnonymousAWSCredentials(), sut1.Credentials, true); + Assert.Equal(RegionEndpoint.EUWest1, sut1.Endpoint); + Assert.Equal(new Uri("urn:null"), sut1.SourceQueue); + Assert.True(sut1.ClientConfigurations.All(config => config is AmazonSQSConfig || config is AmazonSimpleNotificationServiceConfig)); + Assert.Equal(2, sut1.ClientConfigurations.Length); + Assert.Equal("http://localhost:4566/", sut1.ClientConfigurations.SimpleQueueService().ServiceURL); + Assert.Equal("eu-west-1", sut1.ClientConfigurations.SimpleQueueService().AuthenticationRegion); + Assert.Equal(sut1.ClientConfigurations.SimpleQueueService().ServiceURL, sut1.ClientConfigurations.SimpleNotificationService().ServiceURL); + Assert.Equal(sut1.ClientConfigurations.SimpleQueueService().AuthenticationRegion, sut1.ClientConfigurations.SimpleNotificationService().AuthenticationRegion); + } - Assert.Throws(() => sut.ConfigureClient(null)); - } + [Fact] + public void ConfigureClient_Should_Throw_When_Setup_Is_Null() + { + var sut = new AmazonMessageOptions(); + + Assert.Throws(() => sut.ConfigureClient(null)); + } - [Fact] - public void ValidateOptions_ThrowsInvalidOperationException_WhenClientConfigurationsAreInvalid() + [Fact] + public void ValidateOptions_ThrowsInvalidOperationException_WhenClientConfigurationsAreInvalid() + { + var sut1 = new AmazonMessageOptions { - var sut1 = new AmazonMessageOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("urn:null") - }; - - typeof(AmazonMessageOptions) - .GetProperty(nameof(AmazonMessageOptions.ClientConfigurations), BindingFlags.Instance | BindingFlags.Public)! - .SetValue(sut1, new ClientConfig[] { new AmazonSQSConfig() }); - - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.ClientConfigurations)}.Length > 0 && ({nameof(AmazonMessageOptions.ClientConfigurations)}.Length != 2 || !({nameof(AmazonMessageOptions.ClientConfigurations)}[0] is AmazonSQSConfig && {nameof(AmazonMessageOptions.ClientConfigurations)}[1] is AmazonSimpleNotificationServiceConfig))')", sut2.Message); - Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Credentials = new AnonymousAWSCredentials(), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("urn:null") + }; + + typeof(AmazonMessageOptions) + .GetProperty(nameof(AmazonMessageOptions.ClientConfigurations), BindingFlags.Instance | BindingFlags.Public)! + .SetValue(sut1, new ClientConfig[] { new AmazonSQSConfig() }); + + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonMessageOptions.ClientConfigurations)}.Length > 0 && ({nameof(AmazonMessageOptions.ClientConfigurations)}.Length != 2 || !({nameof(AmazonMessageOptions.ClientConfigurations)}[0] is AmazonSQSConfig && {nameof(AmazonMessageOptions.ClientConfigurations)}[1] is AmazonSimpleNotificationServiceConfig))')", sut2.Message); + Assert.Equal($"{nameof(AmazonMessageOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs index 238b6391..dc1ef02a 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs @@ -2,61 +2,60 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +public class AmazonMessageReceiveOptionsTest : Test { - public class AmazonMessageReceiveOptionsTest : Test + public AmazonMessageReceiveOptionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Ctor_ShouldHaveDefaultValues() + { + var sut = new AmazonMessageReceiveOptions(); + + Assert.Equal(10, sut.NumberOfMessagesToTakePerRequest); + Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds), sut.PollingTimeout); + Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.DefaultVisibilityTimeoutInSeconds), sut.VisibilityTimeout); + Assert.True(sut.AssumeMessageProcessed); + Assert.True(sut.RemoveProcessedMessages); + Assert.False(sut.UseApproximateNumberOfMessages); + } + + [Fact] + public void NumberOfMessagesToTakePerRequest_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() { - public AmazonMessageReceiveOptionsTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void Ctor_ShouldHaveDefaultValues() - { - var sut = new AmazonMessageReceiveOptions(); - - Assert.Equal(10, sut.NumberOfMessagesToTakePerRequest); - Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds), sut.PollingTimeout); - Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.DefaultVisibilityTimeoutInSeconds), sut.VisibilityTimeout); - Assert.True(sut.AssumeMessageProcessed); - Assert.True(sut.RemoveProcessedMessages); - Assert.False(sut.UseApproximateNumberOfMessages); - } - - [Fact] - public void NumberOfMessagesToTakePerRequest_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() - { - var sut = new AmazonMessageReceiveOptions(); - - sut.NumberOfMessagesToTakePerRequest = int.MinValue; - Assert.Equal(1, sut.NumberOfMessagesToTakePerRequest); - - sut.NumberOfMessagesToTakePerRequest = int.MaxValue; - Assert.Equal(AmazonMessageOptions.MaxNumberOfMessages, sut.NumberOfMessagesToTakePerRequest); - } - - [Fact] - public void PollingTimeout_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() - { - var sut = new AmazonMessageReceiveOptions(); - - sut.PollingTimeout = TimeSpan.MinValue; - Assert.Equal(TimeSpan.Zero, sut.PollingTimeout); - - sut.PollingTimeout = TimeSpan.MaxValue; - Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds), sut.PollingTimeout); - } - - [Fact] - public void VisibilityTimeout_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() - { - var sut = new AmazonMessageReceiveOptions(); - - sut.VisibilityTimeout = TimeSpan.MinValue; - Assert.Equal(TimeSpan.Zero, sut.VisibilityTimeout); - - sut.VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds + 1); - Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds), sut.VisibilityTimeout); - } + var sut = new AmazonMessageReceiveOptions(); + + sut.NumberOfMessagesToTakePerRequest = int.MinValue; + Assert.Equal(1, sut.NumberOfMessagesToTakePerRequest); + + sut.NumberOfMessagesToTakePerRequest = int.MaxValue; + Assert.Equal(AmazonMessageOptions.MaxNumberOfMessages, sut.NumberOfMessagesToTakePerRequest); + } + + [Fact] + public void PollingTimeout_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() + { + var sut = new AmazonMessageReceiveOptions(); + + sut.PollingTimeout = TimeSpan.MinValue; + Assert.Equal(TimeSpan.Zero, sut.PollingTimeout); + + sut.PollingTimeout = TimeSpan.MaxValue; + Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxPollingWaitTimeInSeconds), sut.PollingTimeout); + } + + [Fact] + public void VisibilityTimeout_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() + { + var sut = new AmazonMessageReceiveOptions(); + + sut.VisibilityTimeout = TimeSpan.MinValue; + Assert.Equal(TimeSpan.Zero, sut.VisibilityTimeout); + + sut.VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds + 1); + Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds), sut.VisibilityTimeout); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageTest.cs index 6636451b..368fea2e 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageTest.cs @@ -9,64 +9,63 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +public class AmazonMessageTest : Test { - public class AmazonMessageTest : Test + public AmazonMessageTest(ITestOutputHelper output) : base(output) { - public AmazonMessageTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Constructor_Should_Set_Protected_Properties_For_Standard_Queue() - { - var marshaller = JsonMarshaller.Default; - var options = CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/orders"); + [Fact] + public void Constructor_Should_Set_Protected_Properties_For_Standard_Queue() + { + var marshaller = JsonMarshaller.Default; + var options = CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/orders"); - var sut = new TestAmazonQueue(marshaller, options); + var sut = new TestAmazonQueue(marshaller, options); - Assert.Same(marshaller, sut.ExposedMarshaller); - Assert.Same(options, sut.Options); - Assert.False(sut.UseFirstInFirstOut); - } + Assert.Same(marshaller, sut.ExposedMarshaller); + Assert.Same(options, sut.Options); + Assert.False(sut.UseFirstInFirstOut); + } - [Fact] - public void Constructor_Should_Detect_First_In_First_Out_Queue() - { - var sut = new TestAmazonQueue(JsonMarshaller.Default, CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/orders.fifo")); + [Fact] + public void Constructor_Should_Detect_First_In_First_Out_Queue() + { + var sut = new TestAmazonQueue(JsonMarshaller.Default, CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/orders.fifo")); - Assert.True(sut.UseFirstInFirstOut); - } + Assert.True(sut.UseFirstInFirstOut); + } - private static AmazonMessageOptions CreateOptions(string queueUrl) + private static AmazonMessageOptions CreateOptions(string queueUrl) + { + return new AmazonMessageOptions { - return new AmazonMessageOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri(queueUrl) - }; - } + Credentials = new AnonymousAWSCredentials(), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri(queueUrl) + }; + } - private sealed class TestAmazonQueue : AmazonQueue + private sealed class TestAmazonQueue : AmazonQueue + { + public TestAmazonQueue(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) { - public TestAmazonQueue(IMarshaller marshaller, AmazonMessageOptions options) : base(marshaller, options) - { - } + } - public bool UseFirstInFirstOut => base.UseFirstInFirstOut; + public bool UseFirstInFirstOut => base.UseFirstInFirstOut; - public IMarshaller ExposedMarshaller => base.Marshaller; + public IMarshaller ExposedMarshaller => base.Marshaller; - public override Task SendAsync(IEnumerable> messages, Action setup = null) - { - return Task.CompletedTask; - } + public override Task SendAsync(IEnumerable> messages, Action setup = null) + { + return Task.CompletedTask; + } - public override async IAsyncEnumerable> ReceiveAsync(Action setup = null) - { - yield break; - } + public override async IAsyncEnumerable> ReceiveAsync(Action setup = null) + { + yield break; } } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs index 6fc48c1e..268f6742 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs @@ -3,79 +3,78 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +public class AmazonResourceNameOptionsTest : Test { - public class AmazonResourceNameOptionsTest : Test + public AmazonResourceNameOptionsTest(ITestOutputHelper output) : base(output) { - public AmazonResourceNameOptionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_ShouldHaveDefaultValues() - { - var sut = new AmazonResourceNameOptions(); + [Fact] + public void Ctor_ShouldHaveDefaultValues() + { + var sut = new AmazonResourceNameOptions(); - Assert.Equal(AmazonResourceNameOptions.DefaultAccountId, sut.AccountId); - Assert.Equal(AmazonResourceNameOptions.DefaultPartition, sut.Partition); - Assert.Equal(AmazonResourceNameOptions.DefaultRegion, sut.Region); - } + Assert.Equal(AmazonResourceNameOptions.DefaultAccountId, sut.AccountId); + Assert.Equal(AmazonResourceNameOptions.DefaultPartition, sut.Partition); + Assert.Equal(AmazonResourceNameOptions.DefaultRegion, sut.Region); + } - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - [InlineData("0123456789")] - [InlineData("A0123456789Z")] - [InlineData("1012345678910")] - public void ValidateOptions_ThrowsInvalidOperationException_WhenAccountIdIsNullOrEmptyOrConsistOfWhiteSpaceOnlyOrNotFixedLengthOrNotANumber(string accountId) + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + [InlineData("0123456789")] + [InlineData("A0123456789Z")] + [InlineData("1012345678910")] + public void ValidateOptions_ThrowsInvalidOperationException_WhenAccountIdIsNullOrEmptyOrConsistOfWhiteSpaceOnlyOrNotFixedLengthOrNotANumber(string accountId) + { + var sut1 = new AmazonResourceNameOptions { - var sut1 = new AmazonResourceNameOptions - { - AccountId = accountId - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + AccountId = accountId + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.AccountId)}.IsNullOrWhiteSpace() || {nameof(AmazonResourceNameOptions.AccountId)}.Length != 12 || !{nameof(AmazonResourceNameOptions.AccountId)}.IsNumeric(NumberStyles.Integer, CultureInfo.InvariantCulture)')", sut2.Message); - Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.AccountId)}.IsNullOrWhiteSpace() || {nameof(AmazonResourceNameOptions.AccountId)}.Length != 12 || !{nameof(AmazonResourceNameOptions.AccountId)}.IsNumeric(NumberStyles.Integer, CultureInfo.InvariantCulture)')", sut2.Message); + Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - public void ValidateOptions_ThrowsInvalidOperationException_WhenPartitionIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string partition) + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void ValidateOptions_ThrowsInvalidOperationException_WhenPartitionIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string partition) + { + var sut1 = new AmazonResourceNameOptions { - var sut1 = new AmazonResourceNameOptions - { - Partition = partition - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + Partition = partition + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.Partition)}.IsNullOrWhiteSpace()')", sut2.Message); - Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.Partition)}.IsNullOrWhiteSpace()')", sut2.Message); + Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); + } - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData(" ")] - public void ValidateOptions_ThrowsInvalidOperationException_WhenRegionIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string region) + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void ValidateOptions_ThrowsInvalidOperationException_WhenRegionIsNullOrEmptyOrConsistOfWhiteSpaceOnly(string region) + { + var sut1 = new AmazonResourceNameOptions { - var sut1 = new AmazonResourceNameOptions - { - Region = region - }; - var sut2 = Assert.Throws(() => sut1.ValidateOptions()); - var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); + Region = region + }; + var sut2 = Assert.Throws(() => sut1.ValidateOptions()); + var sut3 = Assert.Throws(() => Validator.ThrowIfInvalidOptions(sut1)); - Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.Region)}.IsNullOrWhiteSpace()')", sut2.Message); - Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); - Assert.IsType(sut3.InnerException); - } + Assert.Equal($"Operation is not valid due to the current state of the object. (Expression '{nameof(AmazonResourceNameOptions.Region)}.IsNullOrWhiteSpace()')", sut2.Message); + Assert.Equal($"{nameof(AmazonResourceNameOptions)} are not in a valid state. (Parameter '{nameof(sut1)}')", sut3.Message); + Assert.IsType(sut3.InnerException); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs index 2f3faaa9..03dfbeae 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs @@ -4,32 +4,31 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService +namespace Savvyio.Extensions.SimpleQueueService; + +public class ClientConfigExtensionsTest : Test { - public class ClientConfigExtensionsTest : Test + public ClientConfigExtensionsTest(ITestOutputHelper output) : base(output) { - public ClientConfigExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void IsValid_Should_Return_True_When_Both_Aws_Client_Configurations_Are_Present() - { - ClientConfig[] configurations = [ new AmazonSQSConfig(), new AmazonSimpleNotificationServiceConfig() ]; + [Fact] + public void IsValid_Should_Return_True_When_Both_Aws_Client_Configurations_Are_Present() + { + ClientConfig[] configurations = [ new AmazonSQSConfig(), new AmazonSimpleNotificationServiceConfig() ]; - Assert.True(configurations.IsValid()); - Assert.IsType(configurations.SimpleQueueService()); - Assert.IsType(configurations.SimpleNotificationService()); - } + Assert.True(configurations.IsValid()); + Assert.IsType(configurations.SimpleQueueService()); + Assert.IsType(configurations.SimpleNotificationService()); + } - [Fact] - public void IsValid_Should_Return_False_When_Configurations_Are_Missing_Expected_Types() - { - ClientConfig[] invalid = [ new AmazonSQSConfig() ]; + [Fact] + public void IsValid_Should_Return_False_When_Configurations_Are_Missing_Expected_Types() + { + ClientConfig[] invalid = [ new AmazonSQSConfig() ]; - Assert.False(invalid.IsValid()); - Assert.NotNull(invalid.SimpleQueueService()); - Assert.Null(invalid.SimpleNotificationService()); - } + Assert.False(invalid.IsValid()); + Assert.NotNull(invalid.SimpleQueueService()); + Assert.Null(invalid.SimpleNotificationService()); } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/Commands/AmazonCommandQueueTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/Commands/AmazonCommandQueueTest.cs index 99f48689..0ba51565 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/Commands/AmazonCommandQueueTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/Commands/AmazonCommandQueueTest.cs @@ -16,244 +16,243 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService.Commands +namespace Savvyio.Extensions.SimpleQueueService.Commands; + +/// +/// Unit tests for . +/// +public class AmazonCommandQueueTest : Test { - /// - /// Unit tests for . - /// - public class AmazonCommandQueueTest : Test - { - private readonly IMarshaller _marshaller; - private readonly AmazonCommandQueueOptions _options; + private readonly IMarshaller _marshaller; + private readonly AmazonCommandQueueOptions _options; - public AmazonCommandQueueTest(ITestOutputHelper output) : base(output) + public AmazonCommandQueueTest(ITestOutputHelper output) : base(output) + { + _marshaller = new JsonMarshaller(); + _options = new AmazonCommandQueueOptions { - _marshaller = new JsonMarshaller(); - _options = new AmazonCommandQueueOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = Amazon.RegionEndpoint.USEast1, - SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") - }; - } + Credentials = new AnonymousAWSCredentials(), + Endpoint = Amazon.RegionEndpoint.USEast1, + SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") + }; + } - [Fact] - public void Ctor_Should_Throw_ArgumentNullException_When_Marshaller_Is_Null() - { - Assert.Throws(() => new AmazonCommandQueue(null, _options)); - } + [Fact] + public void Ctor_Should_Throw_ArgumentNullException_When_Marshaller_Is_Null() + { + Assert.Throws(() => new AmazonCommandQueue(null, _options)); + } - [Fact] - public void Ctor_Should_Throw_ArgumentNullException_When_Options_Is_Null() - { - Assert.Throws(() => new AmazonCommandQueue(_marshaller, null)); - } + [Fact] + public void Ctor_Should_Throw_ArgumentNullException_When_Options_Is_Null() + { + Assert.Throws(() => new AmazonCommandQueue(_marshaller, null)); + } - [Fact] - public void Ctor_Should_Throw_ArgumentException_When_Options_Invalid() - { - var invalidOptions = new AmazonCommandQueueOptions(); - Assert.Throws(() => new AmazonCommandQueue(_marshaller, invalidOptions)); - } + [Fact] + public void Ctor_Should_Throw_ArgumentException_When_Options_Invalid() + { + var invalidOptions = new AmazonCommandQueueOptions(); + Assert.Throws(() => new AmazonCommandQueue(_marshaller, invalidOptions)); + } - [Fact] - public async Task SendAsync_Should_Throw_ArgumentNullException_When_Messages_Is_Null() - { - var sut = new AmazonCommandQueue(_marshaller, _options); - await Assert.ThrowsAsync(() => sut.SendAsync(null)); - } + [Fact] + public async Task SendAsync_Should_Throw_ArgumentNullException_When_Messages_Is_Null() + { + var sut = new AmazonCommandQueue(_marshaller, _options); + await Assert.ThrowsAsync(() => sut.SendAsync(null)); + } - [Fact] - public async Task ReceiveAsync_Should_Call_RetrieveMessagesAsync() - { - var sut = new AmazonCommandQueue(_marshaller, _options); + [Fact] + public async Task ReceiveAsync_Should_Call_RetrieveMessagesAsync() + { + var sut = new AmazonCommandQueue(_marshaller, _options); - // Act - var result = sut.ReceiveAsync(); + // Act + var result = sut.ReceiveAsync(); - // Assert - Assert.NotNull(result); - // We can't enumerate without a real SQS, but we can check the type - Assert.IsAssignableFrom>>(result); - } + // Assert + Assert.NotNull(result); + // We can't enumerate without a real SQS, but we can check the type + Assert.IsAssignableFrom>>(result); + } - [Fact] - public void GetHealthCheckTarget_Should_Return_IAmazonSQS_Instance() - { - var sut = new AmazonCommandQueue(_marshaller, _options); + [Fact] + public void GetHealthCheckTarget_Should_Return_IAmazonSQS_Instance() + { + var sut = new AmazonCommandQueue(_marshaller, _options); - var sqs = sut.GetHealthCheckTarget(); + var sqs = sut.GetHealthCheckTarget(); - Assert.NotNull(sqs); - Assert.IsAssignableFrom(sqs); - } + Assert.NotNull(sqs); + Assert.IsAssignableFrom(sqs); + } - [Fact] - public void GetHealthCheckTarget_Should_Use_Configured_Client_When_Available() + [Fact] + public void GetHealthCheckTarget_Should_Use_Configured_Client_When_Available() + { + var options = new AmazonCommandQueueOptions { - var options = new AmazonCommandQueueOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = Amazon.RegionEndpoint.USEast1, - SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") - }; - options.ConfigureClient(config => - { - config.ServiceURL = "http://localhost:4566"; - config.AuthenticationRegion = Amazon.RegionEndpoint.USEast1.SystemName; - }); + Credentials = new AnonymousAWSCredentials(), + Endpoint = Amazon.RegionEndpoint.USEast1, + SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") + }; + options.ConfigureClient(config => + { + config.ServiceURL = "http://localhost:4566"; + config.AuthenticationRegion = Amazon.RegionEndpoint.USEast1.SystemName; + }); - var sut = new AmazonCommandQueue(_marshaller, options); + var sut = new AmazonCommandQueue(_marshaller, options); - var sqs = sut.GetHealthCheckTarget(); + var sqs = sut.GetHealthCheckTarget(); - Assert.Equal("http://localhost:4566/", sqs.Config.ServiceURL); - Assert.Equal(Amazon.RegionEndpoint.USEast1.SystemName, sqs.Config.AuthenticationRegion); - } + Assert.Equal("http://localhost:4566/", sqs.Config.ServiceURL); + Assert.Equal(Amazon.RegionEndpoint.USEast1.SystemName, sqs.Config.AuthenticationRegion); + } - [Fact] - public async Task SendAsync_ShouldSendMessagesInBatches() - { - var sqs = new Mock(); - var requests = new List(); - sqs.Setup(s => s.SendMessageBatchAsync(It.IsAny(), It.IsAny())) - .Callback((request, _) => requests.Add(request)) - .ReturnsAsync(new SendMessageBatchResponse()); - var queue = new TestableAmazonCommandQueue(_marshaller, _options, sqs.Object); - var messages = Enumerable.Range(0, 11).Select(_ => CreateMessage()).ToArray(); + [Fact] + public async Task SendAsync_ShouldSendMessagesInBatches() + { + var sqs = new Mock(); + var requests = new List(); + sqs.Setup(s => s.SendMessageBatchAsync(It.IsAny(), It.IsAny())) + .Callback((request, _) => requests.Add(request)) + .ReturnsAsync(new SendMessageBatchResponse()); + var queue = new TestableAmazonCommandQueue(_marshaller, _options, sqs.Object); + var messages = Enumerable.Range(0, 11).Select(_ => CreateMessage()).ToArray(); - await queue.SendAsync(messages); + await queue.SendAsync(messages); - Assert.Equal(2, requests.Count); - Assert.Equal(10, requests[0].Entries.Count); - Assert.Single(requests[1].Entries); - Assert.All(requests.SelectMany(request => request.Entries), entry => - { - Assert.NotNull(entry.MessageBody); - Assert.True(entry.MessageAttributes.ContainsKey("type")); - }); - } + Assert.Equal(2, requests.Count); + Assert.Equal(10, requests[0].Entries.Count); + Assert.Single(requests[1].Entries); + Assert.All(requests.SelectMany(request => request.Entries), entry => + { + Assert.NotNull(entry.MessageBody); + Assert.True(entry.MessageAttributes.ContainsKey("type")); + }); + } - [Fact] - public async Task ReceiveAsync_ShouldDeserializeMessagesAndDeleteAcknowledgedMessages() + [Fact] + public async Task ReceiveAsync_ShouldDeserializeMessagesAndDeleteAcknowledgedMessages() + { + var message = CreateMessage(); + var awsMessage = new Message { - var message = CreateMessage(); - var awsMessage = new Message + Body = _marshaller.Serialize(message).ToEncodedString(), + MessageId = "message-id", + ReceiptHandle = "receipt-handle", + MessageAttributes = new Dictionary { - Body = _marshaller.Serialize(message).ToEncodedString(), - MessageId = "message-id", - ReceiptHandle = "receipt-handle", - MessageAttributes = new Dictionary + ["type"] = new MessageAttributeValue { - ["type"] = new MessageAttributeValue - { - DataType = "String", - StringValue = message.GetType().ToFullNameIncludingAssemblyName() - } + DataType = "String", + StringValue = message.GetType().ToFullNameIncludingAssemblyName() } - }; - var sqs = new Mock(); - sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReceiveMessageResponse - { - Messages = [awsMessage] - }); - DeleteMessageBatchRequest deleteRequest = null; - sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) - .Callback((request, _) => deleteRequest = request) - .ReturnsAsync(new DeleteMessageBatchResponse()); - var queue = new TestableAmazonCommandQueue(_marshaller, _options, sqs.Object); - - var received = new List>(); - await foreach (var item in queue.ReceiveAsync()) - { - received.Add(item); } + }; + var sqs = new Mock(); + sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new ReceiveMessageResponse + { + Messages = [awsMessage] + }); + DeleteMessageBatchRequest deleteRequest = null; + sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) + .Callback((request, _) => deleteRequest = request) + .ReturnsAsync(new DeleteMessageBatchResponse()); + var queue = new TestableAmazonCommandQueue(_marshaller, _options, sqs.Object); - Assert.Single(received); - Assert.Equal(message.Id, received[0].Id); - Assert.NotNull(deleteRequest); - Assert.Equal("message-id", deleteRequest.Entries[0].Id); - Assert.Equal("receipt-handle", deleteRequest.Entries[0].ReceiptHandle); + var received = new List>(); + await foreach (var item in queue.ReceiveAsync()) + { + received.Add(item); } - [Fact] - public async Task ReceiveAsync_ShouldUseApproximateNumberOfMessages_WhenConfigured() + Assert.Single(received); + Assert.Equal(message.Id, received[0].Id); + Assert.NotNull(deleteRequest); + Assert.Equal("message-id", deleteRequest.Entries[0].Id); + Assert.Equal("receipt-handle", deleteRequest.Entries[0].ReceiptHandle); + } + + [Fact] + public async Task ReceiveAsync_ShouldUseApproximateNumberOfMessages_WhenConfigured() + { + var message = CreateMessage(); + var awsMessage = new Message { - var message = CreateMessage(); - var awsMessage = new Message + Body = _marshaller.Serialize(message).ToEncodedString(), + MessageId = "message-id", + ReceiptHandle = "receipt-handle", + MessageAttributes = new Dictionary { - Body = _marshaller.Serialize(message).ToEncodedString(), - MessageId = "message-id", - ReceiptHandle = "receipt-handle", - MessageAttributes = new Dictionary + ["type"] = new MessageAttributeValue { - ["type"] = new MessageAttributeValue - { - DataType = "String", - StringValue = message.GetType().ToFullNameIncludingAssemblyName() - } + DataType = "String", + StringValue = message.GetType().ToFullNameIncludingAssemblyName() } - }; - var options = new AmazonCommandQueueOptions + } + }; + var options = new AmazonCommandQueueOptions + { + Credentials = new AnonymousAWSCredentials(), + Endpoint = Amazon.RegionEndpoint.USEast1, + SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") + }; + options.ReceiveContext.UseApproximateNumberOfMessages = true; + var sqs = new Mock(); + sqs.Setup(s => s.GetQueueAttributesAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new GetQueueAttributesResponse { - Credentials = new AnonymousAWSCredentials(), - Endpoint = Amazon.RegionEndpoint.USEast1, - SourceQueue = new Uri("https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue") - }; - options.ReceiveContext.UseApproximateNumberOfMessages = true; - var sqs = new Mock(); - sqs.Setup(s => s.GetQueueAttributesAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new GetQueueAttributesResponse - { - Attributes = new Dictionary - { - ["ApproximateNumberOfMessages"] = "1" - } - }); - sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReceiveMessageResponse + Attributes = new Dictionary { - Messages = [awsMessage] - }); - sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new DeleteMessageBatchResponse()); - var queue = new TestableAmazonCommandQueue(_marshaller, options, sqs.Object); - - var received = new List>(); - await foreach (var item in queue.ReceiveAsync()) + ["ApproximateNumberOfMessages"] = "1" + } + }); + sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new ReceiveMessageResponse { - received.Add(item); - } - - Assert.Single(received); - sqs.Verify(s => s.GetQueueAttributesAsync(It.Is(request => request.QueueUrl == options.SourceQueue.OriginalString), It.IsAny()), Times.Once); - } + Messages = [awsMessage] + }); + sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new DeleteMessageBatchResponse()); + var queue = new TestableAmazonCommandQueue(_marshaller, options, sqs.Object); - private static IMessage CreateMessage() + var received = new List>(); + await foreach (var item in queue.ReceiveAsync()) { - return new Message( - Guid.NewGuid().ToString("N"), - new Uri("urn:test"), - "test", - new TestCommand()); + received.Add(item); } - private sealed class TestableAmazonCommandQueue : AmazonCommandQueue - { - private readonly IAmazonSQS _sqs; + Assert.Single(received); + sqs.Verify(s => s.GetQueueAttributesAsync(It.Is(request => request.QueueUrl == options.SourceQueue.OriginalString), It.IsAny()), Times.Once); + } - public TestableAmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options, IAmazonSQS sqs) : base(marshaller, options) - { - _sqs = sqs; - } + private static IMessage CreateMessage() + { + return new Message( + Guid.NewGuid().ToString("N"), + new Uri("urn:test"), + "test", + new TestCommand()); + } - protected override IAmazonSQS CreateSimpleQueueServiceClient() - { - return _sqs; - } + private sealed class TestableAmazonCommandQueue : AmazonCommandQueue + { + private readonly IAmazonSQS _sqs; + + public TestableAmazonCommandQueue(IMarshaller marshaller, AmazonCommandQueueOptions options, IAmazonSQS sqs) : base(marshaller, options) + { + _sqs = sqs; } - private record TestCommand : Command { } + protected override IAmazonSQS CreateSimpleQueueServiceClient() + { + return _sqs; + } } + + private record TestCommand : Command { } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/AmazonEventBusTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/AmazonEventBusTest.cs index 10cdede6..fcf1b2d2 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/AmazonEventBusTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/AmazonEventBusTest.cs @@ -23,200 +23,199 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +/// +/// Unit tests for . +/// +public class AmazonEventBusTest : Test { - /// - /// Unit tests for . - /// - public class AmazonEventBusTest : Test + public AmazonEventBusTest(ITestOutputHelper output) : base(output) { - public AmazonEventBusTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Ctor_Should_ThrowArgumentNullException_When_MarshallerIsNull() + [Fact] + public void Ctor_Should_ThrowArgumentNullException_When_MarshallerIsNull() + { + var options = new AmazonEventBusOptions { - var options = new AmazonEventBusOptions - { - Credentials = new BasicAWSCredentials("key", "secret"), - Endpoint = RegionEndpoint.EUWest1 - }; + Credentials = new BasicAWSCredentials("key", "secret"), + Endpoint = RegionEndpoint.EUWest1 + }; - Assert.Throws(() => new AmazonEventBus(null, options)); - } + Assert.Throws(() => new AmazonEventBus(null, options)); + } - [Fact] - public void Ctor_Should_ThrowArgumentNullException_When_OptionsIsNull() - { - var marshaller = new JsonMarshaller(); + [Fact] + public void Ctor_Should_ThrowArgumentNullException_When_OptionsIsNull() + { + var marshaller = new JsonMarshaller(); - Assert.Throws(() => new AmazonEventBus(marshaller, null)); - } + Assert.Throws(() => new AmazonEventBus(marshaller, null)); + } - [Fact] - public void Ctor_Should_ThrowArgumentException_When_OptionsInvalid() - { - var marshaller = new JsonMarshaller(); - var options = new AmazonEventBusOptions(); // Missing required properties + [Fact] + public void Ctor_Should_ThrowArgumentException_When_OptionsInvalid() + { + var marshaller = new JsonMarshaller(); + var options = new AmazonEventBusOptions(); // Missing required properties - Assert.Throws(() => new AmazonEventBus(marshaller, options)); - } + Assert.Throws(() => new AmazonEventBus(marshaller, options)); + } - [Fact] - public void GetHealthCheckTarget_Should_Return_IAmazonSimpleNotificationService_Instance() + [Fact] + public void GetHealthCheckTarget_Should_Return_IAmazonSimpleNotificationService_Instance() + { + var marshaller = new JsonMarshaller(); + var options = new AmazonEventBusOptions { - var marshaller = new JsonMarshaller(); - var options = new AmazonEventBusOptions - { - Credentials = new BasicAWSCredentials("key", "secret"), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue") - }; + Credentials = new BasicAWSCredentials("key", "secret"), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue") + }; - var sut = new AmazonEventBus(marshaller, options); + var sut = new AmazonEventBus(marshaller, options); - var sns = sut.GetHealthCheckTarget(); + var sns = sut.GetHealthCheckTarget(); - Assert.NotNull(sns); - Assert.IsAssignableFrom(sns); - } + Assert.NotNull(sns); + Assert.IsAssignableFrom(sns); + } - [Fact] - public void GetHealthCheckTarget_Should_Use_Configured_Client_When_Available() + [Fact] + public void GetHealthCheckTarget_Should_Use_Configured_Client_When_Available() + { + var marshaller = new JsonMarshaller(); + var options = new AmazonEventBusOptions { - var marshaller = new JsonMarshaller(); - var options = new AmazonEventBusOptions - { - Credentials = new BasicAWSCredentials("key", "secret"), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue") - }; - options.ConfigureClient(config => - { - config.ServiceURL = "http://localhost:4566"; - config.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; - }); + Credentials = new BasicAWSCredentials("key", "secret"), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue") + }; + options.ConfigureClient(config => + { + config.ServiceURL = "http://localhost:4566"; + config.AuthenticationRegion = RegionEndpoint.EUWest1.SystemName; + }); - var sut = new AmazonEventBus(marshaller, options); + var sut = new AmazonEventBus(marshaller, options); - var sns = sut.GetHealthCheckTarget(); + var sns = sut.GetHealthCheckTarget(); - Assert.Equal("http://localhost:4566/", sns.Config.ServiceURL); - Assert.Equal(RegionEndpoint.EUWest1.SystemName, sns.Config.AuthenticationRegion); - } + Assert.Equal("http://localhost:4566/", sns.Config.ServiceURL); + Assert.Equal(RegionEndpoint.EUWest1.SystemName, sns.Config.AuthenticationRegion); + } - [Fact] - public async Task PublishAsync_ShouldSendSerializedEvent() - { - var sns = new Mock(); - PublishRequest request = null; - sns.Setup(s => s.PublishAsync(It.IsAny(), It.IsAny())) - .Callback((r, _) => request = r) - .ReturnsAsync(new PublishResponse()); - var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue.fifo"), sns.Object); - var message = CreateMessage(); - - await bus.PublishAsync(message); - - Assert.NotNull(request); - Assert.Equal(message.Source, request.TopicArn); - Assert.Equal(message.Source, request.MessageGroupId); - Assert.Equal(message.Id, request.MessageDeduplicationId); - Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), request.MessageAttributes["type"].StringValue); - } + [Fact] + public async Task PublishAsync_ShouldSendSerializedEvent() + { + var sns = new Mock(); + PublishRequest request = null; + sns.Setup(s => s.PublishAsync(It.IsAny(), It.IsAny())) + .Callback((r, _) => request = r) + .ReturnsAsync(new PublishResponse()); + var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue.fifo"), sns.Object); + var message = CreateMessage(); + + await bus.PublishAsync(message); + + Assert.NotNull(request); + Assert.Equal(message.Source, request.TopicArn); + Assert.Equal(message.Source, request.MessageGroupId); + Assert.Equal(message.Id, request.MessageDeduplicationId); + Assert.Equal(message.GetType().ToFullNameIncludingAssemblyName(), request.MessageAttributes["type"].StringValue); + } - [Fact] - public async Task SubscribeAsync_ShouldReceiveMessagesAndInvokeHandler() + [Fact] + public async Task SubscribeAsync_ShouldReceiveMessagesAndInvokeHandler() + { + var message = CreateMessage(); + var sqsMessage = new Message { - var message = CreateMessage(); - var sqsMessage = new Message + Body = new JsonMarshaller().Serialize(message).ToEncodedString(), + MessageId = "message-id", + ReceiptHandle = "receipt-handle", + MessageAttributes = new Dictionary { - Body = new JsonMarshaller().Serialize(message).ToEncodedString(), - MessageId = "message-id", - ReceiptHandle = "receipt-handle", - MessageAttributes = new Dictionary + ["type"] = new Amazon.SQS.Model.MessageAttributeValue { - ["type"] = new Amazon.SQS.Model.MessageAttributeValue - { - DataType = "String", - StringValue = message.GetType().ToFullNameIncludingAssemblyName() - } + DataType = "String", + StringValue = message.GetType().ToFullNameIncludingAssemblyName() } - }; - var sqs = new Mock(); - sqs.SetupSequence(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReceiveMessageResponse { Messages = [sqsMessage] }) - .ReturnsAsync(new ReceiveMessageResponse { Messages = [] }); - sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(new DeleteMessageBatchResponse()); - var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue"), Mock.Of(), sqs.Object); - IMessage received = null; - - await bus.SubscribeAsync((msg, _) => - { - received = msg; - return Task.CompletedTask; - }); + } + }; + var sqs = new Mock(); + sqs.SetupSequence(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new ReceiveMessageResponse { Messages = [sqsMessage] }) + .ReturnsAsync(new ReceiveMessageResponse { Messages = [] }); + sqs.Setup(s => s.DeleteMessageBatchAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new DeleteMessageBatchResponse()); + var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue"), Mock.Of(), sqs.Object); + IMessage received = null; + + await bus.SubscribeAsync((msg, _) => + { + received = msg; + return Task.CompletedTask; + }); - Assert.NotNull(received); - Assert.Equal(message.Id, received.Id); - } + Assert.NotNull(received); + Assert.Equal(message.Id, received.Id); + } - [Fact] - public async Task SubscribeAsync_ShouldSwallowCancellation_WhenThrowIfCancellationWasRequestedIsFalse() - { - using var cts = new CancellationTokenSource(); - cts.Cancel(); - var sqs = new Mock(); - sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) - .ThrowsAsync(new OperationCanceledException(cts.Token)); - var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue"), Mock.Of(), sqs.Object); + [Fact] + public async Task SubscribeAsync_ShouldSwallowCancellation_WhenThrowIfCancellationWasRequestedIsFalse() + { + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var sqs = new Mock(); + sqs.Setup(s => s.ReceiveMessageAsync(It.IsAny(), It.IsAny())) + .ThrowsAsync(new OperationCanceledException(cts.Token)); + var bus = new TestableAmazonEventBus(new JsonMarshaller(), CreateOptions("https://sqs.eu-west-1.amazonaws.com/123456789012/MyQueue"), Mock.Of(), sqs.Object); - await bus.SubscribeAsync((_, _) => Task.CompletedTask, o => o.CancellationToken = cts.Token); + await bus.SubscribeAsync((_, _) => Task.CompletedTask, o => o.CancellationToken = cts.Token); - sqs.Verify(s => s.ReceiveMessageAsync(It.IsAny(), cts.Token), Times.Once); - } + sqs.Verify(s => s.ReceiveMessageAsync(It.IsAny(), cts.Token), Times.Once); + } - private static AmazonEventBusOptions CreateOptions(string queueUrl) + private static AmazonEventBusOptions CreateOptions(string queueUrl) + { + return new AmazonEventBusOptions { - return new AmazonEventBusOptions - { - Credentials = new AnonymousAWSCredentials(), - Endpoint = RegionEndpoint.EUWest1, - SourceQueue = new Uri(queueUrl) - }; - } + Credentials = new AnonymousAWSCredentials(), + Endpoint = RegionEndpoint.EUWest1, + SourceQueue = new Uri(queueUrl) + }; + } + + private static IMessage CreateMessage() + { + return new Message("id", new Uri("arn:aws:sns:eu-west-1:123456789012:topic.fifo"), "type", new DummyIntegrationEvent(), DateTime.UtcNow); + } + + private sealed record DummyIntegrationEvent : IntegrationEvent + { + } - private static IMessage CreateMessage() + private sealed class TestableAmazonEventBus : AmazonEventBus + { + private readonly IAmazonSimpleNotificationService _sns; + private readonly IAmazonSQS _sqs; + + public TestableAmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options, IAmazonSimpleNotificationService sns, IAmazonSQS sqs = null) : base(marshaller, options) { - return new Message("id", new Uri("arn:aws:sns:eu-west-1:123456789012:topic.fifo"), "type", new DummyIntegrationEvent(), DateTime.UtcNow); + _sns = sns; + _sqs = sqs; } - private sealed record DummyIntegrationEvent : IntegrationEvent + protected override IAmazonSimpleNotificationService CreateSimpleNotificationServiceClient() { + return _sns; } - private sealed class TestableAmazonEventBus : AmazonEventBus + protected override IAmazonSQS CreateSimpleQueueServiceClient() { - private readonly IAmazonSimpleNotificationService _sns; - private readonly IAmazonSQS _sqs; - - public TestableAmazonEventBus(IMarshaller marshaller, AmazonEventBusOptions options, IAmazonSimpleNotificationService sns, IAmazonSQS sqs = null) : base(marshaller, options) - { - _sns = sns; - _sqs = sqs; - } - - protected override IAmazonSimpleNotificationService CreateSimpleNotificationServiceClient() - { - return _sns; - } - - protected override IAmazonSQS CreateSimpleQueueServiceClient() - { - return _sqs ?? base.CreateSimpleQueueServiceClient(); - } + return _sqs ?? base.CreateSimpleQueueServiceClient(); } } } diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs index f3d1802c..c36b9bee 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs @@ -2,39 +2,38 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.SimpleQueueService.EventDriven +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; + +public class StringExtensionsTest : Test { - public class StringExtensionsTest : Test + public StringExtensionsTest(ITestOutputHelper output) : base(output) { - public StringExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToSnsUri_Should_Use_Default_Amazon_Resource_Name_Options() - { - var result = "order-created".ToSnsUri(); + [Fact] + public void ToSnsUri_Should_Use_Default_Amazon_Resource_Name_Options() + { + var result = "order-created".ToSnsUri(); - Assert.Equal($"arn:{AmazonResourceNameOptions.DefaultPartition}:sns:{AmazonResourceNameOptions.DefaultRegion}:{AmazonResourceNameOptions.DefaultAccountId}:order-created", result.OriginalString); - } + Assert.Equal($"arn:{AmazonResourceNameOptions.DefaultPartition}:sns:{AmazonResourceNameOptions.DefaultRegion}:{AmazonResourceNameOptions.DefaultAccountId}:order-created", result.OriginalString); + } - [Fact] - public void ToSnsUri_Should_Apply_Custom_Amazon_Resource_Name_Options() + [Fact] + public void ToSnsUri_Should_Apply_Custom_Amazon_Resource_Name_Options() + { + var result = "order-created".ToSnsUri(o => { - var result = "order-created".ToSnsUri(o => - { - o.Partition = "aws-cn"; - o.Region = "cn-north-1"; - o.AccountId = "123456789012"; - }); + o.Partition = "aws-cn"; + o.Region = "cn-north-1"; + o.AccountId = "123456789012"; + }); - Assert.Equal("arn:aws-cn:sns:cn-north-1:123456789012:order-created", result.OriginalString); - } + Assert.Equal("arn:aws-cn:sns:cn-north-1:123456789012:order-created", result.OriginalString); + } - [Fact] - public void ToSnsUri_Should_Throw_When_Configurator_Produces_Invalid_Options() - { - Assert.Throws(() => "order-created".ToSnsUri(o => o.AccountId = "bad")); - } + [Fact] + public void ToSnsUri_Should_Throw_When_Configurator_Produces_Invalid_Options() + { + Assert.Throws(() => "order-created".ToSnsUri(o => o.AccountId = "bad")); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs index af5a07fe..ae73cbcf 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs @@ -4,42 +4,41 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Extensions.Text.Json.Commands +namespace Savvyio.Extensions.Text.Json.Commands; + +public class CommandTest : Test { - public class CommandTest : Test + public CommandTest(ITestOutputHelper output) : base(output) { - public CommandTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CreateAccount_ShouldUseCustomConverter() - { - var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + [Fact] + public void CreateAccount_ShouldUseCustomConverter() + { + var ca = new CreateAccount(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var json = new JsonMarshaller().Serialize(ca); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(ca); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new JsonMarshaller().Deserialize(json); + var rehydrated = new JsonMarshaller().Deserialize(json); - Assert.Equivalent(ca, rehydrated, true); - } + Assert.Equivalent(ca, rehydrated, true); + } - [Fact] - public void CreateAccountWithValueObjects_ShouldUseCustomConverter() - { - var ca = new CreateAccountWithValueObjects(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); + [Fact] + public void CreateAccountWithValueObjects_ShouldUseCustomConverter() + { + var ca = new CreateAccountWithValueObjects(Guid.NewGuid(), "Michael Mortensen", "root@gimlichael.dev"); - var json = new JsonMarshaller().Serialize(ca); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(ca); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new JsonMarshaller().Deserialize(json); + var rehydrated = new JsonMarshaller().Deserialize(json); - Assert.Equivalent(ca, rehydrated, true); - } + Assert.Equivalent(ca, rehydrated, true); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs index b46455c7..dce0df6a 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs @@ -7,35 +7,35 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.Text.Json.Commands.Messaging +namespace Savvyio.Extensions.Text.Json.Commands.Messaging; + +public class CommandExtensionsTest : Test { - public class CommandExtensionsTest : Test + public CommandExtensionsTest(ITestOutputHelper output) : base(output) { - public CommandExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ShouldSerializeAndDeserialize_CreateMemberCommand_UsingInterface() + [Fact] + public void ToMessage_ShouldSerializeAndDeserialize_CreateMemberCommand_UsingInterface() + { + var utcNow = DateTime.UtcNow; + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }); - var json = new JsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new JsonMarshaller().Deserialize>(json); + var sut4 = new JsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -52,6 +52,5 @@ public void ToMessage_ShouldSerializeAndDeserialize_CreateMemberCommand_UsingInt } } """.ReplaceLineEndings(), jsonString); - } } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs index 06adf5a9..0403c4cf 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/Cryptography/MessageExtensionsTest.cs @@ -8,47 +8,46 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.Text.Json.Commands.Messaging.Cryptography +namespace Savvyio.Extensions.Text.Json.Commands.Messaging.Cryptography; + +public class MessageExtensionsTest : Test { - public class MessageExtensionsTest : Test + public MessageExtensionsTest(ITestOutputHelper output) : base(output) { - public MessageExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void EncloseToSignedMessage_ShouldSerialize_WithSignature() + [Fact] + public void EncloseToSignedMessage_ShouldSerialize_WithSignature() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(JsonMarshaller.Default, o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new CreateMemberCommand("Jane Doe", 21, "jd@office.com").SetCorrelationId("3eefdef050c340bfba100bd49c58c181"); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(CreateMemberCommand), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(JsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); - var json = JsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = JsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - var signatureException = Assert.Throws(() => - { - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + var signatureException = Assert.Throws(() => + { + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - var sut4 = JsonMarshaller.Default.Deserialize>(json); + var sut4 = JsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"CreateMemberCommand","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","age":21,"emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.Commands.CreateMemberCommand, Savvyio.Assets.Tests","correlationId":"3eefdef050c340bfba100bd49c58c181"}},"signature":"76df78c14ee668b2812a4c8c8ab58738de6b595623938e9c8aa893e9630ff5ad"}""", jsonString); - } + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"CreateMemberCommand","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","age":21,"emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.Commands.CreateMemberCommand, Savvyio.Assets.Tests","correlationId":"3eefdef050c340bfba100bd49c58c181"}},"signature":"76df78c14ee668b2812a4c8c8ab58738de6b595623938e9c8aa893e9630ff5ad"}""", jsonString); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs index 4efd9806..59cd9bb7 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs @@ -14,75 +14,74 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio.Extensions.Text.Json.Commands.Messaging +namespace Savvyio.Extensions.Text.Json.Commands.Messaging; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class InMemoryCommandQueueTest : Test { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class InMemoryCommandQueueTest : Test - { - private static readonly InMemoryCommandQueue Queue = new(); - private static readonly InMemoryTestStore> Comparer = new(); + private static readonly InMemoryCommandQueue Queue = new(); + private static readonly InMemoryTestStore> Comparer = new(); - public InMemoryCommandQueueTest(ITestOutputHelper output) : base(output) - { - } + public InMemoryCommandQueueTest(ITestOutputHelper output) : base(output) + { + } - [Fact, Priority(0)] - public async Task SendAsync_CreateMemberCommand_OneTime() - { - var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); - var sut2 = "https://fancy.io/members".ToUri(); - var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); + [Fact, Priority(0)] + public async Task SendAsync_CreateMemberCommand_OneTime() + { + var sut1 = new CreateMemberCommand("John Doe", 44, "jd@outlook.com"); + var sut2 = "https://fancy.io/members".ToUri(); + var sut3 = sut1.ToMessage(sut2, nameof(CreateMemberCommand)); - TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); + TestOutput.WriteLine(Generate.ObjectPortrayal(sut2, o => o.Delimiter = Environment.NewLine)); - TestOutput.WriteLine(new JsonMarshaller().Serialize(sut2).ToEncodedString()); + TestOutput.WriteLine(new JsonMarshaller().Serialize(sut2).ToEncodedString()); - Comparer.Add(sut3); + Comparer.Add(sut3); - await Queue.SendAsync(sut3.Yield()); - } + await Queue.SendAsync(sut3.Yield()); + } - [Fact, Priority(1)] - public async Task ReceiveAsync_CreateMemberCommand_OneTime() - { - var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); - var sut2 = await Queue.ReceiveAsync().SingleOrDefaultAsync(); + [Fact, Priority(1)] + public async Task ReceiveAsync_CreateMemberCommand_OneTime() + { + var sut1 = Comparer.Query(message => message.Source == "https://fancy.io/members").Single(); + var sut2 = await Queue.ReceiveAsync().SingleOrDefaultAsync(); - Assert.Equal(sut1.Data, sut2.Data); - Assert.Equal(sut1.Time, sut2.Time); - Assert.Equal(sut1.Source, sut2.Source); - Assert.Equal(sut1.Id, sut2.Id); - Assert.Equal(sut1.Type, sut2.Type); - } + Assert.Equal(sut1.Data, sut2.Data); + Assert.Equal(sut1.Time, sut2.Time); + Assert.Equal(sut1.Source, sut2.Source); + Assert.Equal(sut1.Id, sut2.Id); + Assert.Equal(sut1.Type, sut2.Type); + } - [Fact, Priority(2)] - public async Task SendAsync_CreateMemberCommand_ThousandTimes() + [Fact, Priority(2)] + public async Task SendAsync_CreateMemberCommand_ThousandTimes() + { + var messages = Generate.RangeOf(1000, i => { - var messages = Generate.RangeOf(1000, i => - { - var email = $"{Generate.RandomString(5)}@outlook.com"; - return new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); - }); + var email = $"{Generate.RandomString(5)}@outlook.com"; + return new CreateMemberCommand(Generate.RandomString(10), (byte)Generate.RandomNumber(byte.MaxValue), email).ToMessage($"urn:{i}:{email}".ToUri(), nameof(CreateMemberCommand)); + }); - await ParallelFactory.ForEachAsync(messages, (message, token) => - { - Comparer.Add(message); - return Queue.SendAsync(message.Yield(), o => o.CancellationToken = token); - }); - } - - [Fact, Priority(3)] - public async Task ReceiveAsync_CreateMemberCommand_All() + await ParallelFactory.ForEachAsync(messages, (message, token) => { - var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); - var sut2 = await Queue.ReceiveAsync().ToListAsync(); + Comparer.Add(message); + return Queue.SendAsync(message.Yield(), o => o.CancellationToken = token); + }); + } + + [Fact, Priority(3)] + public async Task ReceiveAsync_CreateMemberCommand_All() + { + var sut1 = Comparer.Query(message => message.Source.StartsWith("urn")).ToList(); + var sut2 = await Queue.ReceiveAsync().ToListAsync(); - TestOutput.WriteLines(sut2.Take(10)); + TestOutput.WriteLines(sut2.Take(10)); - Assert.Equal(sut1.Count, sut2.Count); - Assert.Equal(sut1, sut2); - Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); - Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); - } + Assert.Equal(sut1.Count, sut2.Count); + Assert.Equal(sut1, sut2); + Assert.Equal(sut1.Select(message => message.Data), sut2.Select(message => message.Data)); + Assert.Equal(sut1.Select(message => message.Data.Metadata), sut2.Select(message => message.Data.Metadata)); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeConverterTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeConverterTest.cs index 70a0ee89..245b7178 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeConverterTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeConverterTest.cs @@ -5,59 +5,58 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +public class DateTimeConverterTest : Test { - public class DateTimeConverterTest : Test + public DateTimeConverterTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void CanConvert_ShouldReturnTrue_ForDateTime() + { + var converter = new DateTimeConverter(); + Assert.True(converter.CanConvert(typeof(DateTime))); + } + + [Fact] + public void CanConvert_ShouldReturnFalse_ForOtherTypes() + { + var converter = new DateTimeConverter(); + Assert.False(converter.CanConvert(typeof(string))); + Assert.False(converter.CanConvert(typeof(DateTimeOffset))); + } + + [Fact] + public void Write_ShouldSerializeDateTime_AsIso8601() { - public DateTimeConverterTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void CanConvert_ShouldReturnTrue_ForDateTime() - { - var converter = new DateTimeConverter(); - Assert.True(converter.CanConvert(typeof(DateTime))); - } - - [Fact] - public void CanConvert_ShouldReturnFalse_ForOtherTypes() - { - var converter = new DateTimeConverter(); - Assert.False(converter.CanConvert(typeof(string))); - Assert.False(converter.CanConvert(typeof(DateTimeOffset))); - } - - [Fact] - public void Write_ShouldSerializeDateTime_AsIso8601() - { - var utc = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); - var converter = new DateTimeConverter(); - var buffer = new ArrayBufferWriter(); - using var writer = new Utf8JsonWriter(buffer); - - converter.Write(writer, utc, new JsonSerializerOptions()); - writer.Flush(); - - var json = Encoding.UTF8.GetString(buffer.WrittenSpan); - TestOutput.WriteLine(json); - - Assert.Contains("2023-11-16", json); - } - - [Fact] - public void Read_ShouldDeserializeDateTime_FromIso8601() - { - var utc = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); - var converter = new DateTimeConverter(); - var jsonString = $"\"{utc:O}\""; - var bytes = Encoding.UTF8.GetBytes(jsonString); - var reader = new Utf8JsonReader(bytes); - reader.Read(); - - var result = converter.Read(ref reader, typeof(DateTime), new JsonSerializerOptions()); - - Assert.Equal(utc, result); - } + var utc = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); + var converter = new DateTimeConverter(); + var buffer = new ArrayBufferWriter(); + using var writer = new Utf8JsonWriter(buffer); + + converter.Write(writer, utc, new JsonSerializerOptions()); + writer.Flush(); + + var json = Encoding.UTF8.GetString(buffer.WrittenSpan); + TestOutput.WriteLine(json); + + Assert.Contains("2023-11-16", json); + } + + [Fact] + public void Read_ShouldDeserializeDateTime_FromIso8601() + { + var utc = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); + var converter = new DateTimeConverter(); + var jsonString = $"\"{utc:O}\""; + var bytes = Encoding.UTF8.GetBytes(jsonString); + var reader = new Utf8JsonReader(bytes); + reader.Read(); + + var result = converter.Read(ref reader, typeof(DateTime), new JsonSerializerOptions()); + + Assert.Equal(utc, result); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeOffsetConverterTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeOffsetConverterTest.cs index 3a11fb6f..bc957afa 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeOffsetConverterTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Converters/DateTimeOffsetConverterTest.cs @@ -5,52 +5,51 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +public class DateTimeOffsetConverterTest : Test { - public class DateTimeOffsetConverterTest : Test + public DateTimeOffsetConverterTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void CanConvert_ReturnsTrue_ForDateTime() { - public DateTimeOffsetConverterTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void CanConvert_ReturnsTrue_ForDateTime() - { - var converter = new DateTimeOffsetConverter(); - // Note: CanConvert checks for DateTime (not DateTimeOffset) by design in this implementation - Assert.True(converter.CanConvert(typeof(DateTime))); - } - - [Fact] - public void Write_ShouldSerializeDateTimeOffset_AsIso8601() - { - var dto = new DateTimeOffset(2023, 11, 16, 23, 24, 17, TimeSpan.Zero); - var converter = new DateTimeOffsetConverter(); - var buffer = new ArrayBufferWriter(); - using var writer = new Utf8JsonWriter(buffer); - - converter.Write(writer, dto, new JsonSerializerOptions()); - writer.Flush(); - - var json = Encoding.UTF8.GetString(buffer.WrittenSpan); - TestOutput.WriteLine(json); - - Assert.Contains("2023-11-16", json); - } - - [Fact] - public void Read_ShouldDeserializeDateTimeOffset_FromIso8601() - { - var dto = new DateTimeOffset(2023, 11, 16, 23, 24, 17, TimeSpan.Zero); - var converter = new DateTimeOffsetConverter(); - var jsonString = $"\"{dto:O}\""; - var bytes = Encoding.UTF8.GetBytes(jsonString); - var reader = new Utf8JsonReader(bytes); - reader.Read(); - - var result = converter.Read(ref reader, typeof(DateTimeOffset), new JsonSerializerOptions()); - - Assert.Equal(dto, result); - } + var converter = new DateTimeOffsetConverter(); + // Note: CanConvert checks for DateTime (not DateTimeOffset) by design in this implementation + Assert.True(converter.CanConvert(typeof(DateTime))); + } + + [Fact] + public void Write_ShouldSerializeDateTimeOffset_AsIso8601() + { + var dto = new DateTimeOffset(2023, 11, 16, 23, 24, 17, TimeSpan.Zero); + var converter = new DateTimeOffsetConverter(); + var buffer = new ArrayBufferWriter(); + using var writer = new Utf8JsonWriter(buffer); + + converter.Write(writer, dto, new JsonSerializerOptions()); + writer.Flush(); + + var json = Encoding.UTF8.GetString(buffer.WrittenSpan); + TestOutput.WriteLine(json); + + Assert.Contains("2023-11-16", json); + } + + [Fact] + public void Read_ShouldDeserializeDateTimeOffset_FromIso8601() + { + var dto = new DateTimeOffset(2023, 11, 16, 23, 24, 17, TimeSpan.Zero); + var converter = new DateTimeOffsetConverter(); + var jsonString = $"\"{dto:O}\""; + var bytes = Encoding.UTF8.GetBytes(jsonString); + var reader = new Utf8JsonReader(bytes); + reader.Read(); + + var result = converter.Read(ref reader, typeof(DateTimeOffset), new JsonSerializerOptions()); + + Assert.Equal(dto, result); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Converters/MessageConverterTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Converters/MessageConverterTest.cs index ea6a5514..5b5618ee 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Converters/MessageConverterTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Converters/MessageConverterTest.cs @@ -10,77 +10,76 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +public class MessageConverterTest : Test { - public class MessageConverterTest : Test + public MessageConverterTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void MessageConverter_ShouldConvertOnlyMessages() + { + var sut = new MessageConverter(); + + Assert.True(sut.CanConvert(typeof(Message))); + Assert.False(sut.CanConvert(typeof(MemberCreated))); + Assert.False(sut.CanConvert(typeof(string))); + } + + [Fact] + public void MessageConverter_ShouldRoundtripCloudEventExtensionAttributes() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var cloudEvent = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc) + .ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent(); + + ((IDictionary)cloudEvent).Add("traceparent", "00-abc-def-01"); + + var marshaller = new JsonMarshaller(); + var json = marshaller.Serialize(cloudEvent); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + + TestOutput.WriteLine(jsonString); + + var result = marshaller.Deserialize>(json); + + Assert.Contains("traceparent", jsonString); + Assert.True(((IDictionary)result).ContainsKey("traceparent")); + } + + [Fact] + public void MessageConverter_ShouldRoundtripDataWithWritableMetadata() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var data = new WritableMetadataRequest { Name = "Jane Doe" }; + data.Metadata.Add("custom", "value"); + var message = new Message("2d4030d32a254ee8a27046e5bafe696a", "https://fancy.api/members".ToUri(), nameof(WritableMetadataRequest), data, utc); + + var marshaller = new JsonMarshaller(); + var json = marshaller.Serialize(message); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + + TestOutput.WriteLine(jsonString); + + var result = marshaller.Deserialize>(json); + + Assert.NotNull(result); + Assert.Equal("Jane Doe", result.Data.Name); + Assert.NotNull(result.Data.Metadata); + Assert.True(result.Data.Metadata.ContainsKey("custom")); + Assert.Equal("value", result.Data.Metadata["custom"].ToString()); + } + + private sealed record WritableMetadataRequest : IRequest, IMetadata { - public MessageConverterTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void MessageConverter_ShouldConvertOnlyMessages() - { - var sut = new MessageConverter(); - - Assert.True(sut.CanConvert(typeof(Message))); - Assert.False(sut.CanConvert(typeof(MemberCreated))); - Assert.False(sut.CanConvert(typeof(string))); - } - - [Fact] - public void MessageConverter_ShouldRoundtripCloudEventExtensionAttributes() - { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var cloudEvent = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc) - .ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent(); - - ((IDictionary)cloudEvent).Add("traceparent", "00-abc-def-01"); - - var marshaller = new JsonMarshaller(); - var json = marshaller.Serialize(cloudEvent); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - var result = marshaller.Deserialize>(json); - - Assert.Contains("traceparent", jsonString); - Assert.True(((IDictionary)result).ContainsKey("traceparent")); - } - - [Fact] - public void MessageConverter_ShouldRoundtripDataWithWritableMetadata() - { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var data = new WritableMetadataRequest { Name = "Jane Doe" }; - data.Metadata.Add("custom", "value"); - var message = new Message("2d4030d32a254ee8a27046e5bafe696a", "https://fancy.api/members".ToUri(), nameof(WritableMetadataRequest), data, utc); - - var marshaller = new JsonMarshaller(); - var json = marshaller.Serialize(message); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - var result = marshaller.Deserialize>(json); - - Assert.NotNull(result); - Assert.Equal("Jane Doe", result.Data.Name); - Assert.NotNull(result.Data.Metadata); - Assert.True(result.Data.Metadata.ContainsKey("custom")); - Assert.Equal("value", result.Data.Metadata["custom"].ToString()); - } - - private sealed record WritableMetadataRequest : IRequest, IMetadata - { - public string Name { get; set; } - - public IMetadataDictionary Metadata { get; set; } = new MetadataDictionary(); - } + public string Name { get; set; } + + public IMetadataDictionary Metadata { get; set; } = new MetadataDictionary(); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Converters/MetadataDictionaryConverterTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Converters/MetadataDictionaryConverterTest.cs index 75800b56..12a13b35 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Converters/MetadataDictionaryConverterTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Converters/MetadataDictionaryConverterTest.cs @@ -5,167 +5,166 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +public class MetadataDictionaryConverterTest : Test { - public class MetadataDictionaryConverterTest : Test + public MetadataDictionaryConverterTest(ITestOutputHelper output) : base(output) { - public MetadataDictionaryConverterTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void CanConvert_ShouldReturnTrue_ForIMetadataDictionary() - { - var converter = new MetadataDictionaryConverter(); + [Fact] + public void CanConvert_ShouldReturnTrue_ForIMetadataDictionary() + { + var converter = new MetadataDictionaryConverter(); - Assert.True(converter.CanConvert(typeof(IMetadataDictionary))); - Assert.True(converter.CanConvert(typeof(MetadataDictionary))); - } + Assert.True(converter.CanConvert(typeof(IMetadataDictionary))); + Assert.True(converter.CanConvert(typeof(MetadataDictionary))); + } - [Fact] - public void CanConvert_ShouldReturnFalse_ForUnrelatedTypes() - { - var converter = new MetadataDictionaryConverter(); + [Fact] + public void CanConvert_ShouldReturnFalse_ForUnrelatedTypes() + { + var converter = new MetadataDictionaryConverter(); - Assert.False(converter.CanConvert(typeof(string))); - Assert.False(converter.CanConvert(typeof(int))); - } + Assert.False(converter.CanConvert(typeof(string))); + Assert.False(converter.CanConvert(typeof(int))); + } - [Fact] - public void Read_ShouldHandleBooleanFalse() - { - var json = """{"flag": false}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleBooleanFalse() + { + var json = """{"flag": false}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.Equal(false, result["flag"]); - } + Assert.NotNull(result); + Assert.Equal(false, result["flag"]); + } - [Fact] - public void Read_ShouldHandleBooleanTrue() - { - var json = """{"flag": true}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleBooleanTrue() + { + var json = """{"flag": true}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.Equal(true, result["flag"]); - } + Assert.NotNull(result); + Assert.Equal(true, result["flag"]); + } - [Fact] - public void Read_ShouldHandleNullValue() - { - var json = """{"key": null}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleNullValue() + { + var json = """{"key": null}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.Null(result["key"]); - } + Assert.NotNull(result); + Assert.Null(result["key"]); + } - [Fact] - public void Read_ShouldHandleInt64Number() - { - var json = """{"count": 9876543210}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleInt64Number() + { + var json = """{"count": 9876543210}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.Equal(9876543210L, result["count"]); - } + Assert.NotNull(result); + Assert.Equal(9876543210L, result["count"]); + } - [Fact] - public void Read_ShouldHandleDecimalNumber() - { - var json = """{"price": 3.14}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleDecimalNumber() + { + var json = """{"price": 3.14}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.Equal(3.14m, result["price"]); - } + Assert.NotNull(result); + Assert.Equal(3.14m, result["price"]); + } - [Fact] - public void Read_ShouldHandleNestedObject() - { - var json = """{"outer": {"inner": "value"}}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleNestedObject() + { + var json = """{"outer": {"inner": "value"}}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - var nested = Assert.IsAssignableFrom(result["outer"]); - Assert.Equal("value", nested["inner"]); - } + Assert.NotNull(result); + var nested = Assert.IsAssignableFrom(result["outer"]); + Assert.Equal("value", nested["inner"]); + } - [Fact] - public void Read_ShouldHandleArrayValue() - { - var json = """{"items": ["a", "b", "c"]}"""; - var options = CreateOptions(); + [Fact] + public void Read_ShouldHandleArrayValue() + { + var json = """{"items": ["a", "b", "c"]}"""; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - var list = Assert.IsAssignableFrom>(result["items"]); - Assert.Equal(3, list.Count); - Assert.Equal("a", list[0]); - Assert.Equal("b", list[1]); - Assert.Equal("c", list[2]); + Assert.NotNull(result); + var list = Assert.IsAssignableFrom>(result["items"]); + Assert.Equal(3, list.Count); + Assert.Equal("a", list[0]); + Assert.Equal("b", list[1]); + Assert.Equal("c", list[2]); - TestOutput.WriteLine(string.Join(", ", list)); - } + TestOutput.WriteLine(string.Join(", ", list)); + } - [Fact] - public void Read_ShouldDeserializeDateTimeString() - { - var dt = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); - var json = $"{{\"ts\": \"{dt:O}\"}}"; - var options = CreateOptions(); + [Fact] + public void Read_ShouldDeserializeDateTimeString() + { + var dt = new DateTime(2023, 11, 16, 23, 24, 17, DateTimeKind.Utc); + var json = $"{{\"ts\": \"{dt:O}\"}}"; + var options = CreateOptions(); - var result = JsonSerializer.Deserialize(json, options); + var result = JsonSerializer.Deserialize(json, options); - Assert.NotNull(result); - Assert.IsType(result["ts"]); - Assert.Equal(dt, (DateTime)result["ts"]); + Assert.NotNull(result); + Assert.IsType(result["ts"]); + Assert.Equal(dt, (DateTime)result["ts"]); - TestOutput.WriteLine(result["ts"].ToString()); - } + TestOutput.WriteLine(result["ts"].ToString()); + } - [Fact] - public void Write_ShouldSerializeMetadataDictionary() - { - var md = new MetadataDictionary - { - { "key1", "value1" }, - { "key2", 99L }, - { "key3", false } - }; - - var options = CreateOptions(); - var json = JsonSerializer.Serialize(md, options); - - TestOutput.WriteLine(json); - - Assert.Contains("key1", json); - Assert.Contains("value1", json); - Assert.Contains("key2", json); - Assert.Contains("99", json); - Assert.Contains("key3", json); - Assert.Contains("false", json); - } - - private static JsonSerializerOptions CreateOptions() + [Fact] + public void Write_ShouldSerializeMetadataDictionary() + { + var md = new MetadataDictionary { - var options = new JsonSerializerOptions(); - options.Converters.Add(new MetadataDictionaryConverter()); - return options; - } + { "key1", "value1" }, + { "key2", 99L }, + { "key3", false } + }; + + var options = CreateOptions(); + var json = JsonSerializer.Serialize(md, options); + + TestOutput.WriteLine(json); + + Assert.Contains("key1", json); + Assert.Contains("value1", json); + Assert.Contains("key2", json); + Assert.Contains("99", json); + Assert.Contains("key3", json); + Assert.Contains("false", json); + } + + private static JsonSerializerOptions CreateOptions() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new MetadataDictionaryConverter()); + return options; } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Converters/RequestConverterTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Converters/RequestConverterTest.cs index 15e417a8..f1624deb 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Converters/RequestConverterTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Converters/RequestConverterTest.cs @@ -5,85 +5,84 @@ using Savvyio.Assets.Commands; using Xunit; -namespace Savvyio.Extensions.Text.Json.Converters +namespace Savvyio.Extensions.Text.Json.Converters; + +public class RequestConverterTest : Test { - public class RequestConverterTest : Test + public RequestConverterTest(ITestOutputHelper output) : base(output) { - public RequestConverterTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void RequestConverter_ShouldConvertOnlyRequests() - { - var sut = new RequestConverter(); + [Fact] + public void RequestConverter_ShouldConvertOnlyRequests() + { + var sut = new RequestConverter(); - Assert.True(sut.CanConvert(typeof(CreateMemberCommand))); - Assert.False(sut.CanConvert(typeof(string))); - } + Assert.True(sut.CanConvert(typeof(CreateMemberCommand))); + Assert.False(sut.CanConvert(typeof(string))); + } - [Fact] - public void RequestConverter_ShouldRehydrateAutoPropertyRequests() - { - var sut = JsonSerializer.Deserialize("{\"name\":\"Jane Doe\",\"age\":21,\"emailAddress\":\"jd@office.com\"}", CreateOptions()); + [Fact] + public void RequestConverter_ShouldRehydrateAutoPropertyRequests() + { + var sut = JsonSerializer.Deserialize("{\"name\":\"Jane Doe\",\"age\":21,\"emailAddress\":\"jd@office.com\"}", CreateOptions()); - Assert.NotNull(sut); - Assert.Equal("Jane Doe", sut.Name); - Assert.Equal((byte)21, sut.Age); - Assert.Equal("jd@office.com", sut.EmailAddress); - } + Assert.NotNull(sut); + Assert.Equal("Jane Doe", sut.Name); + Assert.Equal((byte)21, sut.Age); + Assert.Equal("jd@office.com", sut.EmailAddress); + } - [Fact] - public void RequestConverter_ShouldRehydrateWritableProperties() - { - var sut = JsonSerializer.Deserialize("{\"name\":\"Jane Doe\"}", CreateOptions()); + [Fact] + public void RequestConverter_ShouldRehydrateWritableProperties() + { + var sut = JsonSerializer.Deserialize("{\"name\":\"Jane Doe\"}", CreateOptions()); - Assert.NotNull(sut); - Assert.Equal("Jane Doe", sut.Name); - } + Assert.NotNull(sut); + Assert.Equal("Jane Doe", sut.Name); + } - [Fact] - public void RequestConverter_ShouldFailWhenNoSupportedBackingFieldExists() - { - var ex = Assert.Throws(() => JsonSerializer.Deserialize("{\"name\":\"Jane Doe\"}", CreateOptions())); + [Fact] + public void RequestConverter_ShouldFailWhenNoSupportedBackingFieldExists() + { + var ex = Assert.Throws(() => JsonSerializer.Deserialize("{\"name\":\"Jane Doe\"}", CreateOptions())); - Assert.StartsWith("This deserializer only supports rehydration", ex.Message); - } + Assert.StartsWith("This deserializer only supports rehydration", ex.Message); + } - [Fact] - public void RequestConverter_ShouldRoundtripThroughWrite() - { - var options = CreateOptions(); - var json = JsonSerializer.Serialize(new WritableRequest { Name = "Jane Doe" }, options); + [Fact] + public void RequestConverter_ShouldRoundtripThroughWrite() + { + var options = CreateOptions(); + var json = JsonSerializer.Serialize(new WritableRequest { Name = "Jane Doe" }, options); - TestOutput.WriteLine(json); + TestOutput.WriteLine(json); - var sut = JsonSerializer.Deserialize(json, options); + var sut = JsonSerializer.Deserialize(json, options); - Assert.NotNull(sut); - Assert.Equal("Jane Doe", sut.Name); - } + Assert.NotNull(sut); + Assert.Equal("Jane Doe", sut.Name); + } - private static JsonSerializerOptions CreateOptions() - { - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - options.Converters.Add(new RequestConverter()); - return options; - } - - private sealed class WritableRequest : IRequest + private static JsonSerializerOptions CreateOptions() + { + var options = new JsonSerializerOptions { - public string Name { get; set; } - } + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + options.Converters.Add(new RequestConverter()); + return options; + } - private sealed class UnsupportedRequest : IRequest - { - private readonly string _name = string.Empty; + private sealed class WritableRequest : IRequest + { + public string Name { get; set; } + } + + private sealed class UnsupportedRequest : IRequest + { + private readonly string _name = string.Empty; - public string Name => _name; - } + public string Name => _name; } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs index 61b33205..ec2e6693 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs @@ -4,61 +4,60 @@ using Savvyio.Assets.Domain; using Xunit; -namespace Savvyio.Extensions.Text.Json.Domain +namespace Savvyio.Extensions.Text.Json.Domain; + +public class DomainTest : Test { - public class DomainTest : Test + public DomainTest(ITestOutputHelper output) : base(output) { - public DomainTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Coordinates_ShouldBeAbleToBothSerializeAndDeserialize() - { - var sut = new Coordinates(10.1, 10.2); + [Fact] + public void Coordinates_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new Coordinates(10.1, 10.2); - var json = new JsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new JsonMarshaller().Deserialize(json); + var rehydrated = new JsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); + } - [Fact] - public void Timestamp_ShouldBeAbleToBothSerializeAndDeserialize() + [Fact] + public void Timestamp_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new Timestamp(DateTimeOffset.UtcNow) { - var sut = new Timestamp(DateTimeOffset.UtcNow) - { - IsDaylightSavingTime = false, - TimeZone = "Europe/Berlin" - }; + IsDaylightSavingTime = false, + TimeZone = "Europe/Berlin" + }; - var json = new JsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new JsonMarshaller().Deserialize(json); + var rehydrated = new JsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); + } - [Fact] - public void PlatformProviderId_ShouldBeAbleToBothSerializeAndDeserialize() - { - var sut = new PlatformProviderId(Guid.NewGuid()); + [Fact] + public void PlatformProviderId_ShouldBeAbleToBothSerializeAndDeserialize() + { + var sut = new PlatformProviderId(Guid.NewGuid()); - var json = new JsonMarshaller().Serialize(sut); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var rehydrated = new JsonMarshaller().Deserialize(json); + var rehydrated = new JsonMarshaller().Deserialize(json); - Assert.Equivalent(sut, rehydrated, true); - } + Assert.Equivalent(sut, rehydrated, true); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs index f8b1ea93..b9145f0d 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs @@ -9,64 +9,63 @@ using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; using Xunit; -namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.CloudEvents.Cryptography +namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.CloudEvents.Cryptography; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent() - .SignCloudEvent(JsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent() + .SignCloudEvent(JsonMarshaller.Default, o => + { + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); - var json = JsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = JsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = JsonMarshaller.Default.Deserialize>(json); + var sut4 = JsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"da3badf039aa727878add5d098cb98817382496720b5ef03f64882a50e05a3c8"}""", jsonString); - } + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"da3badf039aa727878add5d098cb98817382496720b5ef03f64882a50e05a3c8"}""", jsonString); + } - [Fact] - public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_ToCloudEvent_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent() + .SignCloudEvent(JsonMarshaller.Default, o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent() - .SignCloudEvent(JsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); - var json = JsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = JsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = JsonMarshaller.Default.Deserialize>(json); + var sut4 = JsonMarshaller.Default.Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"da3badf039aa727878add5d098cb98817382496720b5ef03f64882a50e05a3c8"}""", jsonString); - } + Assert.Equivalent(sut2, sut4, true); + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"specversion":"1.0","signature":"da3badf039aa727878add5d098cb98817382496720b5ef03f64882a50e05a3c8"}""", jsonString); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs index 923571e2..c36de0af 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs @@ -8,35 +8,35 @@ using Savvyio.EventDriven.Messaging.CloudEvents; using Xunit; -namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.CloudEvents +namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.CloudEvents; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).ToCloudEvent(); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).ToCloudEvent(); - var json = new JsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new JsonMarshaller().Deserialize>(json); + var sut4 = new JsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal(""" + Assert.Equal(""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -54,29 +54,29 @@ public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_U "specversion": "1.0" } """.ReplaceLineEndings(), jsonString); - } + } - [Fact] - public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utcNow = DateTime.UtcNow; + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }).ToCloudEvent(); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }).ToCloudEvent(); - var json = new JsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new JsonMarshaller().Deserialize>(json); + var sut4 = new JsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -94,6 +94,5 @@ public void ToMessage_ToCloudEvent_ShouldSerializeAndDeserialize_MemberCreated_U "specversion": "1.0" } """.ReplaceLineEndings(), jsonString); - } } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs index 00a20252..7158978f 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs @@ -8,78 +8,77 @@ using Savvyio.Messaging.Cryptography; using Xunit; -namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.Cryptography +namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging.Cryptography; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(JsonMarshaller.Default, o => { - } + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + var json = JsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + + TestOutput.WriteLine(jsonString); - [Fact] - public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + var signatureException = Assert.Throws(() => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(JsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - var json = JsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - - var signatureException = Assert.Throws(() => - { - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - - var sut4 = JsonMarshaller.Default.Deserialize>(json); - - Assert.Equivalent(sut2, sut4, true); - - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"e0b6ca2328019e236d9cd5590c20d12a2a92797f8feb34c044b92f36df013fac"}""", jsonString); - } - - [Fact] - public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + + var sut4 = JsonMarshaller.Default.Deserialize>(json); + + Assert.Equivalent(sut2, sut4, true); + + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"e0b6ca2328019e236d9cd5590c20d12a2a92797f8feb34c044b92f36df013fac"}""", jsonString); + } + + [Fact] + public void ToMessage_Sign_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => + { + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }).Sign(JsonMarshaller.Default, o => + { + o.SignatureSecret = new byte[] { 1, 2, 3 }; + }); + var json = JsonMarshaller.Default.Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + + TestOutput.WriteLine(jsonString); + + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); + + var signatureException = Assert.Throws(() => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }).Sign(JsonMarshaller.Default, o => - { - o.SignatureSecret = new byte[] { 1, 2, 3 }; - }); - var json = JsonMarshaller.Default.Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - - TestOutput.WriteLine(jsonString); - - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 1, 2, 3 }); - - var signatureException = Assert.Throws(() => - { - sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); - }); - Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); - - var sut4 = JsonMarshaller.Default.Deserialize>(json); - - Assert.Equivalent(sut2, sut4, true); - - Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"e0b6ca2328019e236d9cd5590c20d12a2a92797f8feb34c044b92f36df013fac"}""", jsonString); - } + sut2.CheckSignature(JsonMarshaller.Default, o => o.SignatureSecret = new byte[] { 3, 2, 1 }); + }); + Assert.StartsWith("The signature of the message does not match the cryptographically calculated value. Either you are using an incorrect secret and/or algorithm or the message has been tampered with.", signatureException.Message); + + var sut4 = JsonMarshaller.Default.Deserialize>(json); + + Assert.Equivalent(sut2, sut4, true); + + Assert.Equal("""{"id":"2d4030d32a254ee8a27046e5bafe696a","source":"https://fancy.api/members","type":"MemberCreated","time":"2023-11-16T23:24:17.8414532Z","data":{"name":"Jane Doe","emailAddress":"jd@office.com","metadata":{"memberType":"Savvyio.Assets.EventDriven.MemberCreated, Savvyio.Assets.Tests","eventId":"69bccf3b1117425397c5ed9ed757bb0f","timestamp":"2023-11-16T23:24:17.8414532Z"}},"signature":"e0b6ca2328019e236d9cd5590c20d12a2a92797f8feb34c044b92f36df013fac"}""", jsonString); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs index 7a1e8cc3..985082bc 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs @@ -8,35 +8,35 @@ using Savvyio.Messaging; using Xunit; -namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging +namespace Savvyio.Extensions.Text.Json.EventDriven.Messaging; + +public class IntegrationEventExtensionsTest : Test { - public class IntegrationEventExtensionsTest : Test + public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) { - public IntegrationEventExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + [Fact] + public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface() + { + var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utc = DateTime.Parse("2023-11-16T23:24:17.8414532Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal); - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utc); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utc; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utc; + }); - var json = new JsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new JsonMarshaller().Deserialize>(json); + var sut4 = new JsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal(""" + Assert.Equal(""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -53,29 +53,29 @@ public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingInterface } } """.ReplaceLineEndings(), jsonString); - } + } - [Fact] - public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + [Fact] + public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteType() + { + var utcNow = DateTime.UtcNow; + var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); + var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => { - var utcNow = DateTime.UtcNow; - var sut1 = new MemberCreated("Jane Doe", "jd@office.com").SetEventId("69bccf3b1117425397c5ed9ed757bb0f").SetTimestamp(utcNow); - var sut2 = sut1.ToMessage("https://fancy.api/members".ToUri(), nameof(MemberCreated), o => - { - o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; - o.Time = utcNow; - }); + o.MessageId = "2d4030d32a254ee8a27046e5bafe696a"; + o.Time = utcNow; + }); - var json = new JsonMarshaller().Serialize(sut2); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = new JsonMarshaller().Serialize(sut2); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var sut4 = new JsonMarshaller().Deserialize>(json); + var sut4 = new JsonMarshaller().Deserialize>(json); - Assert.Equivalent(sut2, sut4, true); + Assert.Equivalent(sut2, sut4, true); - Assert.Equal($$""" + Assert.Equal($$""" { "id": "2d4030d32a254ee8a27046e5bafe696a", "source": "https://fancy.api/members", @@ -92,6 +92,5 @@ public void ToMessage_ShouldSerializeAndDeserialize_MemberCreated_UsingConcreteT } } """.ReplaceLineEndings(), jsonString); - } } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/JsonConverterExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/JsonConverterExtensionsTest.cs index 110c857b..a884c25e 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/JsonConverterExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/JsonConverterExtensionsTest.cs @@ -6,113 +6,112 @@ using Savvyio.Extensions.Text.Json.Converters; using Xunit; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +public class JsonConverterExtensionsTest : Test { - public class JsonConverterExtensionsTest : Test + public JsonConverterExtensionsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void AddDateTimeConverter_ShouldAddConverter() + { + var converters = new List(); + converters.AddDateTimeConverter(); + + Assert.Single(converters, c => c is DateTimeConverter); + } + + [Fact] + public void AddDateTimeOffsetConverter_ShouldAddConverter() + { + var converters = new List(); + converters.AddDateTimeOffsetConverter(); + + Assert.Single(converters, c => c is DateTimeOffsetConverter); + } + + [Fact] + public void AddSingleValueObjectConverter_ShouldAddConverter() + { + var converters = new List(); + converters.AddSingleValueObjectConverter(); + + Assert.Single(converters, c => c is SingleValueObjectConverter); + } + + [Fact] + public void AddMetadataDictionaryConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddMetadataDictionaryConverter()); + } + + [Fact] + public void AddMessageConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddMessageConverter()); + } + + [Fact] + public void AddRequestConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddRequestConverter()); + } + + [Fact] + public void AddDateTimeConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddDateTimeConverter()); + } + + [Fact] + public void AddDateTimeOffsetConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddDateTimeOffsetConverter()); + } + + [Fact] + public void AddSingleValueObjectConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).AddSingleValueObjectConverter()); + } + + [Fact] + public void RemoveAllOf_Generic_ShouldRemoveMatchingConverter() + { + var converters = new List(); + converters.AddDateTimeConverter(); + converters.AddDateTimeOffsetConverter(); + + Assert.Equal(2, converters.Count); + + converters.RemoveAllOf(); + + Assert.DoesNotContain(converters, c => c is DateTimeConverter); + } + + [Fact] + public void RemoveAllOf_Generic_ShouldThrowArgumentNullException_WhenConvertersIsNull() + { + Assert.Throws(() => ((ICollection)null).RemoveAllOf()); + } + + [Fact] + public void RemoveAllOf_Params_ShouldRemoveMatchingConverters() + { + var converters = new List(); + converters.AddDateTimeConverter(); + converters.AddDateTimeOffsetConverter(); + + converters.RemoveAllOf(typeof(DateTime), typeof(DateTimeOffset)); + + Assert.Empty(converters); + } + + [Fact] + public void RemoveAllOf_Params_ShouldThrowArgumentNullException_WhenConvertersIsNull() { - public JsonConverterExtensionsTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void AddDateTimeConverter_ShouldAddConverter() - { - var converters = new List(); - converters.AddDateTimeConverter(); - - Assert.Single(converters, c => c is DateTimeConverter); - } - - [Fact] - public void AddDateTimeOffsetConverter_ShouldAddConverter() - { - var converters = new List(); - converters.AddDateTimeOffsetConverter(); - - Assert.Single(converters, c => c is DateTimeOffsetConverter); - } - - [Fact] - public void AddSingleValueObjectConverter_ShouldAddConverter() - { - var converters = new List(); - converters.AddSingleValueObjectConverter(); - - Assert.Single(converters, c => c is SingleValueObjectConverter); - } - - [Fact] - public void AddMetadataDictionaryConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddMetadataDictionaryConverter()); - } - - [Fact] - public void AddMessageConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddMessageConverter()); - } - - [Fact] - public void AddRequestConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddRequestConverter()); - } - - [Fact] - public void AddDateTimeConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddDateTimeConverter()); - } - - [Fact] - public void AddDateTimeOffsetConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddDateTimeOffsetConverter()); - } - - [Fact] - public void AddSingleValueObjectConverter_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).AddSingleValueObjectConverter()); - } - - [Fact] - public void RemoveAllOf_Generic_ShouldRemoveMatchingConverter() - { - var converters = new List(); - converters.AddDateTimeConverter(); - converters.AddDateTimeOffsetConverter(); - - Assert.Equal(2, converters.Count); - - converters.RemoveAllOf(); - - Assert.DoesNotContain(converters, c => c is DateTimeConverter); - } - - [Fact] - public void RemoveAllOf_Generic_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).RemoveAllOf()); - } - - [Fact] - public void RemoveAllOf_Params_ShouldRemoveMatchingConverters() - { - var converters = new List(); - converters.AddDateTimeConverter(); - converters.AddDateTimeOffsetConverter(); - - converters.RemoveAllOf(typeof(DateTime), typeof(DateTimeOffset)); - - Assert.Empty(converters); - } - - [Fact] - public void RemoveAllOf_Params_ShouldThrowArgumentNullException_WhenConvertersIsNull() - { - Assert.Throws(() => ((ICollection)null).RemoveAllOf(typeof(DateTime))); - } + Assert.Throws(() => ((ICollection)null).RemoveAllOf(typeof(DateTime))); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/JsonSerializerOptionsExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/JsonSerializerOptionsExtensionsTest.cs index ba2678fd..93fdb3c6 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/JsonSerializerOptionsExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/JsonSerializerOptionsExtensionsTest.cs @@ -4,39 +4,38 @@ using Savvyio.Extensions.Text.Json.Converters; using Xunit; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +public class JsonSerializerOptionsExtensionsTest : Test { - public class JsonSerializerOptionsExtensionsTest : Test + public JsonSerializerOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public JsonSerializerOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void Clone_ShouldThrowArgumentNullException_WhenOptionsIsNull() - { - Assert.Throws(() => ((JsonSerializerOptions)null).Clone()); - } + [Fact] + public void Clone_ShouldThrowArgumentNullException_WhenOptionsIsNull() + { + Assert.Throws(() => ((JsonSerializerOptions)null).Clone()); + } - [Fact] - public void Clone_ShouldReturnNewInstance_WithoutSetup() - { - var original = new JsonSerializerOptions { WriteIndented = true }; - var cloned = original.Clone(); + [Fact] + public void Clone_ShouldReturnNewInstance_WithoutSetup() + { + var original = new JsonSerializerOptions { WriteIndented = true }; + var cloned = original.Clone(); - Assert.NotSame(original, cloned); - Assert.True(cloned.WriteIndented); - } + Assert.NotSame(original, cloned); + Assert.True(cloned.WriteIndented); + } - [Fact] - public void Clone_ShouldApplySetup_WhenProvided() - { - var original = new JsonSerializerOptions { WriteIndented = true }; - var cloned = original.Clone(o => o.WriteIndented = false); + [Fact] + public void Clone_ShouldApplySetup_WhenProvided() + { + var original = new JsonSerializerOptions { WriteIndented = true }; + var cloned = original.Clone(o => o.WriteIndented = false); - Assert.NotSame(original, cloned); - Assert.True(original.WriteIndented); - Assert.False(cloned.WriteIndented); - } + Assert.NotSame(original, cloned); + Assert.True(original.WriteIndented); + Assert.False(cloned.WriteIndented); } } diff --git a/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs index 6dd71f27..364fc99d 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs @@ -4,37 +4,36 @@ using Codebelt.Extensions.Xunit; using Xunit; -namespace Savvyio.Extensions.Text.Json +namespace Savvyio.Extensions.Text.Json; + +public class MetadataDictionaryTest : Test { - public class MetadataDictionaryTest : Test + public MetadataDictionaryTest(ITestOutputHelper output) : base(output) { - public MetadataDictionaryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void MetadataDictionary_ShouldUseCustomConverter() + [Fact] + public void MetadataDictionary_ShouldUseCustomConverter() + { + var md = new MetadataDictionary() { - var md = new MetadataDictionary() - { - { "guid", $"{Guid.NewGuid()}" }, - { "int32", 2312313 }, - { "dateTime", DateTime.UtcNow } - }; + { "guid", $"{Guid.NewGuid()}" }, + { "int32", 2312313 }, + { "dateTime", DateTime.UtcNow } + }; - var json = JsonFormatter.SerializeObject(md); - var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); + var json = JsonFormatter.SerializeObject(md); + var jsonString = json.ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(jsonString); + TestOutput.WriteLine(jsonString); - var mdRehydrated = JsonFormatter.DeserializeObject(json, o => - { - o.Settings.Converters - .AddMessageConverter() - .AddMetadataDictionaryConverter(); - }); + var mdRehydrated = JsonFormatter.DeserializeObject(json, o => + { + o.Settings.Converters + .AddMessageConverter() + .AddMetadataDictionaryConverter(); + }); - Assert.Equivalent(md, mdRehydrated, true); - } + Assert.Equivalent(md, mdRehydrated, true); } } diff --git a/test/Savvyio.FunctionalTests/Assets/AccountData.cs b/test/Savvyio.FunctionalTests/Assets/AccountData.cs index 72b7b622..f814a660 100644 --- a/test/Savvyio.FunctionalTests/Assets/AccountData.cs +++ b/test/Savvyio.FunctionalTests/Assets/AccountData.cs @@ -7,37 +7,36 @@ using Savvyio.Assets.Queries; using Savvyio.Extensions.Dapper; -namespace Savvyio.Assets +namespace Savvyio.Assets; + +public class AccountData : DapperDataStore { - public class AccountData : DapperDataStore + public AccountData(IDapperDataSource source) : base(source) { - public AccountData(IDapperDataSource source) : base(source) - { - } + } - public override Task CreateAsync(AccountProjection dto, Action setup = null) - { - return Source.ExecuteAsync("INSERT INTO AccountProjection (Id, FullName, EmailAddress) VALUES (@Id, @FullName, @EmailAddress)", dto); - } + public override Task CreateAsync(AccountProjection dto, Action setup = null) + { + return Source.ExecuteAsync("INSERT INTO AccountProjection (Id, FullName, EmailAddress) VALUES (@Id, @FullName, @EmailAddress)", dto); + } - public override Task UpdateAsync(AccountProjection dto, Action setup = null) - { - throw new NotImplementedException(); - } + public override Task UpdateAsync(AccountProjection dto, Action setup = null) + { + throw new NotImplementedException(); + } - public override Task GetByIdAsync(object id, Action setup) - { - return Source.QuerySingleOrDefaultAsync("SELECT * FROM AccountProjection WHERE Id = @Id", new { Id = id }); - } + public override Task GetByIdAsync(object id, Action setup) + { + return Source.QuerySingleOrDefaultAsync("SELECT * FROM AccountProjection WHERE Id = @Id", new { Id = id }); + } - public override Task> FindAllAsync(Action setup = null) - { - return setup == null ? Source.QueryAsync("SELECT * FROM AccountProjection") : Source.QueryAsync(setup.Configure()); - } + public override Task> FindAllAsync(Action setup = null) + { + return setup == null ? Source.QueryAsync("SELECT * FROM AccountProjection") : Source.QueryAsync(setup.Configure()); + } - public override Task DeleteAsync(AccountProjection dto, Action setup = null) - { - throw new NotImplementedException(); - } + public override Task DeleteAsync(AccountProjection dto, Action setup = null) + { + throw new NotImplementedException(); } } diff --git a/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs b/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs index f99f3802..1406af5c 100644 --- a/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs +++ b/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs @@ -38,170 +38,169 @@ using Xunit; using Xunit.v3.Priority; -namespace Savvyio +namespace Savvyio; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class DistributedMediatorTest : Test { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class DistributedMediatorTest : Test - { - private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - private static readonly string UniqueId = $"{Guid.NewGuid():N}"; + private static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + private static readonly string UniqueId = $"{Guid.NewGuid():N}"; - public DistributedMediatorTest() - { - NewtonsoftJsonFormatterOptions.DefaultConverters += list => list.Add(new ValueObjectConverter()); - } + public DistributedMediatorTest() + { + NewtonsoftJsonFormatterOptions.DefaultConverters += list => list.Add(new ValueObjectConverter()); + } - [Fact, Priority(0)] - public async Task EmulateWebApi_Controller_SendCommand() + [Fact, Priority(0)] + public async Task EmulateWebApi_Controller_SendCommand() + { + await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => { - await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => + services.AddMarshaller(); + services.AddAmazonCommandQueue(o => { - services.AddMarshaller(); - services.AddAmazonCommandQueue(o => - { - o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test"); - }); - - AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test"); }); - var correlationId = Guid.NewGuid().ToString("N"); - var platformProviderId = Guid.NewGuid(); - var fullName = "Michael Amazortensen"; - var emailAddress = IsLinux ? $"linux-{UniqueId}@aws.dev" : $"windows-{UniqueId}@aws.dev"; - var createAccount = new CreateAccount(platformProviderId, fullName, emailAddress).SetCorrelationId(correlationId); + AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + }); + var correlationId = Guid.NewGuid().ToString("N"); + var platformProviderId = Guid.NewGuid(); + var fullName = "Michael Amazortensen"; + var emailAddress = IsLinux ? $"linux-{UniqueId}@aws.dev" : $"windows-{UniqueId}@aws.dev"; - var commandQueue = test.Host.Services.GetRequiredService>(); + var createAccount = new CreateAccount(platformProviderId, fullName, emailAddress).SetCorrelationId(correlationId); - await commandQueue.SendAsync(createAccount.ToMessage("urn:command:create-account".ToUri(), nameof(createAccount)).Yield()).ConfigureAwait(false); - } + var commandQueue = test.Host.Services.GetRequiredService>(); - [Fact, Priority(1)] - public async Task EmulateWorker_ReceiveCommand() + await commandQueue.SendAsync(createAccount.ToMessage("urn:command:create-account".ToUri(), nameof(createAccount)).Yield()).ConfigureAwait(false); + } + + [Fact, Priority(1)] + public async Task EmulateWorker_ReceiveCommand() + { + await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => { - await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => + services.AddMarshaller(); + services.AddEfCoreAggregateDataSource(o => { - services.AddMarshaller(); - services.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase($"AWS{nameof(Account)}").EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddAccount(); - }).AddEfCoreRepository(); + o.ContextConfigurator = b => b.UseInMemoryDatabase($"AWS{nameof(Account)}").EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddAccount(); + }).AddEfCoreRepository(); - services.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase($"AWS{nameof(PlatformProvider)}").EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddPlatformProvider(); - }).AddEfCoreRepository(); + services.AddEfCoreAggregateDataSource(o => + { + o.ContextConfigurator = b => b.UseInMemoryDatabase($"AWS{nameof(PlatformProvider)}").EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddPlatformProvider(); + }).AddEfCoreRepository(); - services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection().SetDefaults().AddAccountTable().AddPlatformProviderTable()) - .AddDapperDataStore() - .AddDapperExtensionsDataStore(); + services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection().SetDefaults().AddAccountTable().AddPlatformProviderTable()) + .AddDapperDataStore() + .AddDapperExtensionsDataStore(); - services.AddAmazonCommandQueue(o => - { - o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test"); - o.ReceiveContext.AssumeMessageProcessed = false; - o.ReceiveContext.VisibilityTimeout = TimeSpan.FromSeconds(5); - }); - - services.AddAmazonEventBus(o => - { - o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test.fifo"); - }); + services.AddAmazonCommandQueue(o => + { + o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test"); + o.ReceiveContext.AssumeMessageProcessed = false; + o.ReceiveContext.VisibilityTimeout = TimeSpan.FromSeconds(5); + }); - services.AddSavvyIO(o => - { - o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator(); - }); + services.AddAmazonEventBus(o => + { + o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test.fifo"); + }); - AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + services.AddSavvyIO(o => + { + o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator(); }); - await Task.Delay(TimeSpan.FromSeconds(5)); - using var scope = test.Host.Services.GetService().CreateScope(); + AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + }); + await Task.Delay(TimeSpan.FromSeconds(5)); - var commandQueue = scope.ServiceProvider.GetRequiredService>(); - var mediator = scope.ServiceProvider.GetRequiredService(); + using var scope = test.Host.Services.GetService().CreateScope(); - IMessage createAccountMessage = null; - var cmdDeadline = DateTime.UtcNow.AddSeconds(90); - while (createAccountMessage == null && DateTime.UtcNow < cmdDeadline) + var commandQueue = scope.ServiceProvider.GetRequiredService>(); + var mediator = scope.ServiceProvider.GetRequiredService(); + + IMessage createAccountMessage = null; + var cmdDeadline = DateTime.UtcNow.AddSeconds(90); + while (createAccountMessage == null && DateTime.UtcNow < cmdDeadline) + { + await foreach (var msg in commandQueue.ReceiveAsync()) { - await foreach (var msg in commandQueue.ReceiveAsync()) + if (msg.Data is CreateAccount ca && ca.EmailAddress.Contains(UniqueId)) { - if (msg.Data is CreateAccount ca && ca.EmailAddress.Contains(UniqueId)) - { - await msg.AcknowledgeAsync().ConfigureAwait(false); - createAccountMessage = msg; - } + await msg.AcknowledgeAsync().ConfigureAwait(false); + createAccountMessage = msg; } } + } - Assert.NotNull(createAccountMessage); - var receivedCommand = Assert.IsType(createAccountMessage.Data); + Assert.NotNull(createAccountMessage); + var receivedCommand = Assert.IsType(createAccountMessage.Data); - await mediator.CommitAsync(receivedCommand); + await mediator.CommitAsync(receivedCommand); - var accounts = scope.ServiceProvider.GetRequiredService>(); + var accounts = scope.ServiceProvider.GetRequiredService>(); - var entity = await accounts.FindAllAsync(account => account.EmailAddress == receivedCommand.EmailAddress).SingleOrDefaultAsync(); + var entity = await accounts.FindAllAsync(account => account.EmailAddress == receivedCommand.EmailAddress).SingleOrDefaultAsync(); - var dao = await mediator.QueryAsync(new GetAccount(entity.Id)).ConfigureAwait(false); + var dao = await mediator.QueryAsync(new GetAccount(entity.Id)).ConfigureAwait(false); - Assert.Equal(entity.Id, dao.Id); - Assert.Equal(entity.EmailAddress, dao.EmailAddress); - Assert.Equal(entity.FullName, dao.FullName); + Assert.Equal(entity.Id, dao.Id); + Assert.Equal(entity.EmailAddress, dao.EmailAddress); + Assert.Equal(entity.FullName, dao.FullName); - await Task.Delay(TimeSpan.FromSeconds(5)); - } + await Task.Delay(TimeSpan.FromSeconds(5)); + } - [Fact, Priority(2)] - public async Task EmulateAnotherWorker_SubscribingToAccountCreated() + [Fact, Priority(2)] + public async Task EmulateAnotherWorker_SubscribingToAccountCreated() + { + await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => { - await using var test = WebHostTestFactory.CreateWithHostBuilderContext((context, services) => + services.Configure(o => o.Settings.Converters.AddMessageConverter().AddMetadataDictionaryConverter()); + services.AddMarshaller(); + services.AddAmazonEventBus(o => { - services.Configure(o => o.Settings.Converters.AddMessageConverter().AddMetadataDictionaryConverter()); - services.AddMarshaller(); - services.AddAmazonEventBus(o => - { - o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); - o.Endpoint = RegionEndpoint.EUWest1; - o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test.fifo"); - o.ReceiveContext.AssumeMessageProcessed = false; - o.ReceiveContext.VisibilityTimeout = TimeSpan.FromSeconds(5); - }); - - AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + o.Credentials = new BasicAWSCredentials(context.Configuration["AWS:IAM:AccessKey"], context.Configuration["AWS:IAM:SecretKey"]); + o.Endpoint = RegionEndpoint.EUWest1; + o.SourceQueue = new Uri($"https://sqs.eu-west-1.amazonaws.com/{context.Configuration["AWS:CallerIdentity"]}/distribute-mediator-test.fifo"); + o.ReceiveContext.AssumeMessageProcessed = false; + o.ReceiveContext.VisibilityTimeout = TimeSpan.FromSeconds(5); }); - var eventBus = test.Host.Services.GetRequiredService>(); - var invocationCount = 0; - var deadline = DateTime.UtcNow.AddSeconds(90); - while (invocationCount == 0 && DateTime.UtcNow < deadline) + AmazonResourceNameOptions.DefaultAccountId = context.Configuration["AWS:CallerIdentity"]; + }); + var eventBus = test.Host.Services.GetRequiredService>(); + + var invocationCount = 0; + var deadline = DateTime.UtcNow.AddSeconds(90); + while (invocationCount == 0 && DateTime.UtcNow < deadline) + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await eventBus.SubscribeAsync(async (message, token) => { - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - await eventBus.SubscribeAsync(async (message, token) => + if (message.Data is AccountCreated ac && ac.EmailAddress.Contains(UniqueId)) { - if (message.Data is AccountCreated ac && ac.EmailAddress.Contains(UniqueId)) - { - invocationCount++; - await message.AcknowledgeAsync().ConfigureAwait(false); - cts.Cancel(); - } - }, o => - { - o.CancellationToken = cts.Token; - o.ThrowIfCancellationWasRequested = false; - }).ConfigureAwait(false); - } - Assert.Equal(1, invocationCount); + invocationCount++; + await message.AcknowledgeAsync().ConfigureAwait(false); + cts.Cancel(); + } + }, o => + { + o.CancellationToken = cts.Token; + o.ThrowIfCancellationWasRequested = false; + }).ConfigureAwait(false); } + Assert.Equal(1, invocationCount); } } diff --git a/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs b/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs index 1f1b72c3..15953d35 100644 --- a/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs @@ -6,36 +6,36 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Savvyio.Extensions.DependencyInjection +namespace Savvyio.Extensions.DependencyInjection; + +public class ServiceCollectionExtensionsTest : Test { - public class ServiceCollectionExtensionsTest : Test + public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) { - public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddHandlerServicesDescriptor_ShouldAddHandlerServiceDescriptorAsIHandlerServicesDescriptor() - { - using var test = HostTestFactory.Create( - services => - { - services.AddXunitTestLogging(TestOutput); - services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); - services.AddHandlerServicesDescriptor(); - }); + [Fact] + public void AddHandlerServicesDescriptor_ShouldAddHandlerServiceDescriptorAsIHandlerServicesDescriptor() + { + using var test = HostTestFactory.Create( + services => + { + services.AddXunitTestLogging(TestOutput); + services.AddSavvyIO(o => o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); + services.AddHandlerServicesDescriptor(); + }); - test.Host.Services.WriteHandlerDiscoveriesToLog(); + test.Host.Services.WriteHandlerDiscoveriesToLog(); - var loggerEntry = test.Host.Services.GetRequiredService>() - .GetTestStore() - .Query(entry => entry.Severity == LogLevel.Information && entry.Message.Contains("Discovered 2 ICommandHandler implementations")) - .SingleOrDefault(); + var loggerEntry = test.Host.Services.GetRequiredService>() + .GetTestStore() + .Query(entry => entry.Severity == LogLevel.Information && entry.Message.Contains("Discovered 2 ICommandHandler implementations")) + .SingleOrDefault(); - Assert.NotNull(loggerEntry); - Assert.NotNull(test.Host.Services.GetService()); - Assert.IsType(test.Host.Services.GetService()); - Assert.Equal(""" + Assert.NotNull(loggerEntry); + Assert.NotNull(test.Host.Services.GetService()); + Assert.IsType(test.Host.Services.GetService()); + Assert.Equal(""" Information: Discovered 2 ICommandHandler implementations covering a total of 5 ICommand methods Assembly: Savvyio.Assets.Tests @@ -102,21 +102,20 @@ Discovered 1 IQueryHandler implementation covering a total of 4 IQuery methods ------------------------------------------------------------------------------ """.ReplaceLineEndings(), loggerEntry.Message); - } + } - [Fact] - public void AddHandlerServicesDescriptor_ShouldThrowInvalidOperationException_SinceEnableHandlerServicesDescriptorWasNotSetupInAddSavvyIO() - { - using var test = HostTestFactory.Create( - services => - { - services.AddXunitTestLogging(TestOutput); - services.AddSavvyIO(o => o.UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); - services.AddHandlerServicesDescriptor(); - }); + [Fact] + public void AddHandlerServicesDescriptor_ShouldThrowInvalidOperationException_SinceEnableHandlerServicesDescriptorWasNotSetupInAddSavvyIO() + { + using var test = HostTestFactory.Create( + services => + { + services.AddXunitTestLogging(TestOutput); + services.AddSavvyIO(o => o.UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true)); + services.AddHandlerServicesDescriptor(); + }); - Assert.Throws(() => test.Host.Services.WriteHandlerDiscoveriesToLog()); - Assert.Null(test.Host.Services.GetService()); - } + Assert.Throws(() => test.Host.Services.WriteHandlerDiscoveriesToLog()); + Assert.Null(test.Host.Services.GetService()); } } diff --git a/test/Savvyio.FunctionalTests/MediatorTest.cs b/test/Savvyio.FunctionalTests/MediatorTest.cs index c9440895..11d32bee 100644 --- a/test/Savvyio.FunctionalTests/MediatorTest.cs +++ b/test/Savvyio.FunctionalTests/MediatorTest.cs @@ -28,54 +28,54 @@ using Xunit.v3.Priority; using YamlDotNet.Serialization.NamingConventions; -namespace Savvyio +namespace Savvyio; + +[TestMethodOrderer(typeof(PriorityMethodOrderer))] +public class MediatorTest : HostTest { - [TestMethodOrderer(typeof(PriorityMethodOrderer))] - public class MediatorTest : HostTest - { - private IServiceProvider _provider; + private IServiceProvider _provider; - public MediatorTest(ManagedHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) - { - _provider = hostFixture.Host.Services.CreateScope().ServiceProvider; - } + public MediatorTest(ManagedHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) + { + _provider = hostFixture.Host.Services.CreateScope().ServiceProvider; + } - [Fact, Priority(0)] - public async Task RegisterNewUser() - { - var correlationId = Guid.NewGuid().ToString("N"); - var caPpId = Guid.NewGuid(); - var caFullName = "Michael Mortensen"; - var caEmailAddress = "root@gimlichael.dev"; + [Fact, Priority(0)] + public async Task RegisterNewUser() + { + var correlationId = Guid.NewGuid().ToString("N"); + var caPpId = Guid.NewGuid(); + var caFullName = "Michael Mortensen"; + var caEmailAddress = "root@gimlichael.dev"; - var mediator = _provider.GetRequiredService(); + var mediator = _provider.GetRequiredService(); - var hsd = _provider.GetRequiredService(); - var plaintext = hsd.ToString(); + var hsd = _provider.GetRequiredService(); + var plaintext = hsd.ToString(); - var mappings = hsd.GenerateHandlerDiscoveries(); - var json = JsonMarshaller.Create().Serialize(mappings).ToEncodedString(o => o.LeaveOpen = true); - var newtonsoftJson = NewtonsoftJsonMarshaller.Create().Serialize(mappings).ToEncodedString(o => o.LeaveOpen = true); - var yaml = YamlFormatter.SerializeObject(mappings, o => o.Settings.NamingConvention = CamelCaseNamingConvention.Instance).ToEncodedString(o => o.LeaveOpen = true); + var mappings = hsd.GenerateHandlerDiscoveries(); + var json = JsonMarshaller.Create().Serialize(mappings).ToEncodedString(o => o.LeaveOpen = true); + var newtonsoftJson = NewtonsoftJsonMarshaller.Create().Serialize(mappings).ToEncodedString(o => o.LeaveOpen = true); + var yaml = YamlFormatter.SerializeObject(mappings, o => o.Settings.NamingConvention = CamelCaseNamingConvention.Instance).ToEncodedString(o => o.LeaveOpen = true); - TestOutput.WriteLine(json); + TestOutput.WriteLine(json); - TestOutput.WriteLine(System.Environment.NewLine); - TestOutput.WriteLine("---"); - TestOutput.WriteLine(System.Environment.NewLine); + TestOutput.WriteLine(System.Environment.NewLine); + TestOutput.WriteLine("---"); + TestOutput.WriteLine(System.Environment.NewLine); - TestOutput.WriteLine(yaml); + TestOutput.WriteLine(yaml); - var accountRepo = _provider.GetRequiredService>(); + var accountRepo = _provider.GetRequiredService>(); - await mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress).SetCorrelationId(correlationId)); + await mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress).SetCorrelationId(correlationId)); - var entity = await accountRepo.FindAllAsync(a => a.Metadata.Contains(new KeyValuePair(MetadataDictionary.CorrelationId, correlationId))).SingleOrDefaultAsync(); + var entity = await accountRepo.FindAllAsync(a => a.Metadata.Contains(new KeyValuePair(MetadataDictionary.CorrelationId, correlationId))).SingleOrDefaultAsync(); - var dao = await mediator.QueryAsync(new GetAccount(entity.Id)).ConfigureAwait(false); + var dao = await mediator.QueryAsync(new GetAccount(entity.Id)).ConfigureAwait(false); - Assert.True(Match(""" + Assert.True(Match(""" Discovered 2 ICommandHandler implementations covering a total of 5 ICommand methods Assembly: Savvyio.Assets.Tests @@ -142,8 +142,8 @@ Discovered 1 IQueryHandler implementation covering a total of 4 IQuery methods ------------------------------------------------------------------------------ """.ReplaceLineEndings(), plaintext, o => o.ThrowOnNoMatch = true)); - Assert.Equal(json, newtonsoftJson); - Assert.True(Match(""" + Assert.Equal(json, newtonsoftJson); + Assert.True(Match(""" [ { "abstractionType": "ICommandHandler", @@ -335,7 +335,7 @@ Discovered 1 IQueryHandler implementation covering a total of 4 IQuery methods ] """.ReplaceLineEndings(), json, o => o.ThrowOnNoMatch = true)); - Assert.True(Match(""" + Assert.True(Match(""" - abstractionType: ICommandHandler implementationsCount: 2 delegateType: ICommand @@ -433,79 +433,78 @@ Discovered 1 IQueryHandler implementation covering a total of 4 IQuery methods """.ReplaceLineEndings(), yaml, o => o.ThrowOnNoMatch = true)); - Assert.Equal(entity.Id, dao.Id); - Assert.Equal(entity.EmailAddress, dao.EmailAddress); - Assert.Equal(entity.FullName, dao.FullName); + Assert.Equal(entity.Id, dao.Id); + Assert.Equal(entity.EmailAddress, dao.EmailAddress); + Assert.Equal(entity.FullName, dao.FullName); - } + } - [Fact, Priority(1)] - public async Task RegisterNewUser_ShouldFailWithValidationException_BecauseOfUniqueEmailAddress() - { - var correlationId = Guid.NewGuid().ToString("N"); - var caPpId = Guid.NewGuid(); - var caFullName = "El Presidente"; - var caEmailAddress = "root@gimlichael.dev"; + [Fact, Priority(1)] + public async Task RegisterNewUser_ShouldFailWithValidationException_BecauseOfUniqueEmailAddress() + { + var correlationId = Guid.NewGuid().ToString("N"); + var caPpId = Guid.NewGuid(); + var caFullName = "El Presidente"; + var caEmailAddress = "root@gimlichael.dev"; - var mediator = _provider.GetRequiredService(); + var mediator = _provider.GetRequiredService(); - await Assert.ThrowsAsync(() => mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress).SetCorrelationId(correlationId))); - } + await Assert.ThrowsAsync(() => mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress).SetCorrelationId(correlationId))); + } - [Fact, Priority(2)] - public async Task RegisterAnotherUser() - { - var caPpId = Guid.NewGuid(); - var caFullName = "El Presidento"; - var caEmailAddress = "makemyday@us.gov"; + [Fact, Priority(2)] + public async Task RegisterAnotherUser() + { + var caPpId = Guid.NewGuid(); + var caFullName = "El Presidento"; + var caEmailAddress = "makemyday@us.gov"; - var mediator = _provider.GetRequiredService(); + var mediator = _provider.GetRequiredService(); - await mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress)); - } + await mediator.CommitAsync(new CreateAccount(caPpId, caFullName, caEmailAddress)); + } - [Fact, Priority(3)] - public async Task VerifyUsers() + [Fact, Priority(3)] + public async Task VerifyUsers() + { + var accountRepo = _provider.GetRequiredService>(); + var accountDao = _provider.GetRequiredService>(); + var daos = new List(await accountDao.FindAllAsync().ConfigureAwait(false)); + var entities = new List(await accountRepo.FindAllAsync().ConfigureAwait(false)); + foreach (var entity in entities) { - var accountRepo = _provider.GetRequiredService>(); - var accountDao = _provider.GetRequiredService>(); - var daos = new List(await accountDao.FindAllAsync().ConfigureAwait(false)); - var entities = new List(await accountRepo.FindAllAsync().ConfigureAwait(false)); - foreach (var entity in entities) - { - TestOutput.WriteLine(entity.EmailAddress); - Assert.Equal(entity.Id, daos.Single(ac => ac.Id == entity.Id).Id); - Assert.Equal(entity.EmailAddress, daos.Single(ac => ac.Id == entity.Id).EmailAddress); - Assert.Equal(entity.FullName, daos.Single(ac => ac.Id == entity.Id).FullName); - } - - Assert.Equal(2, entities.Count); - Assert.Equal(2, daos.Count); + TestOutput.WriteLine(entity.EmailAddress); + Assert.Equal(entity.Id, daos.Single(ac => ac.Id == entity.Id).Id); + Assert.Equal(entity.EmailAddress, daos.Single(ac => ac.Id == entity.Id).EmailAddress); + Assert.Equal(entity.FullName, daos.Single(ac => ac.Id == entity.Id).FullName); } - public override void ConfigureServices(IServiceCollection services) + Assert.Equal(2, entities.Count); + Assert.Equal(2, daos.Count); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddEfCoreAggregateDataSource(o => { - services.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(Account)).EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddAccount(); - }).AddEfCoreRepository(); + o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(Account)).EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddAccount(); + }).AddEfCoreRepository(); - services.AddEfCoreAggregateDataSource(o => - { - o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); - o.ModelConstructor = mb => mb.AddPlatformProvider(); - }).AddEfCoreRepository(); + services.AddEfCoreAggregateDataSource(o => + { + o.ContextConfigurator = b => b.UseInMemoryDatabase(nameof(PlatformProvider)).EnableDetailedErrors().LogTo(Console.WriteLine); + o.ModelConstructor = mb => mb.AddPlatformProvider(); + }).AddEfCoreRepository(); - services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection().SetDefaults().AddAccountTable().AddPlatformProviderTable()) - .AddDapperDataStore() - .AddDapperExtensionsDataStore(); + services.AddDapperDataSource(o => o.ConnectionFactory = () => new SqliteConnection().SetDefaults().AddAccountTable().AddPlatformProviderTable()) + .AddDapperDataStore() + .AddDapperExtensionsDataStore(); - services.AddSavvyIO(o => - { - o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator(); - }) - .AddHandlerServicesDescriptor(); - } + services.AddSavvyIO(o => + { + o.EnableHandlerServicesDescriptor().UseAutomaticDispatcherDiscovery(true).UseAutomaticHandlerDiscovery(true).AddMediator(); + }) + .AddHandlerServicesDescriptor(); } } diff --git a/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs b/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs index 6d9f1547..a3b8ce31 100644 --- a/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs +++ b/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs @@ -1,6 +1,5 @@ -namespace Savvyio.Queries.Assets +namespace Savvyio.Queries.Assets; + +internal record DefaultQuery : Query { - internal record DefaultQuery : Query - { - } } diff --git a/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs b/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs index c8e098c2..6376e4bd 100644 --- a/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs +++ b/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs @@ -1,19 +1,18 @@ using System.Threading.Tasks; using Savvyio.Handlers; -namespace Savvyio.Queries.Assets +namespace Savvyio.Queries.Assets; + +internal class DefaultQueryHandler : QueryHandler { - internal class DefaultQueryHandler : QueryHandler + public DefaultQueryHandler() { - public DefaultQueryHandler() - { - } + } - protected override void RegisterDelegates(IRequestReplyRegistry handlers) - { - handlers.Register, string>(_ => nameof(DefaultQuery)); - handlers.RegisterAsync, string>(_ => Task.FromResult(nameof(DefaultQuery) + "Async")); - } + protected override void RegisterDelegates(IRequestReplyRegistry handlers) + { + handlers.Register, string>(_ => nameof(DefaultQuery)); + handlers.RegisterAsync, string>(_ => Task.FromResult(nameof(DefaultQuery) + "Async")); } } diff --git a/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs b/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs index ad858222..3ae4eb32 100644 --- a/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs +++ b/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs @@ -7,40 +7,39 @@ using Savvyio.Queries.Assets; using Xunit; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +public class QueryDispatcherTest : Test { - public class QueryDispatcherTest : Test + public QueryDispatcherTest(ITestOutputHelper output) : base(output) { - public QueryDispatcherTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void QueryDispatcher_Ensure_Initialization_Defaults() - { - var sp = new ServiceCollection().AddServiceLocator().BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); + [Fact] + public void QueryDispatcher_Ensure_Initialization_Defaults() + { + var sp = new ServiceCollection().AddServiceLocator().BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); - Assert.Throws(() => sut.Query(new DefaultQuery())); - Assert.ThrowsAsync(() => sut.QueryAsync(new DefaultQuery())); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - } + Assert.Throws(() => sut.Query(new DefaultQuery())); + Assert.ThrowsAsync(() => sut.QueryAsync(new DefaultQuery())); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + } - [Fact] - public async Task QueryDispatcher_ShouldQuery_DefaultQuery() - { - var sp = new ServiceCollection().AddServiceLocator().AddTransient().AddSingleton, InMemoryTestStore>().BuildServiceProvider(); - var sut = new QueryDispatcher(sp.GetRequiredService()); - var ts = sp.GetRequiredService>(); + [Fact] + public async Task QueryDispatcher_ShouldQuery_DefaultQuery() + { + var sp = new ServiceCollection().AddServiceLocator().AddTransient().AddSingleton, InMemoryTestStore>().BuildServiceProvider(); + var sut = new QueryDispatcher(sp.GetRequiredService()); + var ts = sp.GetRequiredService>(); - var qr = sut.Query(new DefaultQuery()); - var aqr = await sut.QueryAsync(new DefaultQuery()); + var qr = sut.Query(new DefaultQuery()); + var aqr = await sut.QueryAsync(new DefaultQuery()); - Assert.Equal(qr, nameof(DefaultQuery)); - Assert.Equal(aqr, nameof(DefaultQuery) + "Async"); - } + Assert.Equal(qr, nameof(DefaultQuery)); + Assert.Equal(aqr, nameof(DefaultQuery) + "Async"); } } diff --git a/test/Savvyio.Queries.Tests/QueryHandlerTest.cs b/test/Savvyio.Queries.Tests/QueryHandlerTest.cs index dcb26350..db47598d 100644 --- a/test/Savvyio.Queries.Tests/QueryHandlerTest.cs +++ b/test/Savvyio.Queries.Tests/QueryHandlerTest.cs @@ -4,25 +4,24 @@ using Savvyio.Queries.Assets; using Xunit; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +public class QueryHandlerTest : Test { - public class QueryHandlerTest : Test + public QueryHandlerTest(ITestOutputHelper output) : base(output) { - public QueryHandlerTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public async Task QueryHandler_Ensure_Initialization_Defaults() - { - var sut = new DefaultQueryHandler(); + [Fact] + public async Task QueryHandler_Ensure_Initialization_Defaults() + { + var sut = new DefaultQueryHandler(); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.True(sut.Delegates.TryInvoke(new DefaultQuery(), out _)); - Assert.True((await sut.Delegates.TryInvokeAsync(new DefaultQuery())).Succeeded); - Assert.False(sut.Delegates.TryInvoke(new GetAccount(1), out _)); - Assert.False((await sut.Delegates.TryInvokeAsync(new GetAccount(1))).Succeeded); - } + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.True(sut.Delegates.TryInvoke(new DefaultQuery(), out _)); + Assert.True((await sut.Delegates.TryInvokeAsync(new DefaultQuery())).Succeeded); + Assert.False(sut.Delegates.TryInvoke(new GetAccount(1), out _)); + Assert.False((await sut.Delegates.TryInvokeAsync(new GetAccount(1))).Succeeded); } } diff --git a/test/Savvyio.Queries.Tests/QueryTest.cs b/test/Savvyio.Queries.Tests/QueryTest.cs index 1bf96cb2..5cc8abce 100644 --- a/test/Savvyio.Queries.Tests/QueryTest.cs +++ b/test/Savvyio.Queries.Tests/QueryTest.cs @@ -3,30 +3,29 @@ using Savvyio.Queries.Assets; using Xunit; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +public class QueryTest : Test { - public class QueryTest : Test + public QueryTest(ITestOutputHelper output) : base(output) { - public QueryTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void DefaultQuery_Ensure_Initialization_Defaults() - { - var sut = new DefaultQuery(); + [Fact] + public void DefaultQuery_Ensure_Initialization_Defaults() + { + var sut = new DefaultQuery(); - Assert.IsAssignableFrom>(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom>(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.IsAssignableFrom(sut); - Assert.Collection(sut.Metadata, pair => - { - Assert.Equal(MetadataDictionary.MemberType, pair.Key); - Assert.Equal(typeof(DefaultQuery).ToFullNameIncludingAssemblyName(), pair.Value); - }); - } + Assert.IsAssignableFrom>(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom>(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.IsAssignableFrom(sut); + Assert.Collection(sut.Metadata, pair => + { + Assert.Equal(MetadataDictionary.MemberType, pair.Key); + Assert.Equal(typeof(DefaultQuery).ToFullNameIncludingAssemblyName(), pair.Value); + }); } } diff --git a/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs index 2bafe65f..6946e489 100644 --- a/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs @@ -2,42 +2,41 @@ using Savvyio.Assets; using Xunit; -namespace Savvyio.Queries +namespace Savvyio.Queries; + +public class SavvyioOptionsExtensionsTest : Test { - public class SavvyioOptionsExtensionsTest : Test + public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) { - public SavvyioOptionsExtensionsTest(ITestOutputHelper output) : base(output) - { - } + } - [Fact] - public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() - { - var sut = new SavvyioOptions().AddHandlers(); - Assert.Empty(sut.HandlerServiceTypes); - Assert.Empty(sut.HandlerImplementationTypes); - } + [Fact] + public void AddHandlers_ShouldNotAddAnyHandlersFromCurrentDomain() + { + var sut = new SavvyioOptions().AddHandlers(); + Assert.Empty(sut.HandlerServiceTypes); + Assert.Empty(sut.HandlerImplementationTypes); + } - [Fact] - public void AddQueryHandler_ShouldAddQueryHandler() - { - var sut = new SavvyioOptions().AddQueryHandler(); + [Fact] + public void AddQueryHandler_ShouldAddQueryHandler() + { + var sut = new SavvyioOptions().AddQueryHandler(); - Assert.NotEmpty(sut.HandlerServiceTypes); - Assert.NotEmpty(sut.HandlerImplementationTypes); - Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IQueryHandler), type)); - Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountQueryHandler), type)); - } + Assert.NotEmpty(sut.HandlerServiceTypes); + Assert.NotEmpty(sut.HandlerImplementationTypes); + Assert.Collection(sut.HandlerServiceTypes, type => Assert.Equal(typeof(IQueryHandler), type)); + Assert.Collection(sut.HandlerImplementationTypes, type => Assert.Equal(typeof(AccountQueryHandler), type)); + } - [Fact] - public void AddQueryDispatcher_ShouldAddQueryDispatcher() - { - var sut = new SavvyioOptions().AddQueryDispatcher(); + [Fact] + public void AddQueryDispatcher_ShouldAddQueryDispatcher() + { + var sut = new SavvyioOptions().AddQueryDispatcher(); - Assert.NotEmpty(sut.DispatcherServiceTypes); - Assert.NotEmpty(sut.DispatcherImplementationTypes); - Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IQueryDispatcher), type)); - Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(QueryDispatcher), type)); - } + Assert.NotEmpty(sut.DispatcherServiceTypes); + Assert.NotEmpty(sut.DispatcherImplementationTypes); + Assert.Collection(sut.DispatcherServiceTypes, type => Assert.Equal(typeof(IQueryDispatcher), type)); + Assert.Collection(sut.DispatcherImplementationTypes, type => Assert.Equal(typeof(QueryDispatcher), type)); } } From e95aba66b8cef8baa2da9ece482fe5fd68761c87 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:37:11 +0200 Subject: [PATCH 12/36] =?UTF-8?q?=F0=9F=94=A7=20enforce=20file-scoped=20na?= =?UTF-8?q?mespaces=20in=20editorconfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The namespace rule is now an error instead of a suggestion, and the note that existing block-scoped files should be left alone is removed. The codebase is converted in the previous commit, so the rule can be enforced without new violations. --- .editorconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index a083db5c..e6ec61ef 100644 --- a/.editorconfig +++ b/.editorconfig @@ -57,9 +57,8 @@ indent_size = 4 # IDE0161: Namespace declaration preferences # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0161 -# Prefer file-scoped namespaces for new files; existing block-scoped files should not be converted unless explicitly asked [*.cs] -csharp_style_namespace_declarations = file_scoped:suggestion +csharp_style_namespace_declarations = file_scoped:error # Top-level statements: DO NOT USE # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0210-ide0211 From dc29703258521186ac26c37adba903571b6c5fbc Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:39:57 +0200 Subject: [PATCH 13/36] =?UTF-8?q?=F0=9F=8E=A8=20normalize=20utf-8=20and=20?= =?UTF-8?q?lf=20line=20endings=20in=20sources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the UTF-8 byte order mark and normalize line endings to LF so the files match the charset and end_of_line rules in .editorconfig. --- src/Savvyio.Commands.Messaging/CommandExtensions.cs | 2 +- src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs | 2 +- src/Savvyio.Commands/Command.cs | 2 +- src/Savvyio.Commands/CommandDispatcher.cs | 2 +- src/Savvyio.Commands/CommandHandler.cs | 2 +- src/Savvyio.Commands/SavvyioOptionsExtensions.cs | 2 +- src/Savvyio.Core/AsyncEventHandler.cs | 2 +- src/Savvyio.Core/Commands/ICommand.cs | 2 +- src/Savvyio.Core/Commands/ICommandDispatcher.cs | 2 +- src/Savvyio.Core/Commands/ICommandHandler.cs | 2 +- src/Savvyio.Core/Data/IDataStore.cs | 2 +- src/Savvyio.Core/Data/IDeletableDataStore.cs | 2 +- src/Savvyio.Core/Data/IPersistentDataStore.cs | 2 +- src/Savvyio.Core/Data/IReadableDataStore.cs | 2 +- src/Savvyio.Core/Data/ISearchableDataStore.cs | 2 +- src/Savvyio.Core/Data/IWritableDataStore.cs | 2 +- src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs | 2 +- src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs | 2 +- src/Savvyio.Core/Dispatchers/Dispatcher.cs | 2 +- src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs | 2 +- src/Savvyio.Core/Dispatchers/IDispatcher.cs | 2 +- src/Savvyio.Core/Dispatchers/IServiceLocator.cs | 2 +- src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs | 2 +- src/Savvyio.Core/Dispatchers/ServiceLocator.cs | 2 +- src/Savvyio.Core/Domain/DomainException.cs | 2 +- .../Domain/EventSourcing/ITracedAggregateRepository.cs | 2 +- src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs | 2 +- src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs | 2 +- src/Savvyio.Core/Domain/IAggregateRepository.cs | 2 +- src/Savvyio.Core/Domain/IAggregateRoot.cs | 2 +- src/Savvyio.Core/Domain/IDeletableRepository.cs | 2 +- src/Savvyio.Core/Domain/IDomainEvent.cs | 2 +- src/Savvyio.Core/Domain/IDomainEventDispatcher.cs | 2 +- src/Savvyio.Core/Domain/IDomainEventHandler.cs | 2 +- src/Savvyio.Core/Domain/IEntity.cs | 2 +- src/Savvyio.Core/Domain/IPersistentRepository.cs | 2 +- src/Savvyio.Core/Domain/IReadableRepository.cs | 2 +- src/Savvyio.Core/Domain/IRepository.cs | 2 +- src/Savvyio.Core/Domain/ISearchableRepository.cs | 2 +- src/Savvyio.Core/Domain/IUnitOfWork.cs | 2 +- src/Savvyio.Core/Domain/IWritableRepository.cs | 2 +- src/Savvyio.Core/EventDriven/IIntegrationEvent.cs | 2 +- src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs | 2 +- src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs | 2 +- .../Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs | 2 +- .../EventDriven/Messaging/CloudEvents/ICloudEvent.cs | 2 +- src/Savvyio.Core/HandlerDiscoveryModel.cs | 2 +- src/Savvyio.Core/HandlerFactory.cs | 2 +- src/Savvyio.Core/Handlers/FireForgetManager.cs | 2 +- src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs | 2 +- src/Savvyio.Core/Handlers/IFireForgetActivator.cs | 2 +- src/Savvyio.Core/Handlers/IFireForgetHandler.cs | 2 +- src/Savvyio.Core/Handlers/IFireForgetRegistry.cs | 2 +- src/Savvyio.Core/Handlers/IRequestReplyActivator.cs | 2 +- src/Savvyio.Core/Handlers/IRequestReplyHandler.cs | 2 +- src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs | 2 +- src/Savvyio.Core/Handlers/OrphanedHandlerException.cs | 2 +- src/Savvyio.Core/Handlers/RequestReplyManager.cs | 2 +- src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs | 2 +- src/Savvyio.Core/IDataSource.cs | 2 +- src/Savvyio.Core/IHandler.cs | 2 +- src/Savvyio.Core/IHandlerServicesDescriptor.cs | 2 +- src/Savvyio.Core/IIdentity.cs | 2 +- src/Savvyio.Core/IMarshaller.cs | 2 +- src/Savvyio.Core/IMetadata.cs | 2 +- src/Savvyio.Core/IMetadataDictionary.cs | 2 +- src/Savvyio.Core/IRequest.cs | 2 +- src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs | 2 +- src/Savvyio.Core/Messaging/IAcknowledgeable.cs | 2 +- src/Savvyio.Core/Messaging/IMessage.cs | 2 +- src/Savvyio.Core/Messaging/IPointToPointChannel.cs | 2 +- src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs | 2 +- src/Savvyio.Core/Messaging/IPublisher.cs | 2 +- src/Savvyio.Core/Messaging/IReceiver.cs | 2 +- src/Savvyio.Core/Messaging/ISender.cs | 2 +- src/Savvyio.Core/Messaging/ISubscriber.cs | 2 +- src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs | 2 +- src/Savvyio.Core/MetadataDictionary.cs | 2 +- src/Savvyio.Core/MetadataExtensions.cs | 2 +- src/Savvyio.Core/MetadataFactory.cs | 2 +- src/Savvyio.Core/Queries/IQuery.cs | 2 +- src/Savvyio.Core/Queries/IQueryDispatcher.cs | 2 +- src/Savvyio.Core/Queries/IQueryHandler.cs | 2 +- src/Savvyio.Core/Request.cs | 2 +- src/Savvyio.Core/SavvyioOptions.cs | 2 +- src/Savvyio.Core/SavvyioOptionsExtensions.cs | 2 +- src/Savvyio.Core/TaskExtensions.cs | 2 +- src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs | 2 +- src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs | 2 +- src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs | 2 +- src/Savvyio.Domain/Aggregate.cs | 2 +- src/Savvyio.Domain/AggregateRoot.cs | 2 +- src/Savvyio.Domain/DomainEvent.cs | 2 +- src/Savvyio.Domain/DomainEventDispatcher.cs | 2 +- src/Savvyio.Domain/DomainEventDispatcherExtensions.cs | 2 +- src/Savvyio.Domain/DomainEventExtensions.cs | 2 +- src/Savvyio.Domain/DomainEventHandler.cs | 2 +- src/Savvyio.Domain/Entity.cs | 2 +- src/Savvyio.Domain/SavvyioOptionsExtensions.cs | 2 +- src/Savvyio.Domain/SingleValueObject.cs | 2 +- src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs | 2 +- .../CloudEvents/Cryptography/CloudEventExtensions.cs | 2 +- .../CloudEvents/Cryptography/SignedCloudEvent.cs | 2 +- .../CloudEvents/MessageExtensions.cs | 2 +- src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs | 2 +- src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs | 2 +- src/Savvyio.EventDriven/IntegrationEvent.cs | 2 +- src/Savvyio.EventDriven/IntegrationEventDispatcher.cs | 2 +- src/Savvyio.EventDriven/IntegrationEventExtensions.cs | 2 +- src/Savvyio.EventDriven/IntegrationEventHandler.cs | 2 +- src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs | 2 +- src/Savvyio.Extensions.Dapper/DapperDataSource.cs | 2 +- src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs | 2 +- src/Savvyio.Extensions.Dapper/DapperDataStore.cs | 2 +- src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs | 2 +- src/Savvyio.Extensions.Dapper/IDapperDataSource.cs | 2 +- .../DapperExtensionsDataStore.cs | 2 +- .../DapperExtensionsQueryOptions.cs | 2 +- .../DapperDataSource.cs | 2 +- .../DapperDataSourceOptions.cs | 2 +- .../IDapperDataSource.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../DapperExtensionsDataStore.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../EventSourcing/ITracedAggregateRepository.cs | 2 +- .../EventSourcing/ServiceCollectionExtensions.cs | 2 +- .../GlobalSuppressions.cs | 2 +- .../IAggregateRepository.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../EfCoreTracedAggregateRepository.cs | 2 +- .../GlobalSuppressions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../EfCoreAggregateDataSource.cs | 2 +- .../EfCoreAggregateRepository.cs | 2 +- .../GlobalSuppressions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../EfCoreDataSource.cs | 2 +- .../EfCoreDataSourceOptions.cs | 2 +- .../EfCoreDataStore.cs | 2 +- .../EfCoreDbContext.cs | 2 +- .../EfCoreRepository.cs | 2 +- .../GlobalSuppressions.cs | 2 +- .../IEfCoreDataSource.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../Commands/NatsCommandQueue.cs | 2 +- .../Commands/NatsCommandQueueOptions.cs | 2 +- .../EventDriven/NatsEventBusOptions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../AzureQueueOptions.cs | 2 +- .../Commands/AzureCommandQueue.cs | 2 +- .../EventDriven/AzureEventBus.cs | 2 +- .../EventDriven/AzureEventBusOptions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../Commands/RabbitMqCommandQueue.cs | 2 +- .../Commands/RabbitMqCommandQueueOptions.cs | 2 +- .../EventDriven/RabbitMqEventBusOptions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../Commands/AmazonCommandQueue.cs | 2 +- .../Commands/AmazonCommandQueueOptions.cs | 2 +- .../EventDriven/AmazonEventBus.cs | 2 +- .../EventDriven/AmazonEventBusOptions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs | 2 +- .../Data/IDeletableDataStore.cs | 2 +- .../Data/IPersistentDataStore.cs | 2 +- .../Data/IReadableDataStore.cs | 2 +- .../Data/ISearchableDataStore.cs | 2 +- .../Data/IWritableDataStore.cs | 2 +- .../Data/ServiceCollectionExtensions.cs | 2 +- .../Domain/IDeletableRepository.cs | 2 +- .../Domain/IPersistentRepository.cs | 2 +- .../Domain/IReadableRepository.cs | 2 +- .../Domain/IRepository.cs | 2 +- .../Domain/ISearchableRepository.cs | 2 +- .../Domain/IUnitOfWork.cs | 2 +- .../Domain/IWritableRepository.cs | 2 +- .../Domain/ServiceCollectionExtensions.cs | 2 +- .../GlobalSuppressions.cs | 2 +- src/Savvyio.Extensions.DependencyInjection/IDataSource.cs | 2 +- .../Messaging/IPointToPointChannel.cs | 2 +- .../Messaging/IPublishSubscribeChannel.cs | 2 +- .../Messaging/IPublisher.cs | 2 +- .../Messaging/IReceiver.cs | 2 +- src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs | 2 +- .../Messaging/ISubscriber.cs | 2 +- .../Messaging/ServiceCollectionExtensions.cs | 2 +- .../SavvyioDependencyInjectionOptions.cs | 2 +- .../ServiceCollectionExtensions.cs | 2 +- .../ServiceLocatorOptions.cs | 2 +- .../ServiceProviderExtensions.cs | 2 +- src/Savvyio.Extensions.Dispatchers/IMediator.cs | 2 +- src/Savvyio.Extensions.Dispatchers/Mediator.cs | 2 +- src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs | 2 +- .../EfCoreTracedAggregateEntity.cs | 2 +- .../EfCoreTracedAggregateEntityExtensions.cs | 2 +- .../EfCoreTracedAggregateEntityOptions.cs | 2 +- .../EfCoreTracedAggregateRepository.cs | 2 +- .../ModelBuilderExtensions.cs | 2 +- .../TracedDomainEventExtensions.cs | 2 +- .../DomainEventDispatcherExtensions.cs | 2 +- .../EfCoreAggregateDataSource.cs | 2 +- .../EfCoreAggregateRepository.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs | 2 +- src/Savvyio.Extensions.EFCore/EfCoreRepository.cs | 2 +- src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs | 2 +- src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs | 2 +- src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs | 2 +- src/Savvyio.Extensions.NATS/GlobalSuppressions.cs | 2 +- src/Savvyio.Extensions.NATS/NatsMessage.cs | 2 +- src/Savvyio.Extensions.NATS/NatsMessageOptions.cs | 2 +- .../Converters/MessageConverter.cs | 2 +- .../Converters/RequestConverter.cs | 2 +- .../Converters/SingleValueObjectConverter.cs | 2 +- src/Savvyio.Extensions.Newtonsoft.Json/GlobalSuppressions.cs | 2 +- .../JsonConverterExtensions.cs | 2 +- .../JsonSerializerExtensions.cs | 2 +- .../NewtonsoftJsonMarshaller.cs | 2 +- src/Savvyio.Extensions.QueueStorage/AzureQueue.cs | 2 +- src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs | 2 +- src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs | 2 +- src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs | 2 +- .../Commands/AzureCommandQueue.cs | 2 +- .../EventDriven/AzureEventBusOptions.cs | 2 +- src/Savvyio.Extensions.QueueStorage/GlobalSuppressions.cs | 2 +- .../Commands/RabbitMqCommandQueue.cs | 2 +- .../Commands/RabbitMqCommandQueueOptions.cs | 2 +- .../EventDriven/RabbitMqEventBusOptions.cs | 2 +- src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs | 2 +- src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs | 2 +- src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs | 2 +- src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs | 2 +- .../AmazonMessageOptions.cs | 2 +- .../AmazonMessageReceiveOptions.cs | 2 +- src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs | 2 +- .../AmazonResourceNameOptions.cs | 2 +- .../ClientConfigExtensions.cs | 2 +- .../Commands/AmazonCommandQueue.cs | 2 +- .../Commands/AmazonCommandQueueOptions.cs | 2 +- .../EventDriven/AmazonEventBus.cs | 2 +- .../EventDriven/AmazonEventBusOptions.cs | 2 +- .../EventDriven/StringExtensions.cs | 2 +- src/Savvyio.Extensions.SimpleQueueService/GlobalSuppressions.cs | 2 +- .../Converters/DateTimeConverter.cs | 2 +- .../Converters/DateTimeOffsetConverter.cs | 2 +- src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs | 2 +- .../Converters/MetadataDictionaryConverter.cs | 2 +- src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs | 2 +- .../Converters/SingleValueObjectConverter.cs | 2 +- src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs | 2 +- src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs | 2 +- .../JsonSerializerOptionsExtensions.cs | 2 +- src/Savvyio.Messaging/Acknowledgeable.cs | 2 +- src/Savvyio.Messaging/Cryptography/MessageExtensions.cs | 2 +- src/Savvyio.Messaging/Message.cs | 2 +- src/Savvyio.Messaging/MessageAsyncEnumerable.cs | 2 +- src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs | 2 +- src/Savvyio.Messaging/MessageAsyncEnumerator.cs | 2 +- src/Savvyio.Messaging/MessageExtensions.cs | 2 +- src/Savvyio.Messaging/MessageOptions.cs | 2 +- src/Savvyio.Queries/Query.cs | 2 +- src/Savvyio.Queries/QueryDispatcher.cs | 2 +- src/Savvyio.Queries/QueryHandler.cs | 2 +- src/Savvyio.Queries/SavvyioOptionsExtensions.cs | 2 +- test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs | 2 +- test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs | 2 +- test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs | 2 +- test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs | 2 +- test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs | 2 +- test/Savvyio.Assets.Tests/AccountCommandHandler.cs | 2 +- test/Savvyio.Assets.Tests/AccountEventHandler.cs | 2 +- test/Savvyio.Assets.Tests/AccountQueryHandler.cs | 2 +- test/Savvyio.Assets.Tests/Commands/CreateAccount.cs | 2 +- .../Commands/CreateAccountWithValueObjects.cs | 2 +- test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs | 2 +- test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs | 2 +- test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs | 2 +- test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs | 2 +- .../Commands/UpdatePlatformProviderAccountPolicy.cs | 2 +- test/Savvyio.Assets.Tests/DbMarker.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Account.cs | 2 +- test/Savvyio.Assets.Tests/Domain/AccountId.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Coordinates.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Credentials.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Description.cs | 2 +- test/Savvyio.Assets.Tests/Domain/EmailAddress.cs | 2 +- test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs | 2 +- .../Domain/Events/AccountEmailAddressChanged.cs | 2 +- .../Domain/Events/AccountFullNameChanged.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs | 2 +- .../Domain/Events/AccountInitiatedChained.cs | 2 +- .../Domain/Events/PlatformProviderAccountPolicyChanged.cs | 2 +- .../Domain/Events/PlatformProviderDescriptionChanged.cs | 2 +- .../Domain/Events/PlatformProviderInitiated.cs | 2 +- .../Domain/Events/PlatformProviderNameChanged.cs | 2 +- .../Events/PlatformProviderThirdLevelDomainNameChanged.cs | 2 +- .../Domain/Events/TracedAccountEmailAddressChanged.cs | 2 +- .../Domain/Events/TracedAccountFullNameChanged.cs | 2 +- .../Domain/Events/TracedAccountInitiated.cs | 2 +- .../Domain/Events/UserAccountFailedLogonAttemptCreated.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs | 2 +- .../Domain/Events/UserAccountPasswordInitiated.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs | 2 +- test/Savvyio.Assets.Tests/Domain/FullName.cs | 2 +- .../Domain/Handlers/AccountDomainEventHandler.cs | 2 +- .../Domain/Handlers/PlatformProviderDomainEventHandler.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Name.cs | 2 +- test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs | 2 +- .../Domain/PlatformProviderAccountPolicy.cs | 2 +- test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs | 2 +- test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs | 2 +- test/Savvyio.Assets.Tests/Domain/Timestamp.cs | 2 +- test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs | 2 +- test/Savvyio.Assets.Tests/Domain/UserAccount.cs | 2 +- .../Domain/UserAccountFailedLogonAttempt.cs | 2 +- test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs | 2 +- test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs | 2 +- test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs | 2 +- test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs | 2 +- .../Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs | 2 +- .../Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs | 2 +- test/Savvyio.Assets.Tests/PlatformProviderHandler.cs | 2 +- test/Savvyio.Assets.Tests/Queries/AccountProjection.cs | 2 +- test/Savvyio.Assets.Tests/Queries/GetAccount.cs | 2 +- test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs | 2 +- test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs | 2 +- test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs | 2 +- test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs | 2 +- test/Savvyio.Commands.Tests/CommandDispatcherTest.cs | 2 +- test/Savvyio.Commands.Tests/CommandHandlerTest.cs | 2 +- test/Savvyio.Commands.Tests/CommandTest.cs | 2 +- test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs | 2 +- test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs | 2 +- test/Savvyio.Core.Tests/Assets/AccountHandlers.cs | 2 +- test/Savvyio.Core.Tests/Assets/DummyRequest.cs | 2 +- test/Savvyio.Core.Tests/Assets/FakeCommand.cs | 2 +- test/Savvyio.Core.Tests/Assets/FakeQuery.cs | 2 +- test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs | 2 +- test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs | 2 +- .../Dispatchers/RequestReplyDispatcherTest.cs | 2 +- test/Savvyio.Core.Tests/HandlerFactoryTest.cs | 2 +- .../Messaging/Cryptography/SignedMessageOptionsTest.cs | 2 +- .../Messaging/Cryptography/SignedMessageTest.cs | 2 +- test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs | 2 +- test/Savvyio.Core.Tests/Messaging/MessageTest.cs | 2 +- test/Savvyio.Core.Tests/MetadataDictionaryTest.cs | 2 +- test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs | 2 +- test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs | 2 +- test/Savvyio.Core.Tests/SavvyioOptionsTest.cs | 2 +- .../TracedAggregateRootTest.cs | 2 +- test/Savvyio.Domain.Tests/AggregateRootTest.cs | 2 +- test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs | 2 +- test/Savvyio.Domain.Tests/Assets/Mixed.cs | 2 +- test/Savvyio.Domain.Tests/Assets/Money.cs | 2 +- .../Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs | 2 +- test/Savvyio.Domain.Tests/DomainEventTest.cs | 2 +- test/Savvyio.Domain.Tests/EntityTest.cs | 2 +- test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs | 2 +- test/Savvyio.Domain.Tests/SingleValueObjectTest.cs | 2 +- test/Savvyio.Domain.Tests/ValueObjectTest.cs | 2 +- test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs | 2 +- .../Messaging/CloudEvents/CloudEventTest.cs | 2 +- .../Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs | 2 +- .../Messaging/IntegrationEventExtensionsTest.cs | 2 +- test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs | 2 +- test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs | 2 +- .../DapperDataSourceOptionsTest.cs | 2 +- test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs | 2 +- test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs | 2 +- .../DapperExtensionsQueryOptionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../Assets/BusMarker.cs | 2 +- .../Assets/QueueMarker.cs | 2 +- .../Assets/BusMarker.cs | 2 +- .../Assets/QueueMarker.cs | 2 +- .../Assets/BusMarker.cs | 2 +- .../Assets/QueueMarker.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../Assets/FakeDataSource.cs | 2 +- .../Assets/FakeDataStore.cs | 2 +- .../Assets/FakeRepository.cs | 2 +- .../Assets/TestCommand.cs | 2 +- .../Assets/TestCommandHandler.cs | 2 +- .../Assets/TestDomainEvent.cs | 2 +- .../Assets/TestDomainEventHandler.cs | 2 +- .../Assets/TestIntegrationEvent.cs | 2 +- .../Assets/TestIntegrationEventHandler.cs | 2 +- .../Assets/TestQuery.cs | 2 +- .../Assets/TestQueryHandler.cs | 2 +- .../Data/ServiceCollectionExtensionsTest.cs | 2 +- .../SavvyioDependencyInjectionOptionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../EfCoreDataSourceOptionsTest.cs | 2 +- test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs | 2 +- test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs | 2 +- test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 2 +- .../Assets/CreateMemberCommand.cs | 2 +- .../Assets/MemberCreated.cs | 2 +- .../Commands/NatsCommandQueueOptionsTest.cs | 2 +- .../Commands/CommandTest.cs | 2 +- .../Commands/Messaging/CommandExtensionsTest.cs | 2 +- .../Commands/Messaging/InMemoryCommandQueueTest.cs | 2 +- .../Domain/DomainTest.cs | 2 +- .../CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs | 2 +- .../Messaging/CloudEvents/IntegrationEventExtensionsTest.cs | 2 +- .../Messaging/Cryptography/IntegrationEventExtensionsTest.cs | 2 +- .../EventDriven/Messaging/IntegrationEventExtensionsTest.cs | 2 +- .../MetadataDictionaryTest.cs | 2 +- .../Assets/CreateMemberCommand.cs | 2 +- .../Assets/MarkerStructs.cs | 2 +- .../Assets/MemberCreated.cs | 2 +- .../Commands/AzureCommandQueueJsonSerializerContextTest.cs | 2 +- .../AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs | 2 +- .../EventDriven/AzureEventBusJsonSerializerContextTest.cs | 2 +- .../AzureEventBusNewtonsoftJsonSerializerContextTest.cs | 2 +- .../AzureQueueOptionsTest.cs | 2 +- .../AzureQueueReceiveOptionsTest.cs | 2 +- .../AzureQueueSendOptionsTest.cs | 2 +- .../Assets/CreateMemberCommand.cs | 2 +- .../Assets/MemberCreated.cs | 2 +- .../Commands/RabbitMqCommandQueueOptionsTest.cs | 2 +- .../EventDriven/RabbitMqEventBusOptionsTest.cs | 2 +- .../RabbitMqMessageOptionsTest.cs | 2 +- .../Assets/CreateMemberCommand.cs | 2 +- .../Assets/MemberCreated.cs | 2 +- .../Commands/AmazonCommandQueueJsonSerializerContextTest.cs | 2 +- .../AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs | 2 +- .../EventDriven/AmazonEventBusJsonSerializerContextTest.cs | 2 +- .../AmazonEventBusNewtonsoftJsonSerializerContextTest.cs | 2 +- .../AmazonMessageOptionsTest.cs | 2 +- .../AmazonMessageReceiveOptionsTest.cs | 2 +- .../AmazonResourceNameOptionsTest.cs | 2 +- test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs | 2 +- .../Commands/Messaging/CommandExtensionsTest.cs | 2 +- .../Commands/Messaging/InMemoryCommandQueueTest.cs | 2 +- test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs | 2 +- .../CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs | 2 +- .../Messaging/CloudEvents/IntegrationEventExtensionsTest.cs | 2 +- .../Messaging/Cryptography/IntegrationEventExtensionsTest.cs | 2 +- .../EventDriven/Messaging/IntegrationEventExtensionsTest.cs | 2 +- .../MetadataDictionaryTest.cs | 2 +- test/Savvyio.FunctionalTests/Assets/AccountData.cs | 2 +- test/Savvyio.FunctionalTests/DistributedMediatorTest.cs | 2 +- .../DependencyInjection/ServiceCollectionExtensionsTest.cs | 2 +- test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs | 2 +- test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs | 2 +- test/Savvyio.Queries.Tests/QueryDispatcherTest.cs | 2 +- test/Savvyio.Queries.Tests/QueryHandlerTest.cs | 2 +- test/Savvyio.Queries.Tests/QueryTest.cs | 2 +- test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs | 2 +- 460 files changed, 460 insertions(+), 460 deletions(-) diff --git a/src/Savvyio.Commands.Messaging/CommandExtensions.cs b/src/Savvyio.Commands.Messaging/CommandExtensions.cs index bad6e1ed..2e517912 100644 --- a/src/Savvyio.Commands.Messaging/CommandExtensions.cs +++ b/src/Savvyio.Commands.Messaging/CommandExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Messaging; diff --git a/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs b/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs index ed8c6c75..c9728e46 100644 --- a/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs +++ b/src/Savvyio.Commands.Messaging/InMemoryCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Channels; using System.Threading.Tasks; diff --git a/src/Savvyio.Commands/Command.cs b/src/Savvyio.Commands/Command.cs index 2a489b71..80ace916 100644 --- a/src/Savvyio.Commands/Command.cs +++ b/src/Savvyio.Commands/Command.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Commands; diff --git a/src/Savvyio.Commands/CommandDispatcher.cs b/src/Savvyio.Commands/CommandDispatcher.cs index 8948e854..3116bfde 100644 --- a/src/Savvyio.Commands/CommandDispatcher.cs +++ b/src/Savvyio.Commands/CommandDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Cuemon.Threading; diff --git a/src/Savvyio.Commands/CommandHandler.cs b/src/Savvyio.Commands/CommandHandler.cs index a4eb5c99..3c0ad0e2 100644 --- a/src/Savvyio.Commands/CommandHandler.cs +++ b/src/Savvyio.Commands/CommandHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Commands; diff --git a/src/Savvyio.Commands/SavvyioOptionsExtensions.cs b/src/Savvyio.Commands/SavvyioOptionsExtensions.cs index 41e66552..0f118d64 100644 --- a/src/Savvyio.Commands/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Commands/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Commands; +namespace Savvyio.Commands; /// /// Extension methods for the class. diff --git a/src/Savvyio.Core/AsyncEventHandler.cs b/src/Savvyio.Core/AsyncEventHandler.cs index 404f512e..fb119c07 100644 --- a/src/Savvyio.Core/AsyncEventHandler.cs +++ b/src/Savvyio.Core/AsyncEventHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; namespace Savvyio; diff --git a/src/Savvyio.Core/Commands/ICommand.cs b/src/Savvyio.Core/Commands/ICommand.cs index 96694566..fd4a09db 100644 --- a/src/Savvyio.Core/Commands/ICommand.cs +++ b/src/Savvyio.Core/Commands/ICommand.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Commands; +namespace Savvyio.Commands; /// /// A marker interface that specifies an intention to do something (e.g. change the state). diff --git a/src/Savvyio.Core/Commands/ICommandDispatcher.cs b/src/Savvyio.Core/Commands/ICommandDispatcher.cs index f10128d4..9ab8aebb 100644 --- a/src/Savvyio.Core/Commands/ICommandDispatcher.cs +++ b/src/Savvyio.Core/Commands/ICommandDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; using Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/Commands/ICommandHandler.cs b/src/Savvyio.Core/Commands/ICommandHandler.cs index 05022d8d..ded321a9 100644 --- a/src/Savvyio.Core/Commands/ICommandHandler.cs +++ b/src/Savvyio.Core/Commands/ICommandHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Commands; diff --git a/src/Savvyio.Core/Data/IDataStore.cs b/src/Savvyio.Core/Data/IDataStore.cs index 87a49c4c..331fc59b 100644 --- a/src/Savvyio.Core/Data/IDataStore.cs +++ b/src/Savvyio.Core/Data/IDataStore.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Data; +namespace Savvyio.Data; /// /// A marker interface that specifies an abstraction of data persistence based on the Data Access Object pattern aka DAO. diff --git a/src/Savvyio.Core/Data/IDeletableDataStore.cs b/src/Savvyio.Core/Data/IDeletableDataStore.cs index c443867e..a2520fb1 100644 --- a/src/Savvyio.Core/Data/IDeletableDataStore.cs +++ b/src/Savvyio.Core/Data/IDeletableDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Data/IPersistentDataStore.cs b/src/Savvyio.Core/Data/IPersistentDataStore.cs index 5866ff80..7a06bbd8 100644 --- a/src/Savvyio.Core/Data/IPersistentDataStore.cs +++ b/src/Savvyio.Core/Data/IPersistentDataStore.cs @@ -1,4 +1,4 @@ -using Cuemon.Threading; +using Cuemon.Threading; namespace Savvyio.Data; diff --git a/src/Savvyio.Core/Data/IReadableDataStore.cs b/src/Savvyio.Core/Data/IReadableDataStore.cs index 967138df..096b17b9 100644 --- a/src/Savvyio.Core/Data/IReadableDataStore.cs +++ b/src/Savvyio.Core/Data/IReadableDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Data/ISearchableDataStore.cs b/src/Savvyio.Core/Data/ISearchableDataStore.cs index 909e86d2..0d833666 100644 --- a/src/Savvyio.Core/Data/ISearchableDataStore.cs +++ b/src/Savvyio.Core/Data/ISearchableDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Data/IWritableDataStore.cs b/src/Savvyio.Core/Data/IWritableDataStore.cs index b3cad147..8fd6b774 100644 --- a/src/Savvyio.Core/Data/IWritableDataStore.cs +++ b/src/Savvyio.Core/Data/IWritableDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs b/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs index 74a9832e..adf360ee 100644 --- a/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs +++ b/src/Savvyio.Core/Diagnostics/IAsyncHealthCheckProvider.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; namespace Savvyio.Diagnostics; diff --git a/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs b/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs index b901f01b..01d23960 100644 --- a/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs +++ b/src/Savvyio.Core/Diagnostics/IHealthCheckProvider.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Diagnostics; +namespace Savvyio.Diagnostics; /// /// Defines a contract for providing an underlying target that can be probed to assess health status. diff --git a/src/Savvyio.Core/Dispatchers/Dispatcher.cs b/src/Savvyio.Core/Dispatchers/Dispatcher.cs index d75aa5d8..9ce2f370 100644 --- a/src/Savvyio.Core/Dispatchers/Dispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/Dispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Cuemon; diff --git a/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs b/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs index 35339c78..abc3c095 100644 --- a/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/FireForgetDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Core/Dispatchers/IDispatcher.cs b/src/Savvyio.Core/Dispatchers/IDispatcher.cs index 31d7399e..a1827302 100644 --- a/src/Savvyio.Core/Dispatchers/IDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/IDispatcher.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Dispatchers; +namespace Savvyio.Dispatchers; /// /// A marker interface that specifies a dispatcher that encapsulates how a set of objects interact. diff --git a/src/Savvyio.Core/Dispatchers/IServiceLocator.cs b/src/Savvyio.Core/Dispatchers/IServiceLocator.cs index 0e559471..e41fd651 100644 --- a/src/Savvyio.Core/Dispatchers/IServiceLocator.cs +++ b/src/Savvyio.Core/Dispatchers/IServiceLocator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs b/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs index 655f829e..4db4c7a4 100644 --- a/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs +++ b/src/Savvyio.Core/Dispatchers/RequestReplyDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Core/Dispatchers/ServiceLocator.cs b/src/Savvyio.Core/Dispatchers/ServiceLocator.cs index 57fd183b..68db0937 100644 --- a/src/Savvyio.Core/Dispatchers/ServiceLocator.cs +++ b/src/Savvyio.Core/Dispatchers/ServiceLocator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/Domain/DomainException.cs b/src/Savvyio.Core/Domain/DomainException.cs index 0b003a5f..801a917a 100644 --- a/src/Savvyio.Core/Domain/DomainException.cs +++ b/src/Savvyio.Core/Domain/DomainException.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Domain; diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs index 9c5a28cd..2671ce68 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRepository.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain.EventSourcing; +namespace Savvyio.Domain.EventSourcing; /// /// Defines a generic way of abstracting traced read- and writable repositories (CRud) that is optimized for Domain Driven Design. diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs index 23cfc2b4..285577f9 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedAggregateRoot.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain.EventSourcing; +namespace Savvyio.Domain.EventSourcing; /// /// Defines an Event Sourcing capable contract of an Aggregate as specified in Domain Driven Design. diff --git a/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs b/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs index 251fa0a2..0a868b66 100644 --- a/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs +++ b/src/Savvyio.Core/Domain/EventSourcing/ITracedDomainEvent.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain.EventSourcing; +namespace Savvyio.Domain.EventSourcing; /// /// Specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. diff --git a/src/Savvyio.Core/Domain/IAggregateRepository.cs b/src/Savvyio.Core/Domain/IAggregateRepository.cs index 6bfd8a67..ee222af9 100644 --- a/src/Savvyio.Core/Domain/IAggregateRepository.cs +++ b/src/Savvyio.Core/Domain/IAggregateRepository.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// Defines a generic way of abstracting persistent repositories (CRUD) that is optimized for Domain Driven Design. diff --git a/src/Savvyio.Core/Domain/IAggregateRoot.cs b/src/Savvyio.Core/Domain/IAggregateRoot.cs index d242507b..1e94c9be 100644 --- a/src/Savvyio.Core/Domain/IAggregateRoot.cs +++ b/src/Savvyio.Core/Domain/IAggregateRoot.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.Core/Domain/IDeletableRepository.cs b/src/Savvyio.Core/Domain/IDeletableRepository.cs index b7e9c12e..097a73f8 100644 --- a/src/Savvyio.Core/Domain/IDeletableRepository.cs +++ b/src/Savvyio.Core/Domain/IDeletableRepository.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.Core/Domain/IDomainEvent.cs b/src/Savvyio.Core/Domain/IDomainEvent.cs index 87ab1074..79155ce5 100644 --- a/src/Savvyio.Core/Domain/IDomainEvent.cs +++ b/src/Savvyio.Core/Domain/IDomainEvent.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// A marker interface that specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be made aware of. diff --git a/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs b/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs index 37be0347..0f668c62 100644 --- a/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs +++ b/src/Savvyio.Core/Domain/IDomainEventDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; using Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/Domain/IDomainEventHandler.cs b/src/Savvyio.Core/Domain/IDomainEventHandler.cs index fd7c6a04..f5d546c9 100644 --- a/src/Savvyio.Core/Domain/IDomainEventHandler.cs +++ b/src/Savvyio.Core/Domain/IDomainEventHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Domain; diff --git a/src/Savvyio.Core/Domain/IEntity.cs b/src/Savvyio.Core/Domain/IEntity.cs index 60aa8d38..b945e38b 100644 --- a/src/Savvyio.Core/Domain/IEntity.cs +++ b/src/Savvyio.Core/Domain/IEntity.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// Defines an Entity as specified in Domain Driven Design. diff --git a/src/Savvyio.Core/Domain/IPersistentRepository.cs b/src/Savvyio.Core/Domain/IPersistentRepository.cs index e093e58f..66865c61 100644 --- a/src/Savvyio.Core/Domain/IPersistentRepository.cs +++ b/src/Savvyio.Core/Domain/IPersistentRepository.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// Defines a generic way of abstracting persistent repositories (CRUD). diff --git a/src/Savvyio.Core/Domain/IReadableRepository.cs b/src/Savvyio.Core/Domain/IReadableRepository.cs index 44687000..b1ab3f97 100644 --- a/src/Savvyio.Core/Domain/IReadableRepository.cs +++ b/src/Savvyio.Core/Domain/IReadableRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Domain/IRepository.cs b/src/Savvyio.Core/Domain/IRepository.cs index bae651da..df3a3279 100644 --- a/src/Savvyio.Core/Domain/IRepository.cs +++ b/src/Savvyio.Core/Domain/IRepository.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// A marker interface that specifies an abstraction of data persistence based on the Repository pattern. diff --git a/src/Savvyio.Core/Domain/ISearchableRepository.cs b/src/Savvyio.Core/Domain/ISearchableRepository.cs index 4c209dca..3bfacce3 100644 --- a/src/Savvyio.Core/Domain/ISearchableRepository.cs +++ b/src/Savvyio.Core/Domain/ISearchableRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Domain/IUnitOfWork.cs b/src/Savvyio.Core/Domain/IUnitOfWork.cs index ba16b184..9188f798 100644 --- a/src/Savvyio.Core/Domain/IUnitOfWork.cs +++ b/src/Savvyio.Core/Domain/IUnitOfWork.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Domain/IWritableRepository.cs b/src/Savvyio.Core/Domain/IWritableRepository.cs index 07628138..0c4bea43 100644 --- a/src/Savvyio.Core/Domain/IWritableRepository.cs +++ b/src/Savvyio.Core/Domain/IWritableRepository.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs b/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs index 7e8cb9a4..97573a01 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEvent.cs @@ -1,4 +1,4 @@ -namespace Savvyio.EventDriven; +namespace Savvyio.EventDriven; /// /// A marker interface that specifies something that happened when an object was successfully persisted and you want other subsystems (out-process/inter-application) to be made aware of. diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs b/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs index 38731767..7aafab68 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEventDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; using Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs b/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs index 4d52df07..c2bc7001 100644 --- a/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs +++ b/src/Savvyio.Core/EventDriven/IIntegrationEventHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.EventDriven; diff --git a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs index dc09a089..bfc10bc4 100644 --- a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs +++ b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/Cryptography/ISignedCloudEvent.cs @@ -1,4 +1,4 @@ -using Savvyio.Messaging.Cryptography; +using Savvyio.Messaging.Cryptography; namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; diff --git a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs index a44d8b27..5a60c663 100644 --- a/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs +++ b/src/Savvyio.Core/EventDriven/Messaging/CloudEvents/ICloudEvent.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Savvyio.Messaging; namespace Savvyio.EventDriven.Messaging.CloudEvents; diff --git a/src/Savvyio.Core/HandlerDiscoveryModel.cs b/src/Savvyio.Core/HandlerDiscoveryModel.cs index 95a5fff0..bab5f611 100644 --- a/src/Savvyio.Core/HandlerDiscoveryModel.cs +++ b/src/Savvyio.Core/HandlerDiscoveryModel.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Savvyio.Core/HandlerFactory.cs b/src/Savvyio.Core/HandlerFactory.cs index 26900d74..ac73c8eb 100644 --- a/src/Savvyio.Core/HandlerFactory.cs +++ b/src/Savvyio.Core/HandlerFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Handlers; diff --git a/src/Savvyio.Core/Handlers/FireForgetManager.cs b/src/Savvyio.Core/Handlers/FireForgetManager.cs index 4c76c42f..e99b05ec 100644 --- a/src/Savvyio.Core/Handlers/FireForgetManager.cs +++ b/src/Savvyio.Core/Handlers/FireForgetManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs b/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs index 1ed26ae2..e6e2f588 100644 --- a/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs +++ b/src/Savvyio.Core/Handlers/FireForgetRegistryExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; namespace Savvyio.Handlers; diff --git a/src/Savvyio.Core/Handlers/IFireForgetActivator.cs b/src/Savvyio.Core/Handlers/IFireForgetActivator.cs index f65a0e8f..6e9a5bfe 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetActivator.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetActivator.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Core/Handlers/IFireForgetHandler.cs b/src/Savvyio.Core/Handlers/IFireForgetHandler.cs index a355a5af..d7c87b87 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetHandler.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetHandler.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Handlers; +namespace Savvyio.Handlers; /// /// Defines a generic handler that uses Fire-and-Forget/In-Only MEP. diff --git a/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs b/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs index 14d0d8c2..af67e31d 100644 --- a/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs +++ b/src/Savvyio.Core/Handlers/IFireForgetRegistry.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs b/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs index 46f58dee..68648f89 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyActivator.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs b/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs index cda32b26..9d058ceb 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyHandler.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Handlers; +namespace Savvyio.Handlers; /// /// Defines a generic Request-Reply/In-Out MEP handler. diff --git a/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs b/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs index 8e29b2d6..462d17ab 100644 --- a/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs +++ b/src/Savvyio.Core/Handlers/IRequestReplyRegistry.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs b/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs index a0de27ea..1b571952 100644 --- a/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs +++ b/src/Savvyio.Core/Handlers/OrphanedHandlerException.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Handlers; diff --git a/src/Savvyio.Core/Handlers/RequestReplyManager.cs b/src/Savvyio.Core/Handlers/RequestReplyManager.cs index 5930da56..775e2e81 100644 --- a/src/Savvyio.Core/Handlers/RequestReplyManager.cs +++ b/src/Savvyio.Core/Handlers/RequestReplyManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs b/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs index 63c347df..31c5c1a3 100644 --- a/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs +++ b/src/Savvyio.Core/Handlers/RequestReplyRegistryExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; namespace Savvyio.Handlers; diff --git a/src/Savvyio.Core/IDataSource.cs b/src/Savvyio.Core/IDataSource.cs index 5efad1c2..00f5f6cd 100644 --- a/src/Savvyio.Core/IDataSource.cs +++ b/src/Savvyio.Core/IDataSource.cs @@ -1,4 +1,4 @@ -using Savvyio.Data; +using Savvyio.Data; using Savvyio.Domain; namespace Savvyio; diff --git a/src/Savvyio.Core/IHandler.cs b/src/Savvyio.Core/IHandler.cs index 824933ea..4818d938 100644 --- a/src/Savvyio.Core/IHandler.cs +++ b/src/Savvyio.Core/IHandler.cs @@ -1,4 +1,4 @@ -namespace Savvyio; +namespace Savvyio; /// /// A marker interface that specifies a handler. diff --git a/src/Savvyio.Core/IHandlerServicesDescriptor.cs b/src/Savvyio.Core/IHandlerServicesDescriptor.cs index 6d08992e..220b09fc 100644 --- a/src/Savvyio.Core/IHandlerServicesDescriptor.cs +++ b/src/Savvyio.Core/IHandlerServicesDescriptor.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio; diff --git a/src/Savvyio.Core/IIdentity.cs b/src/Savvyio.Core/IIdentity.cs index a1dfed8b..b4edf23a 100644 --- a/src/Savvyio.Core/IIdentity.cs +++ b/src/Savvyio.Core/IIdentity.cs @@ -1,4 +1,4 @@ -namespace Savvyio; +namespace Savvyio; /// /// Defines a generic identity typically associated with a storage such as a database. diff --git a/src/Savvyio.Core/IMarshaller.cs b/src/Savvyio.Core/IMarshaller.cs index 43e8dac1..e23255e2 100644 --- a/src/Savvyio.Core/IMarshaller.cs +++ b/src/Savvyio.Core/IMarshaller.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace Savvyio; diff --git a/src/Savvyio.Core/IMetadata.cs b/src/Savvyio.Core/IMetadata.cs index d840eee0..4c872ecb 100644 --- a/src/Savvyio.Core/IMetadata.cs +++ b/src/Savvyio.Core/IMetadata.cs @@ -1,4 +1,4 @@ -namespace Savvyio; +namespace Savvyio; /// /// Defines a generic way to associate metadata with any type of object. diff --git a/src/Savvyio.Core/IMetadataDictionary.cs b/src/Savvyio.Core/IMetadataDictionary.cs index 2c5f5353..ed133784 100644 --- a/src/Savvyio.Core/IMetadataDictionary.cs +++ b/src/Savvyio.Core/IMetadataDictionary.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio; diff --git a/src/Savvyio.Core/IRequest.cs b/src/Savvyio.Core/IRequest.cs index 43ecd512..e26dd19d 100644 --- a/src/Savvyio.Core/IRequest.cs +++ b/src/Savvyio.Core/IRequest.cs @@ -1,4 +1,4 @@ -namespace Savvyio; +namespace Savvyio; /// /// A marker interface that specifies a request/model/event. diff --git a/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs b/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs index 549e532b..bf3372ab 100644 --- a/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs +++ b/src/Savvyio.Core/Messaging/AcknowledgedEventArgs.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs index 8b1e3a6d..c13f9ede 100644 --- a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs +++ b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Core/Messaging/IMessage.cs b/src/Savvyio.Core/Messaging/IMessage.cs index 5337a1bf..77368a2b 100644 --- a/src/Savvyio.Core/Messaging/IMessage.cs +++ b/src/Savvyio.Core/Messaging/IMessage.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Core/Messaging/IPointToPointChannel.cs b/src/Savvyio.Core/Messaging/IPointToPointChannel.cs index 51d447b6..013f3cf5 100644 --- a/src/Savvyio.Core/Messaging/IPointToPointChannel.cs +++ b/src/Savvyio.Core/Messaging/IPointToPointChannel.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Messaging; +namespace Savvyio.Messaging; /// /// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to do something (e.g., change the state). diff --git a/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs b/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs index 5bd136e1..cce2bfb4 100644 --- a/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs +++ b/src/Savvyio.Core/Messaging/IPublishSubscribeChannel.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Messaging; +namespace Savvyio.Messaging; /// /// Specifies an interface for a bus that is used for interacting with other subsystems (out-process/inter-application) to be notified (e.g., made aware of something that has happened). diff --git a/src/Savvyio.Core/Messaging/IPublisher.cs b/src/Savvyio.Core/Messaging/IPublisher.cs index e1a64e1b..4e2fab00 100644 --- a/src/Savvyio.Core/Messaging/IPublisher.cs +++ b/src/Savvyio.Core/Messaging/IPublisher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Messaging/IReceiver.cs b/src/Savvyio.Core/Messaging/IReceiver.cs index b692aaea..bbeae8d6 100644 --- a/src/Savvyio.Core/Messaging/IReceiver.cs +++ b/src/Savvyio.Core/Messaging/IReceiver.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Cuemon.Threading; diff --git a/src/Savvyio.Core/Messaging/ISender.cs b/src/Savvyio.Core/Messaging/ISender.cs index ee0b6e8f..613033bc 100644 --- a/src/Savvyio.Core/Messaging/ISender.cs +++ b/src/Savvyio.Core/Messaging/ISender.cs @@ -1,4 +1,4 @@ -using Cuemon.Threading; +using Cuemon.Threading; using System.Threading.Tasks; using System; using System.Collections.Generic; diff --git a/src/Savvyio.Core/Messaging/ISubscriber.cs b/src/Savvyio.Core/Messaging/ISubscriber.cs index b25a8823..e8a34fe8 100644 --- a/src/Savvyio.Core/Messaging/ISubscriber.cs +++ b/src/Savvyio.Core/Messaging/ISubscriber.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs b/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs index cbd91dcd..cba5e958 100644 --- a/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs +++ b/src/Savvyio.Core/Messaging/SubscribeAsyncOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using Cuemon.Threading; diff --git a/src/Savvyio.Core/MetadataDictionary.cs b/src/Savvyio.Core/MetadataDictionary.cs index 74bd13ef..6df5c9cf 100644 --- a/src/Savvyio.Core/MetadataDictionary.cs +++ b/src/Savvyio.Core/MetadataDictionary.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/Savvyio.Core/MetadataExtensions.cs b/src/Savvyio.Core/MetadataExtensions.cs index 29f5a2e3..862a52af 100644 --- a/src/Savvyio.Core/MetadataExtensions.cs +++ b/src/Savvyio.Core/MetadataExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.Reflection; diff --git a/src/Savvyio.Core/MetadataFactory.cs b/src/Savvyio.Core/MetadataFactory.cs index e004b1ec..3476ed5a 100644 --- a/src/Savvyio.Core/MetadataFactory.cs +++ b/src/Savvyio.Core/MetadataFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio; diff --git a/src/Savvyio.Core/Queries/IQuery.cs b/src/Savvyio.Core/Queries/IQuery.cs index e9a0d71a..48a156c1 100644 --- a/src/Savvyio.Core/Queries/IQuery.cs +++ b/src/Savvyio.Core/Queries/IQuery.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Queries; +namespace Savvyio.Queries; /// /// A marker interface that specifies something that returns data. diff --git a/src/Savvyio.Core/Queries/IQueryDispatcher.cs b/src/Savvyio.Core/Queries/IQueryDispatcher.cs index 6eefaa0f..6fc28a3e 100644 --- a/src/Savvyio.Core/Queries/IQueryDispatcher.cs +++ b/src/Savvyio.Core/Queries/IQueryDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; using Savvyio.Dispatchers; diff --git a/src/Savvyio.Core/Queries/IQueryHandler.cs b/src/Savvyio.Core/Queries/IQueryHandler.cs index 797e0531..963e438e 100644 --- a/src/Savvyio.Core/Queries/IQueryHandler.cs +++ b/src/Savvyio.Core/Queries/IQueryHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Queries; diff --git a/src/Savvyio.Core/Request.cs b/src/Savvyio.Core/Request.cs index 96ccf041..8d8e5294 100644 --- a/src/Savvyio.Core/Request.cs +++ b/src/Savvyio.Core/Request.cs @@ -1,4 +1,4 @@ -namespace Savvyio; +namespace Savvyio; /// /// Represents the base class from which all implementations of should derive. diff --git a/src/Savvyio.Core/SavvyioOptions.cs b/src/Savvyio.Core/SavvyioOptions.cs index 1505677d..cfee6608 100644 --- a/src/Savvyio.Core/SavvyioOptions.cs +++ b/src/Savvyio.Core/SavvyioOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Cuemon.Configuration; using Cuemon.Extensions; diff --git a/src/Savvyio.Core/SavvyioOptionsExtensions.cs b/src/Savvyio.Core/SavvyioOptionsExtensions.cs index 3ce3b2c8..efd9dbfc 100644 --- a/src/Savvyio.Core/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Core/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/Savvyio.Core/TaskExtensions.cs b/src/Savvyio.Core/TaskExtensions.cs index 425448ed..c6b1199a 100644 --- a/src/Savvyio.Core/TaskExtensions.cs +++ b/src/Savvyio.Core/TaskExtensions.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs b/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs index fd273c10..2a4c21d7 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedAggregateRoot.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Savvyio.Handlers; namespace Savvyio.Domain.EventSourcing; diff --git a/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs b/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs index 438bbbe2..365bbfbb 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedDomainEvent.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain.EventSourcing; +namespace Savvyio.Domain.EventSourcing; /// /// Provides a default implementation of something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of. diff --git a/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs b/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs index 73392fe3..1d05507b 100644 --- a/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs +++ b/src/Savvyio.Domain.EventSourcing/TracedDomainEventExtensions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions; +using Cuemon.Extensions; namespace Savvyio.Domain.EventSourcing; diff --git a/src/Savvyio.Domain/Aggregate.cs b/src/Savvyio.Domain/Aggregate.cs index 8d7192f1..15471dd0 100644 --- a/src/Savvyio.Domain/Aggregate.cs +++ b/src/Savvyio.Domain/Aggregate.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.Domain/AggregateRoot.cs b/src/Savvyio.Domain/AggregateRoot.cs index a0f4c6b9..bc368d3c 100644 --- a/src/Savvyio.Domain/AggregateRoot.cs +++ b/src/Savvyio.Domain/AggregateRoot.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// Provides a way to cover the pattern of an Aggregate Root as specified in Domain Driven Design. This is an abstract class. diff --git a/src/Savvyio.Domain/DomainEvent.cs b/src/Savvyio.Domain/DomainEvent.cs index a58fe12c..5de48e8d 100644 --- a/src/Savvyio.Domain/DomainEvent.cs +++ b/src/Savvyio.Domain/DomainEvent.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Domain; diff --git a/src/Savvyio.Domain/DomainEventDispatcher.cs b/src/Savvyio.Domain/DomainEventDispatcher.cs index 382e02ee..162c8eda 100644 --- a/src/Savvyio.Domain/DomainEventDispatcher.cs +++ b/src/Savvyio.Domain/DomainEventDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Cuemon.Threading; diff --git a/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs b/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs index db4bc657..2cfcc705 100644 --- a/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs +++ b/src/Savvyio.Domain/DomainEventDispatcherExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Domain/DomainEventExtensions.cs b/src/Savvyio.Domain/DomainEventExtensions.cs index 955ad22b..cc06acf7 100644 --- a/src/Savvyio.Domain/DomainEventExtensions.cs +++ b/src/Savvyio.Domain/DomainEventExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Savvyio.Domain.EventSourcing; diff --git a/src/Savvyio.Domain/DomainEventHandler.cs b/src/Savvyio.Domain/DomainEventHandler.cs index 9c7d2fa3..de0f4f1f 100644 --- a/src/Savvyio.Domain/DomainEventHandler.cs +++ b/src/Savvyio.Domain/DomainEventHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Domain; diff --git a/src/Savvyio.Domain/Entity.cs b/src/Savvyio.Domain/Entity.cs index a4ceb16d..ce56f6e6 100644 --- a/src/Savvyio.Domain/Entity.cs +++ b/src/Savvyio.Domain/Entity.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.Domain/SavvyioOptionsExtensions.cs b/src/Savvyio.Domain/SavvyioOptionsExtensions.cs index c88adf60..b675d41c 100644 --- a/src/Savvyio.Domain/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Domain/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Domain; +namespace Savvyio.Domain; /// /// Extension methods for the class. diff --git a/src/Savvyio.Domain/SingleValueObject.cs b/src/Savvyio.Domain/SingleValueObject.cs index 12266e5f..aef6e6e6 100644 --- a/src/Savvyio.Domain/SingleValueObject.cs +++ b/src/Savvyio.Domain/SingleValueObject.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Savvyio.Domain; diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs index fb548b3a..7fdf6361 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/CloudEvent.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs index f3f1ceee..731066f5 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/CloudEventExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Security.Cryptography; using Savvyio.Messaging.Cryptography; diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs index 2762803a..cfb39202 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/Cryptography/SignedCloudEvent.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; diff --git a/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs b/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs index 6b64aee0..359661f9 100644 --- a/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/CloudEvents/MessageExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Messaging; diff --git a/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs b/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs index b6e6cb83..c8a8c64e 100644 --- a/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs +++ b/src/Savvyio.EventDriven.Messaging/InMemoryEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; diff --git a/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs b/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs index d9abd7e2..5510b2d9 100644 --- a/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs +++ b/src/Savvyio.EventDriven.Messaging/IntegrationEventExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Messaging; diff --git a/src/Savvyio.EventDriven/IntegrationEvent.cs b/src/Savvyio.EventDriven/IntegrationEvent.cs index 8868912b..59ab68b0 100644 --- a/src/Savvyio.EventDriven/IntegrationEvent.cs +++ b/src/Savvyio.EventDriven/IntegrationEvent.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.EventDriven; diff --git a/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs b/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs index 22929bb2..965d98cc 100644 --- a/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs +++ b/src/Savvyio.EventDriven/IntegrationEventDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Cuemon.Threading; diff --git a/src/Savvyio.EventDriven/IntegrationEventExtensions.cs b/src/Savvyio.EventDriven/IntegrationEventExtensions.cs index eaf9d0de..aaa082c4 100644 --- a/src/Savvyio.EventDriven/IntegrationEventExtensions.cs +++ b/src/Savvyio.EventDriven/IntegrationEventExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; namespace Savvyio.EventDriven; diff --git a/src/Savvyio.EventDriven/IntegrationEventHandler.cs b/src/Savvyio.EventDriven/IntegrationEventHandler.cs index 55501a9c..72e53156 100644 --- a/src/Savvyio.EventDriven/IntegrationEventHandler.cs +++ b/src/Savvyio.EventDriven/IntegrationEventHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.EventDriven; diff --git a/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs b/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs index ebc7f557..b4d8220f 100644 --- a/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.EventDriven/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.EventDriven; +namespace Savvyio.EventDriven; /// /// Extension methods for the class. diff --git a/src/Savvyio.Extensions.Dapper/DapperDataSource.cs b/src/Savvyio.Extensions.Dapper/DapperDataSource.cs index 88a72422..a2dd7bf0 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataSource.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using Cuemon; diff --git a/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs b/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs index 5eb97a2e..6d3e9b10 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataSourceOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using Cuemon; using Cuemon.Configuration; diff --git a/src/Savvyio.Extensions.Dapper/DapperDataStore.cs b/src/Savvyio.Extensions.Dapper/DapperDataStore.cs index 28f787f8..6dbd769e 100644 --- a/src/Savvyio.Extensions.Dapper/DapperDataStore.cs +++ b/src/Savvyio.Extensions.Dapper/DapperDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs b/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs index 79a62683..889adc20 100644 --- a/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs +++ b/src/Savvyio.Extensions.Dapper/DapperQueryOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using Cuemon.Threading; using Dapper; diff --git a/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs b/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs index a3283be5..baa0045b 100644 --- a/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs +++ b/src/Savvyio.Extensions.Dapper/IDapperDataSource.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; namespace Savvyio.Extensions.Dapper; diff --git a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs index 37f164d1..54365b32 100644 --- a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs +++ b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Extensions; diff --git a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs index ce41fe30..e4818e58 100644 --- a/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs +++ b/src/Savvyio.Extensions.DapperExtensions/DapperExtensionsQueryOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq.Expressions; using Cuemon.Threading; using DapperExtensions; diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs index b04f4abe..64d8acc0 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Extensions.Dapper; namespace Savvyio.Extensions.DependencyInjection.Dapper; diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs index c3c978be..3be666a0 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/DapperDataSourceOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.Dapper; namespace Savvyio.Extensions.DependencyInjection.Dapper; diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs index 8720d7d9..e22335ca 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/IDapperDataSource.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.Dapper; +using Savvyio.Extensions.Dapper; namespace Savvyio.Extensions.DependencyInjection.Dapper; diff --git a/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs index 15a1528e..30ee3575 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Dapper/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs index 53234550..731dab29 100644 --- a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/DapperExtensionsDataStore.cs @@ -1,4 +1,4 @@ -using Savvyio.Data; +using Savvyio.Data; using Savvyio.Extensions.DapperExtensions; using Savvyio.Extensions.DependencyInjection.Dapper; using Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs index 185a4b28..03d60f9f 100644 --- a/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.DapperExtensions/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Microsoft.Extensions.DependencyInjection; using Savvyio.Extensions.DapperExtensions; diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs index 8f672698..ffcc37e1 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ITracedAggregateRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain.EventSourcing; +using Savvyio.Domain.EventSourcing; namespace Savvyio.Extensions.DependencyInjection.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs index 8b7b5dba..d01bf000 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/EventSourcing/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/GlobalSuppressions.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/GlobalSuppressions.cs index c3f38bce..0e40e233 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs index b6af4440..a805f2c9 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/IAggregateRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs index 27acd258..23120110 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs index e663a944..5e638a8c 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain.EventSourcing; +using Savvyio.Domain.EventSourcing; using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.DependencyInjection.Domain.EventSourcing; using Savvyio.Extensions.EFCore.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/GlobalSuppressions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/GlobalSuppressions.cs index 5fab405b..afb154ee 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs index cf1bd1ac..0404fb15 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs index deea5c38..40ce16aa 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateDataSource.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; using Savvyio.Extensions.EFCore; using Savvyio.Extensions.EFCore.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs index df255d64..81341c52 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/EfCoreAggregateRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/GlobalSuppressions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/GlobalSuppressions.cs index 75d8b0da..73f5da6b 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs index 09f7b7fa..b88f89c7 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs index 4478fb80..591377ed 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSource.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.EFCore; +using Savvyio.Extensions.EFCore; namespace Savvyio.Extensions.DependencyInjection.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs index f8e978ef..60495b45 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataSourceOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.EFCore; namespace Savvyio.Extensions.DependencyInjection.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs index 5f172961..be187f52 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDataStore.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.DependencyInjection.Data; +using Savvyio.Extensions.DependencyInjection.Data; using Savvyio.Extensions.EFCore; namespace Savvyio.Extensions.DependencyInjection.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs index 1717f976..75a06349 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreDbContext.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using Savvyio.Extensions.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs index 5edb7a0c..2db17f71 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/EfCoreRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.DependencyInjection.Domain; +using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; namespace Savvyio.Extensions.DependencyInjection.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/GlobalSuppressions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/GlobalSuppressions.cs index 9561458e..4b516b15 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs index 1a297904..ad8d0adb 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/IEfCoreDataSource.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.DependencyInjection.Domain; +using Savvyio.Extensions.DependencyInjection.Domain; using Savvyio.Extensions.EFCore; namespace Savvyio.Extensions.DependencyInjection.EFCore; diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs index 91da561c..d6097672 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs index 30a4d831..950bf441 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.NATS; diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs index 6ac133a0..63dfbe5e 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Commands/NatsCommandQueueOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.NATS.Commands; namespace Savvyio.Extensions.DependencyInjection.NATS.Commands; diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs index 542ceb37..572c90c7 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBusOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.NATS.EventDriven; namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven; diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs index 4c7cfa6e..f9c59709 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Savvyio.Extensions.DependencyInjection.Messaging; using System; diff --git a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs index 575c3b54..dcd4a101 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Newtonsoft.Json.Formatters; using Cuemon; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs index 49e8ad1d..2dcbcce4 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/AzureQueueOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.QueueStorage; namespace Savvyio.Extensions.DependencyInjection.QueueStorage; diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs index 98d04370..6a80a320 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Commands/AzureCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.QueueStorage.Commands; diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs index 733bfbf1..48682df0 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.EventDriven; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.QueueStorage.EventDriven; diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs index b4ebf0cc..4461b54e 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/EventDriven/AzureEventBusOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.QueueStorage.EventDriven; namespace Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven; diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs index bf86288d..121a70f8 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs index f3f4ae8b..a82f9fcf 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.RabbitMQ; diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs index 399074b5..ff8c13a8 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.RabbitMQ.Commands; namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands; diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs index 5e806663..3d683ff3 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.RabbitMQ.EventDriven; namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven; diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs index 7a9d018e..ce8367ca 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.DependencyInjection.RabbitMQ.Commands; diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs index 604a0146..1c6e4235 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.SimpleQueueService; diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs index 157e0011..d71d84a5 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.SimpleQueueService.Commands; namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Commands; diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs index 7f052fba..14d38ee0 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.EventDriven; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.SimpleQueueService; diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs index 67290608..e53382d9 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Extensions.SimpleQueueService.EventDriven; namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.EventDriven; diff --git a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs index 30462d0f..b203c2e8 100644 --- a/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.SimpleQueueService/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs index 05312bdb..ad4bf8c6 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection.Text.Json/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.Text.Json.Formatters; using Microsoft.Extensions.DependencyInjection; using System; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs index 97a874fb..8d09068a 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IDataStore.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs index 6e2676b8..33c3888c 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IDeletableDataStore.cs @@ -1,4 +1,4 @@ -using Savvyio.Data; +using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs index bbfd0b18..f7ada902 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IPersistentDataStore.cs @@ -1,4 +1,4 @@ -using Cuemon.Threading; +using Cuemon.Threading; using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs index 88e79af6..7fd812da 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IReadableDataStore.cs @@ -1,4 +1,4 @@ -using Savvyio.Data; +using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs index 3ecadbe1..8d4d85d4 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/ISearchableDataStore.cs @@ -1,4 +1,4 @@ -using Cuemon.Threading; +using Cuemon.Threading; using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs b/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs index a61a07e7..2c367b01 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/IWritableDataStore.cs @@ -1,4 +1,4 @@ -using Savvyio.Data; +using Savvyio.Data; namespace Savvyio.Extensions.DependencyInjection.Data; diff --git a/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs index 4867555a..ced2f918 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Data/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs index 972e3faa..d694b7a3 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IDeletableRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs index 1973c8d2..fb8eb3d3 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IPersistentRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs index 310ab7d9..5fca806a 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IReadableRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs index af426d72..cc971fa5 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IRepository.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs index c6a5257b..108cd0d6 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/ISearchableRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs index 85ea8626..d7559851 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IUnitOfWork.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs index a0373f2e..ab846dcb 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/IWritableRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Domain; diff --git a/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs index 7eaf9011..ed6ae404 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Domain/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection/GlobalSuppressions.cs b/src/Savvyio.Extensions.DependencyInjection/GlobalSuppressions.cs index 81a3e44d..b3b50dbc 100644 --- a/src/Savvyio.Extensions.DependencyInjection/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs b/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs index f2cabfde..6c8acd8b 100644 --- a/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs +++ b/src/Savvyio.Extensions.DependencyInjection/IDataSource.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; namespace Savvyio.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs index 781b74fa..76495032 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPointToPointChannel.cs @@ -1,4 +1,4 @@ -using Savvyio.Messaging; +using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs index d5e7a2fa..5278f72e 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublishSubscribeChannel.cs @@ -1,4 +1,4 @@ -using Savvyio.Messaging; +using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs index d9e11d96..d09ba272 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IPublisher.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs index 37cddc2b..7b6dc957 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/IReceiver.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs index 8524d8a3..fdde4b36 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISender.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs index 417a5175..6db9d289 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ISubscriber.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.DependencyInjection; +using Cuemon.Extensions.DependencyInjection; using Savvyio.Messaging; namespace Savvyio.Extensions.DependencyInjection.Messaging; diff --git a/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs index 220293d5..e390c745 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/Messaging/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.DependencyInjection; diff --git a/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs b/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs index 214c219a..699a5ea3 100644 --- a/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/SavvyioDependencyInjectionOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs index 9a4ee94f..912e1fb1 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs index 09eb2ac2..65fc0d45 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceLocatorOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Savvyio.Dispatchers; diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs index 2e0bf161..ae771882 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceProviderExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/src/Savvyio.Extensions.Dispatchers/IMediator.cs b/src/Savvyio.Extensions.Dispatchers/IMediator.cs index 217b6c2c..ddf6bdb5 100644 --- a/src/Savvyio.Extensions.Dispatchers/IMediator.cs +++ b/src/Savvyio.Extensions.Dispatchers/IMediator.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; using Savvyio.Domain; using Savvyio.EventDriven; using Savvyio.Queries; diff --git a/src/Savvyio.Extensions.Dispatchers/Mediator.cs b/src/Savvyio.Extensions.Dispatchers/Mediator.cs index 80f6ec19..98936419 100644 --- a/src/Savvyio.Extensions.Dispatchers/Mediator.cs +++ b/src/Savvyio.Extensions.Dispatchers/Mediator.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon.Threading; using Savvyio.Commands; diff --git a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs index f4ee35de..aaa83f2b 100644 --- a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; using Savvyio.Dispatchers; using Savvyio.Domain; using Savvyio.EventDriven; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs index 087b7cfe..2649e432 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntity.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Cuemon.Extensions.Collections.Generic; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs index 2f9ebfee..2f8f8439 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Savvyio.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs index 361526b8..e4feadef 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateEntityOptions.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Cuemon.Configuration; namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs index 9025388a..7a125c2f 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/EfCoreTracedAggregateRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs index 81f5204f..57661c78 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/ModelBuilderExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Microsoft.EntityFrameworkCore; using Savvyio.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs index 7adc9d03..18e1dc69 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/TracedDomainEventExtensions.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.IO; +using Cuemon.Extensions.IO; using Savvyio.Domain.EventSourcing; namespace Savvyio.Extensions.EFCore.Domain.EventSourcing; diff --git a/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs b/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs index fbde6e15..0680033a 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/DomainEventDispatcherExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs index 316186b9..468d8271 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs index 4780b453..1d5ed494 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs +++ b/src/Savvyio.Extensions.EFCore.Domain/EfCoreAggregateRepository.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.EFCore.Domain; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs index 7689b3c1..f4f211cd 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Cuemon.Extensions; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs index cba02726..13d07975 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataSourceOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Configuration; using Microsoft.EntityFrameworkCore; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs b/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs index 5d500281..003971ec 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs b/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs index cd4918ed..324eeb10 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreDbContext.cs @@ -1,4 +1,4 @@ -using Cuemon.Configuration; +using Cuemon.Configuration; using Microsoft.EntityFrameworkCore; namespace Savvyio.Extensions.EFCore; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs b/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs index 6b97a884..4c904d42 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreQueryOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq.Expressions; using Cuemon.Threading; diff --git a/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs b/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs index ebb2a772..37733e40 100644 --- a/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs +++ b/src/Savvyio.Extensions.EFCore/EfCoreRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; diff --git a/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs b/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs index 2317c035..b2e8cfef 100644 --- a/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs +++ b/src/Savvyio.Extensions.EFCore/IEfCoreDataSource.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Savvyio.Domain; namespace Savvyio.Extensions.EFCore; diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs index 6da177bf..11828e6b 100644 --- a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueueOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Extensions.NATS.Commands; diff --git a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs index 84558b8f..9f147632 100644 --- a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBusOptions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.NATS.EventDriven; +namespace Savvyio.Extensions.NATS.EventDriven; /// /// Configuration options for . diff --git a/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs b/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs index 5a435af8..e68a23fe 100644 --- a/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.NATS/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.NATS/NatsMessage.cs b/src/Savvyio.Extensions.NATS/NatsMessage.cs index 8bcab7ec..994bb5a3 100644 --- a/src/Savvyio.Extensions.NATS/NatsMessage.cs +++ b/src/Savvyio.Extensions.NATS/NatsMessage.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using NATS.Net; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs index c0c23e5b..5c55caa9 100644 --- a/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs +++ b/src/Savvyio.Extensions.NATS/NatsMessageOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Configuration; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs index 8ba7ee57..72fd86de 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs index 10246fea..60a9a79f 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/RequestConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs index 5b6b93e1..d9c9d916 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/SingleValueObjectConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using Cuemon.Extensions; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/GlobalSuppressions.cs b/src/Savvyio.Extensions.Newtonsoft.Json/GlobalSuppressions.cs index c648670e..f2047b79 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs b/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs index 4a2668ec..7f916fb2 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/JsonConverterExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Cuemon; using Codebelt.Extensions.Newtonsoft.Json; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs b/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs index e904981b..af96d467 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/JsonSerializerExtensions.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Newtonsoft.Json.Serialization; +using Codebelt.Extensions.Newtonsoft.Json.Serialization; using Newtonsoft.Json; namespace Savvyio.Extensions.Newtonsoft.Json; diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs b/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs index 360eb89e..de638f86 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/NewtonsoftJsonMarshaller.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using Codebelt.Extensions.Newtonsoft.Json.Formatters; using Newtonsoft.Json; diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs index 6e573b3f..7f19d7b3 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs index 8c7f813c..5587c1db 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Azure; using Azure.Core; using Azure.Identity; diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs index 751b9bbd..0b92d733 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueReceiveOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Configuration; namespace Savvyio.Extensions.QueueStorage; diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs index f16b7e45..00f91454 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueSendOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Configuration; namespace Savvyio.Extensions.QueueStorage; diff --git a/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs b/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs index 842432b2..e227b994 100644 --- a/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs +++ b/src/Savvyio.Extensions.QueueStorage/Commands/AzureCommandQueue.cs @@ -1,4 +1,4 @@ -using Azure.Storage.Queues; +using Azure.Storage.Queues; using Cuemon.Threading; using Savvyio.Commands; using Savvyio.Diagnostics; diff --git a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs index 90f76323..039aad66 100644 --- a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Azure; using Azure.Core; using Azure.Identity; diff --git a/src/Savvyio.Extensions.QueueStorage/GlobalSuppressions.cs b/src/Savvyio.Extensions.QueueStorage/GlobalSuppressions.cs index 6431c1a6..59067b15 100644 --- a/src/Savvyio.Extensions.QueueStorage/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.QueueStorage/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs index cec0e203..a70579fd 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueue.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.IO; using Cuemon.Extensions.Reflection; diff --git a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs index f1ba1ecd..ce6fde7a 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/Commands/RabbitMqCommandQueueOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Extensions.RabbitMQ.Commands; diff --git a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs index a42cf8ef..c54fd14b 100644 --- a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBusOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Extensions.RabbitMQ.EventDriven; diff --git a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs index 01fea777..ab16c74f 100644 --- a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs +++ b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using RabbitMQ.Client; diff --git a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs index 878c914e..b19f65df 100644 --- a/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs +++ b/src/Savvyio.Extensions.RabbitMQ/RabbitMqMessageOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Configuration; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs index bd2b0f54..089d4347 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs index 03a90ce7..ef02c42f 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessage.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Cuemon.Configuration; using Cuemon; using Savvyio.Messaging; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs index 61d67818..a62c9d02 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Amazon; using Amazon.Runtime; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs index fa582bfc..ba56394c 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonMessageReceiveOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Extensions.SimpleQueueService; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs index a21cd791..78c98654 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs index eb946d63..24cd2caa 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Amazon; using Cuemon; diff --git a/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs b/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs index f9292875..2bc45221 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/ClientConfigExtensions.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Amazon.Runtime; using Amazon.SimpleNotificationService; using Amazon.SQS; diff --git a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs index 70775d4b..51dc798f 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs index 15d4202e..dac7f7f5 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/Commands/AmazonCommandQueueOptions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.SimpleQueueService.Commands; +namespace Savvyio.Extensions.SimpleQueueService.Commands; /// /// Configuration options for . diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs index b69ac958..45dbff80 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs index 52641f87..43804561 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/AmazonEventBusOptions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.SimpleQueueService.EventDriven; +namespace Savvyio.Extensions.SimpleQueueService.EventDriven; /// /// Configuration options for . diff --git a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs index a0d30b37..dc822278 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; diff --git a/src/Savvyio.Extensions.SimpleQueueService/GlobalSuppressions.cs b/src/Savvyio.Extensions.SimpleQueueService/GlobalSuppressions.cs index e5e0b43c..e8cf4551 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/GlobalSuppressions.cs +++ b/src/Savvyio.Extensions.SimpleQueueService/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// This file is used by Code Analysis to maintain SuppressMessage +// 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. diff --git a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs index 06493c49..1a33a328 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs index 19c384b0..edabc1b7 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/DateTimeOffsetConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs index 138da9b1..c9e464cd 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs index 16e2c752..8ee551c1 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/MetadataDictionaryConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; diff --git a/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs index 367e1dbe..87cd5fa0 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/RequestConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs index d0e1fb65..e44a2660 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/SingleValueObjectConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using System.Text.Json; diff --git a/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs b/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs index 07f68977..ed0aaa97 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonConverterExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; diff --git a/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs b/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs index 6c5fb8d1..ab5a5d67 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonMarshaller.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using Cuemon.Extensions.Text.Json.Formatters; diff --git a/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs b/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs index 2870f95a..c6b268c5 100644 --- a/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs +++ b/src/Savvyio.Extensions.Text.Json/JsonSerializerOptionsExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text.Json; using Cuemon; diff --git a/src/Savvyio.Messaging/Acknowledgeable.cs b/src/Savvyio.Messaging/Acknowledgeable.cs index 1fe527b0..b4739ee3 100644 --- a/src/Savvyio.Messaging/Acknowledgeable.cs +++ b/src/Savvyio.Messaging/Acknowledgeable.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs b/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs index 1549fc99..3ebc9370 100644 --- a/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs +++ b/src/Savvyio.Messaging/Cryptography/MessageExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Security.Cryptography; diff --git a/src/Savvyio.Messaging/Message.cs b/src/Savvyio.Messaging/Message.cs index 4ad7b1f8..b931744f 100644 --- a/src/Savvyio.Messaging/Message.cs +++ b/src/Savvyio.Messaging/Message.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerable.cs b/src/Savvyio.Messaging/MessageAsyncEnumerable.cs index bb3f3f58..07a14719 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerable.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerable.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs b/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs index 1ebe5b51..4183a2d4 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerableOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; diff --git a/src/Savvyio.Messaging/MessageAsyncEnumerator.cs b/src/Savvyio.Messaging/MessageAsyncEnumerator.cs index 8e69ad61..7ffc8f32 100644 --- a/src/Savvyio.Messaging/MessageAsyncEnumerator.cs +++ b/src/Savvyio.Messaging/MessageAsyncEnumerator.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using Cuemon; diff --git a/src/Savvyio.Messaging/MessageExtensions.cs b/src/Savvyio.Messaging/MessageExtensions.cs index a27597ab..1fbcece4 100644 --- a/src/Savvyio.Messaging/MessageExtensions.cs +++ b/src/Savvyio.Messaging/MessageExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Messaging; diff --git a/src/Savvyio.Messaging/MessageOptions.cs b/src/Savvyio.Messaging/MessageOptions.cs index 445bc3b5..24821544 100644 --- a/src/Savvyio.Messaging/MessageOptions.cs +++ b/src/Savvyio.Messaging/MessageOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Configuration; using Cuemon.Extensions; diff --git a/src/Savvyio.Queries/Query.cs b/src/Savvyio.Queries/Query.cs index 048154e0..6d605068 100644 --- a/src/Savvyio.Queries/Query.cs +++ b/src/Savvyio.Queries/Query.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Queries; +namespace Savvyio.Queries; /// /// Provides a default implementation of of the interface. diff --git a/src/Savvyio.Queries/QueryDispatcher.cs b/src/Savvyio.Queries/QueryDispatcher.cs index de0a2d59..5acd1052 100644 --- a/src/Savvyio.Queries/QueryDispatcher.cs +++ b/src/Savvyio.Queries/QueryDispatcher.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Cuemon.Threading; diff --git a/src/Savvyio.Queries/QueryHandler.cs b/src/Savvyio.Queries/QueryHandler.cs index 0e8a0d1c..17beb652 100644 --- a/src/Savvyio.Queries/QueryHandler.cs +++ b/src/Savvyio.Queries/QueryHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Handlers; +using Savvyio.Handlers; namespace Savvyio.Queries; diff --git a/src/Savvyio.Queries/SavvyioOptionsExtensions.cs b/src/Savvyio.Queries/SavvyioOptionsExtensions.cs index 8a4665a1..d7a2665a 100644 --- a/src/Savvyio.Queries/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Queries/SavvyioOptionsExtensions.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Queries; +namespace Savvyio.Queries; /// /// Extension methods for the class. diff --git a/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs b/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs index 306d7351..891f80b1 100644 --- a/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs +++ b/test/Savvyio.Assets.Dapper.Tests/DbConnectionExtensions.cs @@ -1,4 +1,4 @@ -using System.Data; +using System.Data; using Dapper; namespace Savvyio.Assets; diff --git a/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs b/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs index dfaca7c1..f0924832 100644 --- a/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs +++ b/test/Savvyio.Assets.Dapper.Tests/GuidHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using Dapper; diff --git a/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs b/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs index c2389830..8234905f 100644 --- a/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs +++ b/test/Savvyio.Assets.EfCore.Tests/CustomEfCoreDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.EntityFrameworkCore; using Savvyio.Assets.Domain; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs b/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs index 7485698a..5480229e 100644 --- a/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs +++ b/test/Savvyio.Assets.EfCore.Tests/LongValueGenerator.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ValueGeneration; diff --git a/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs b/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs index 831a54c5..dfa23eea 100644 --- a/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs +++ b/test/Savvyio.Assets.EfCore.Tests/ModelBuilderExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/AccountCommandHandler.cs b/test/Savvyio.Assets.Tests/AccountCommandHandler.cs index e6ec7f41..359bd4bd 100644 --- a/test/Savvyio.Assets.Tests/AccountCommandHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountCommandHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Savvyio.Assets.Commands; using Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/AccountEventHandler.cs b/test/Savvyio.Assets.Tests/AccountEventHandler.cs index 97685c09..061163c5 100644 --- a/test/Savvyio.Assets.Tests/AccountEventHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountEventHandler.cs @@ -1,4 +1,4 @@ -using System.Text.Json; +using System.Text.Json; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.Assets.Tests/AccountQueryHandler.cs b/test/Savvyio.Assets.Tests/AccountQueryHandler.cs index e6f21098..34ab1365 100644 --- a/test/Savvyio.Assets.Tests/AccountQueryHandler.cs +++ b/test/Savvyio.Assets.Tests/AccountQueryHandler.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon; using Savvyio.Assets.EventDriven; using Savvyio.Assets.Queries; diff --git a/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs b/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs index 424906d6..6a116122 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateAccount.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Assets.Domain; using Savvyio.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs b/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs index 62e71f3e..e94c3c00 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateAccountWithValueObjects.cs @@ -1,4 +1,4 @@ -using Savvyio.Assets.Domain; +using Savvyio.Assets.Domain; using Savvyio.Commands; namespace Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs b/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs index 1d39bfe9..67d01baf 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreateMemberCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs b/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs index da6d1a11..0d073d95 100644 --- a/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Commands/CreatePlatformProvider.cs @@ -1,4 +1,4 @@ -using Savvyio.Assets.Domain; +using Savvyio.Assets.Domain; using Savvyio.Commands; namespace Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs b/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs index 730de9ab..e343ea58 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdateAccount.cs @@ -1,4 +1,4 @@ -using Savvyio.Assets.Domain; +using Savvyio.Assets.Domain; using Savvyio.Commands; namespace Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs index 4476e303..d5d4c7f5 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Assets.Domain; using Savvyio.Commands; diff --git a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs index f0bcdb74..978db668 100644 --- a/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs +++ b/test/Savvyio.Assets.Tests/Commands/UpdatePlatformProviderAccountPolicy.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; namespace Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/DbMarker.cs b/test/Savvyio.Assets.Tests/DbMarker.cs index 1acf7748..0377e408 100644 --- a/test/Savvyio.Assets.Tests/DbMarker.cs +++ b/test/Savvyio.Assets.Tests/DbMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Assets; +namespace Savvyio.Assets; public struct DbMarker { diff --git a/test/Savvyio.Assets.Tests/Domain/Account.cs b/test/Savvyio.Assets.Tests/Domain/Account.cs index 6312cb33..1ec63697 100644 --- a/test/Savvyio.Assets.Tests/Domain/Account.cs +++ b/test/Savvyio.Assets.Tests/Domain/Account.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Assets.Domain.Events; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/AccountId.cs b/test/Savvyio.Assets.Tests/Domain/AccountId.cs index d7b1751e..2e4bb6cd 100644 --- a/test/Savvyio.Assets.Tests/Domain/AccountId.cs +++ b/test/Savvyio.Assets.Tests/Domain/AccountId.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/Coordinates.cs b/test/Savvyio.Assets.Tests/Domain/Coordinates.cs index d6a42c0a..31134ec1 100644 --- a/test/Savvyio.Assets.Tests/Domain/Coordinates.cs +++ b/test/Savvyio.Assets.Tests/Domain/Coordinates.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/Credentials.cs b/test/Savvyio.Assets.Tests/Domain/Credentials.cs index cb6f459a..340b3665 100644 --- a/test/Savvyio.Assets.Tests/Domain/Credentials.cs +++ b/test/Savvyio.Assets.Tests/Domain/Credentials.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Cuemon.Collections.Generic; using Cuemon.Extensions; using Cuemon.Security.Cryptography; diff --git a/test/Savvyio.Assets.Tests/Domain/Description.cs b/test/Savvyio.Assets.Tests/Domain/Description.cs index 4ce954d9..36cdd128 100644 --- a/test/Savvyio.Assets.Tests/Domain/Description.cs +++ b/test/Savvyio.Assets.Tests/Domain/Description.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs b/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs index 00fbcd6e..ec8e924a 100644 --- a/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs +++ b/test/Savvyio.Assets.Tests/Domain/EmailAddress.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs b/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs index 2dbe43a3..9a5644a1 100644 --- a/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs +++ b/test/Savvyio.Assets.Tests/Domain/EventSourcing/TracedAccount.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Cuemon; using Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs index 47e894a7..0d8b9063 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountEmailAddressChanged.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs index 17562745..dca5435a 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountFullNameChanged.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs index ad9553d2..39fdd263 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiated.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs index 53fce971..e8775653 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/AccountInitiatedChained.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs index e82bc579..80ba6ca9 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderAccountPolicyChanged.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs index 927d6ba7..a4d99390 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderDescriptionChanged.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs index 3c19d646..578f6b52 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderInitiated.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs index 1abd8e08..cb4879a7 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderNameChanged.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs index 0241b198..4407b531 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/PlatformProviderThirdLevelDomainNameChanged.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs index 2d99e6ec..9d8bf7be 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountEmailAddressChanged.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain.EventSourcing; +using Savvyio.Domain.EventSourcing; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs index 8fff4aac..793bbfc3 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountFullNameChanged.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain.EventSourcing; +using Savvyio.Domain.EventSourcing; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs index 65ba4a5d..f0dcf29f 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/TracedAccountInitiated.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain.EventSourcing; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs index 2fde30b1..9cd98135 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountFailedLogonAttemptCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs index d2feb187..4ec914ea 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountInitiated.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs index 69837127..936df299 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountPasswordInitiated.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs index cbbbe15c..29842bb5 100644 --- a/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs +++ b/test/Savvyio.Assets.Tests/Domain/Events/UserAccountRemoved.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/FullName.cs b/test/Savvyio.Assets.Tests/Domain/FullName.cs index c8c53168..733c0b64 100644 --- a/test/Savvyio.Assets.Tests/Domain/FullName.cs +++ b/test/Savvyio.Assets.Tests/Domain/FullName.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs b/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs index cc0d391a..99b0b5a8 100644 --- a/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs +++ b/test/Savvyio.Assets.Tests/Domain/Handlers/AccountDomainEventHandler.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Text.Json; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs b/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs index 3c772da6..a45fa68b 100644 --- a/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs +++ b/test/Savvyio.Assets.Tests/Domain/Handlers/PlatformProviderDomainEventHandler.cs @@ -1,4 +1,4 @@ -using System.Text.Json; +using System.Text.Json; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Assets.Tests/Domain/Name.cs b/test/Savvyio.Assets.Tests/Domain/Name.cs index 15eaa69d..86a115eb 100644 --- a/test/Savvyio.Assets.Tests/Domain/Name.cs +++ b/test/Savvyio.Assets.Tests/Domain/Name.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs index cdf2a1d8..b1d0ac2a 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Assets.Domain.Events; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs index 2d789881..a6701a28 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProviderAccountPolicy.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs b/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs index c9807a48..96c88d1d 100644 --- a/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs +++ b/test/Savvyio.Assets.Tests/Domain/PlatformProviderId.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs b/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs index e9d3a52d..0517bfa7 100644 --- a/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs +++ b/test/Savvyio.Assets.Tests/Domain/ThirdLevelDomainName.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/Timestamp.cs b/test/Savvyio.Assets.Tests/Domain/Timestamp.cs index 96ce0e80..524dd439 100644 --- a/test/Savvyio.Assets.Tests/Domain/Timestamp.cs +++ b/test/Savvyio.Assets.Tests/Domain/Timestamp.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs b/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs index 76bc4ba6..4214207a 100644 --- a/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs +++ b/test/Savvyio.Assets.Tests/Domain/TracedAccountId.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccount.cs b/test/Savvyio.Assets.Tests/Domain/UserAccount.cs index 5323b974..1af37b0c 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccount.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccount.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Savvyio.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs b/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs index ff53c773..7656739b 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccountFailedLogonAttempt.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs b/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs index ce45074e..00c7268a 100644 --- a/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs +++ b/test/Savvyio.Assets.Tests/Domain/UserAccountPassword.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Savvyio.Domain; namespace Savvyio.Assets.Domain; diff --git a/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs index 4a029afe..ccaf9d75 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/AccountCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs b/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs index ffb41c04..f2467e66 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/AccountUpdated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs index 5a84feac..58d0c631 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/MemberCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs index e1cee350..8fb1fb98 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderCreated.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Assets.Domain; using Savvyio.EventDriven; diff --git a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs index 8ce11dcc..986141e6 100644 --- a/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs +++ b/test/Savvyio.Assets.Tests/EventDriven/PlatformProviderUpdated.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Assets.Domain; using Savvyio.EventDriven; diff --git a/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs b/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs index 2e7ff3ee..591a95e9 100644 --- a/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs +++ b/test/Savvyio.Assets.Tests/PlatformProviderHandler.cs @@ -1,4 +1,4 @@ -using System.Text.Json; +using System.Text.Json; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs b/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs index f6ebb023..57535429 100644 --- a/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs +++ b/test/Savvyio.Assets.Tests/Queries/AccountProjection.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Assets.Queries; +namespace Savvyio.Assets.Queries; public class AccountProjection { diff --git a/test/Savvyio.Assets.Tests/Queries/GetAccount.cs b/test/Savvyio.Assets.Tests/Queries/GetAccount.cs index 3e01391a..fddcffca 100644 --- a/test/Savvyio.Assets.Tests/Queries/GetAccount.cs +++ b/test/Savvyio.Assets.Tests/Queries/GetAccount.cs @@ -1,4 +1,4 @@ -using Savvyio.Queries; +using Savvyio.Queries; namespace Savvyio.Assets.Queries; diff --git a/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs b/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs index 8bf1d1a8..22f4da88 100644 --- a/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs +++ b/test/Savvyio.Assets.Tests/Queries/GetFakeAccount.cs @@ -1,4 +1,4 @@ -using Savvyio.Assets.EventDriven; +using Savvyio.Assets.EventDriven; using Savvyio.Queries; namespace Savvyio.Assets.Queries; diff --git a/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs b/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs index c14b72f3..bee19ed4 100644 --- a/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs +++ b/test/Savvyio.Assets.Tests/Queries/PlatformProviderProjection.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Assets.Queries; diff --git a/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs b/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs index 008a396c..08c9f7ce 100644 --- a/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs +++ b/test/Savvyio.Commands.Tests/Assets/DefaultCommand.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Commands.Assets; +namespace Savvyio.Commands.Assets; internal record DefaultCommand : Command { diff --git a/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs b/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs index 53f2329a..edc201db 100644 --- a/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs +++ b/test/Savvyio.Commands.Tests/Assets/DefaultCommandHandler.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Handlers; diff --git a/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs b/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs index 5159b69f..5528b2c2 100644 --- a/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs +++ b/test/Savvyio.Commands.Tests/CommandDispatcherTest.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands.Assets; diff --git a/test/Savvyio.Commands.Tests/CommandHandlerTest.cs b/test/Savvyio.Commands.Tests/CommandHandlerTest.cs index 57103a3f..92d39331 100644 --- a/test/Savvyio.Commands.Tests/CommandHandlerTest.cs +++ b/test/Savvyio.Commands.Tests/CommandHandlerTest.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; using Savvyio.Commands.Assets; diff --git a/test/Savvyio.Commands.Tests/CommandTest.cs b/test/Savvyio.Commands.Tests/CommandTest.cs index bfee754b..b64e5d15 100644 --- a/test/Savvyio.Commands.Tests/CommandTest.cs +++ b/test/Savvyio.Commands.Tests/CommandTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Savvyio.Commands.Assets; using Xunit; diff --git a/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs index eb1cdaff..410d144b 100644 --- a/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Commands.Tests/Messaging/CommandExtensionsTest.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions; +using Cuemon.Extensions; using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs index 0d74a5ce..c27eea6e 100644 --- a/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Commands.Tests/SavvyioOptionsExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Savvyio.Assets; using Xunit; diff --git a/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs b/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs index 42d8e19e..aa82f74e 100644 --- a/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs +++ b/test/Savvyio.Core.Tests/Assets/AccountHandlers.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading.Tasks; using Cuemon; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Core.Tests/Assets/DummyRequest.cs b/test/Savvyio.Core.Tests/Assets/DummyRequest.cs index 895d747f..428b97be 100644 --- a/test/Savvyio.Core.Tests/Assets/DummyRequest.cs +++ b/test/Savvyio.Core.Tests/Assets/DummyRequest.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Assets; diff --git a/test/Savvyio.Core.Tests/Assets/FakeCommand.cs b/test/Savvyio.Core.Tests/Assets/FakeCommand.cs index 96e6777f..ce5c3ffe 100644 --- a/test/Savvyio.Core.Tests/Assets/FakeCommand.cs +++ b/test/Savvyio.Core.Tests/Assets/FakeCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; namespace Savvyio.Assets; diff --git a/test/Savvyio.Core.Tests/Assets/FakeQuery.cs b/test/Savvyio.Core.Tests/Assets/FakeQuery.cs index 6a11b144..306c25b0 100644 --- a/test/Savvyio.Core.Tests/Assets/FakeQuery.cs +++ b/test/Savvyio.Core.Tests/Assets/FakeQuery.cs @@ -1,4 +1,4 @@ -using Savvyio.Queries; +using Savvyio.Queries; namespace Savvyio.Assets; diff --git a/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs b/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs index ff2567ba..de502fe6 100644 --- a/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs +++ b/test/Savvyio.Core.Tests/Assets/RootDummyRequest.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Assets; diff --git a/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs b/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs index 47d46523..6b970c67 100644 --- a/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs +++ b/test/Savvyio.Core.Tests/Dispatchers/FireForgetDispatcherTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs b/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs index c0fdd82a..dabca2ff 100644 --- a/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs +++ b/test/Savvyio.Core.Tests/Dispatchers/RequestReplyDispatcherTest.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Core.Tests/HandlerFactoryTest.cs b/test/Savvyio.Core.Tests/HandlerFactoryTest.cs index ff2d18c3..97259eb7 100644 --- a/test/Savvyio.Core.Tests/HandlerFactoryTest.cs +++ b/test/Savvyio.Core.Tests/HandlerFactoryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs index 7d672d70..9d1e27d1 100644 --- a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs index 4d5bffb2..195599c0 100644 --- a/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/Cryptography/SignedMessageTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs b/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs index 3ebcfc20..a0036752 100644 --- a/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/MessageOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Core.Tests/Messaging/MessageTest.cs b/test/Savvyio.Core.Tests/Messaging/MessageTest.cs index 4fa8b364..9e657c6f 100644 --- a/test/Savvyio.Core.Tests/Messaging/MessageTest.cs +++ b/test/Savvyio.Core.Tests/Messaging/MessageTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.Reflection; diff --git a/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs index a68f79f2..4fe3ba5e 100644 --- a/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Core.Tests/MetadataDictionaryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Cuemon; diff --git a/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs b/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs index 75628352..10ac80ef 100644 --- a/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs +++ b/test/Savvyio.Core.Tests/OrphanedHandlerExceptionTest.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.IO; +using Cuemon.Extensions.IO; using Cuemon.Extensions.Text.Json.Formatters; using Codebelt.Extensions.Xunit; using Savvyio.Assets; diff --git a/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs index 752d84fb..7b50e220 100644 --- a/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Core.Tests/SavvyioOptionsExtensionsTest.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Codebelt.Extensions.Xunit; using Savvyio.Assets; using Savvyio.Assets.Domain; diff --git a/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs b/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs index 3406b01a..9bfa4cad 100644 --- a/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs +++ b/test/Savvyio.Core.Tests/SavvyioOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Xunit; namespace Savvyio; diff --git a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs index e4c0a0a0..6700db35 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Cuemon; using Cuemon.Collections.Generic; using Microsoft.EntityFrameworkCore; diff --git a/test/Savvyio.Domain.Tests/AggregateRootTest.cs b/test/Savvyio.Domain.Tests/AggregateRootTest.cs index c5ca5d25..2992d018 100644 --- a/test/Savvyio.Domain.Tests/AggregateRootTest.cs +++ b/test/Savvyio.Domain.Tests/AggregateRootTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs b/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs index be47f32c..4afd3852 100644 --- a/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs +++ b/test/Savvyio.Domain.Tests/Assets/AccountHandlers.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain.Events; using Savvyio.Handlers; diff --git a/test/Savvyio.Domain.Tests/Assets/Mixed.cs b/test/Savvyio.Domain.Tests/Assets/Mixed.cs index 673b4575..281a665c 100644 --- a/test/Savvyio.Domain.Tests/Assets/Mixed.cs +++ b/test/Savvyio.Domain.Tests/Assets/Mixed.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Assets.Domain; namespace Savvyio.Domain.Assets; diff --git a/test/Savvyio.Domain.Tests/Assets/Money.cs b/test/Savvyio.Domain.Tests/Assets/Money.cs index 22c0aab7..8f6eb602 100644 --- a/test/Savvyio.Domain.Tests/Assets/Money.cs +++ b/test/Savvyio.Domain.Tests/Assets/Money.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Savvyio.Domain.Assets; diff --git a/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs b/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs index c66350cb..77eb8da6 100644 --- a/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs +++ b/test/Savvyio.Domain.Tests/DomainEventDispatcherExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Cuemon; diff --git a/test/Savvyio.Domain.Tests/DomainEventTest.cs b/test/Savvyio.Domain.Tests/DomainEventTest.cs index cca56efd..6328eba9 100644 --- a/test/Savvyio.Domain.Tests/DomainEventTest.cs +++ b/test/Savvyio.Domain.Tests/DomainEventTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; using Savvyio.Assets.Domain.Events; diff --git a/test/Savvyio.Domain.Tests/EntityTest.cs b/test/Savvyio.Domain.Tests/EntityTest.cs index d28a3da3..258e18dd 100644 --- a/test/Savvyio.Domain.Tests/EntityTest.cs +++ b/test/Savvyio.Domain.Tests/EntityTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; using Xunit; diff --git a/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs index 1e54e66d..9eeb9bed 100644 --- a/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Domain.Tests/SavvyioOptionsExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain.Handlers; using Xunit; diff --git a/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs b/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs index 3b56f0ad..4dd0f4d5 100644 --- a/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs +++ b/test/Savvyio.Domain.Tests/SingleValueObjectTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; using Xunit; diff --git a/test/Savvyio.Domain.Tests/ValueObjectTest.cs b/test/Savvyio.Domain.Tests/ValueObjectTest.cs index 58851b58..91f3bf64 100644 --- a/test/Savvyio.Domain.Tests/ValueObjectTest.cs +++ b/test/Savvyio.Domain.Tests/ValueObjectTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; using Savvyio.Domain.Assets; diff --git a/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs b/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs index 424543b3..91854ecb 100644 --- a/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs +++ b/test/Savvyio.EventDriven.Tests/IntegrationEventTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs index 1b9458d4..091a0340 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/CloudEvents/CloudEventTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Codebelt.Extensions.Xunit; using Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs index a28244dc..0fa0a281 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/InMemoryEventBusTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs index 0783645a..80f04ae5 100644 --- a/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/Messaging/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions; +using Cuemon.Extensions; using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Savvyio.Assets.EventDriven; diff --git a/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs index 729bf22a..6aa2266b 100644 --- a/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.EventDriven.Tests/SavvyioOptionsExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Savvyio.Assets; using Xunit; diff --git a/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs b/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs index 94cf183f..303f607d 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/Assets/AccountData.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Extensions; diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs index 8c63f48b..6d14a65b 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Data.Sqlite; using Xunit; diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs index 9f1e13db..e0dcbbf0 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperDataSourceTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs b/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs index 4ead7c84..39a232c2 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs +++ b/test/Savvyio.Extensions.Dapper.Tests/DapperQueryOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Data; using System.Threading; using Cuemon.Extensions; diff --git a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs index cbbb2e15..2bb7df0d 100644 --- a/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs +++ b/test/Savvyio.Extensions.DapperExtensions.Tests/DapperExtensionsQueryOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using DapperExtensions.Predicate; using Savvyio.Assets.Queries; using Xunit; diff --git a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs index 083277ba..7734330d 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Data.Sqlite; using Microsoft.Extensions.DependencyInjection; using Savvyio.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs index 94bd012b..09ad2c98 100644 --- a/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.DapperExtensions.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Data.Sqlite; using Microsoft.Extensions.DependencyInjection; using Savvyio.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs index a5da28bc..99f1b62a 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs index 5ac65f16..2c25abff 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Domain.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Savvyio.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs index ab24810e..fee8882e 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs index 789937a6..44a228c6 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/BusMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; public struct BusMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs index 8c6a4051..a33312ed 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/Assets/QueueMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; +namespace Savvyio.Extensions.DependencyInjection.NATS.Assets; public struct QueueMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs index 2972a79c..e69d2945 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/BusMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; public struct BusMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs index e18a6595..654c1008 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Assets/QueueMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; +namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.Assets; public struct QueueMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs index 49beae81..0e292566 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/BusMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; public struct BusMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs index 50ef7cb2..9625915f 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/Assets/QueueMarker.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; +namespace Savvyio.Extensions.DependencyInjection.SimpleQueueService.Assets; public struct QueueMarker { diff --git a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs index dd0c1ab9..428dafbc 100644 --- a/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.SimpleQueueService.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Amazon; using Amazon.Runtime; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs index 7fdd01a0..55a8ca49 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataSource.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.DependencyInjection.Assets; +namespace Savvyio.Extensions.DependencyInjection.Assets; public class FakeDataSource : IDataSource { diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs index b3110ecd..1ba67056 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeDataStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Threading; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs index 8d27a326..abbbe7da 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/FakeRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Threading.Tasks; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs index a01fb87a..d5ea2785 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Extensions.DependencyInjection.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs index 35c1d152..d9cc471d 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestCommandHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Commands; using Savvyio.Handlers; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs index b5cdb48b..0afc8200 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEvent.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; namespace Savvyio.Extensions.DependencyInjection.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs index 692c40e9..905a3c1d 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestDomainEventHandler.cs @@ -1,4 +1,4 @@ -using Savvyio.Domain; +using Savvyio.Domain; using Savvyio.Handlers; namespace Savvyio.Extensions.DependencyInjection.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs index 9e844383..aa06aca5 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEvent.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Extensions.DependencyInjection.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs index d332ead2..54c6a871 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestIntegrationEventHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.EventDriven; using Savvyio.Handlers; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs index 16606d0a..598d4dac 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQuery.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Queries; namespace Savvyio.Extensions.DependencyInjection.Assets; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs index a8b2dde0..a51abe98 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Assets/TestQueryHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.Handlers; using Savvyio.Queries; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs index 673030ac..184f9b87 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/Data/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Cuemon.Threading; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs index 64758e55..ad790c0c 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/SavvyioDependencyInjectionOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Xunit; diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs index f3bff142..8004ee00 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; using Savvyio.Dispatchers; diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs index ff6df775..48809562 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Xunit; namespace Savvyio.Extensions.EFCore; diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs index fdcd051b..a58aa425 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs index c0c3b4ac..b7143b57 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataStoreTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs index b9b81088..cf972a0b 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreRepositoryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs index 9f0d5942..9fedf1f3 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs index b7eb3395..f90e7ab4 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Extensions.NATS.Assets; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs index c0a0ae0a..810fe39f 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Assets/MemberCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Extensions.NATS.Assets; diff --git a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs index 6dcfd15e..1f741f73 100644 --- a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using System; using Xunit; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs index 88e7f038..5e9d7ddc 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/CommandTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs index 7e7ff31e..c0c40faf 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs index 5b989b16..1b03957f 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Cuemon; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs index 5b145ef9..47d91e3d 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/Domain/DomainTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs index 7606a17d..097865f7 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs index eda2e3b7..55abf231 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs index 51e043b4..87997971 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs index b564f864..4b9f3b27 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs index 78966f5f..af4b3865 100644 --- a/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Extensions.Newtonsoft.Json.Tests/MetadataDictionaryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Codebelt.Extensions.Newtonsoft.Json.Formatters; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs index b4972970..7b6a20f7 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Extensions.QueueStorage.Assets; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs index fd2a98ba..54f58304 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MarkerStructs.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Extensions.QueueStorage.Assets; +namespace Savvyio.Extensions.QueueStorage.Assets; public struct WindowsDebug { diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs index f37fc726..aa0dda1d 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Assets/MemberCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Extensions.QueueStorage.Assets; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs index ef7d0a71..cd7f4c65 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs index 9bd0f8d5..bf99ff71 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs index 4bfc1a68..6b844361 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs index 00e91c81..e9776519 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/EventDriven/AzureEventBusNewtonsoftJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs index aec8217e..87143536 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Azure; using Azure.Identity; using Azure.Storage; diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs index 9140e7af..3f5843a1 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueReceiveOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs index e657ae7e..e7fa2b4c 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.Tests/AzureQueueSendOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs index 7a106825..e38b3ac3 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Extensions.RabbitMQ.Assets; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs index c0347d89..41b00895 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Assets/MemberCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Extensions.RabbitMQ.Assets; diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs index 0cdbead6..6323f632 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/Commands/RabbitMqCommandQueueOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs index 8010f127..9d58e9f9 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/EventDriven/RabbitMqEventBusOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs index 0715c7de..c7eb757f 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs index 9619af17..e8fb4ca2 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/CreateMemberCommand.cs @@ -1,4 +1,4 @@ -using Savvyio.Commands; +using Savvyio.Commands; namespace Savvyio.Extensions.SimpleQueueService.Assets; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs index 4a6ac4e2..2bc5c112 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Assets/MemberCreated.cs @@ -1,4 +1,4 @@ -using Savvyio.EventDriven; +using Savvyio.EventDriven; namespace Savvyio.Extensions.SimpleQueueService.Assets; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs index 9cbdf692..b87d8e7b 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs index 3aecab51..b701aa49 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Commands/AmazonCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs index 6e9ed9c4..664d5b19 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs index 9849add1..e4ce0556 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/EventDriven/AmazonEventBusNewtonsoftJsonSerializerContextTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs index 4f7b8d35..855daabb 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Reflection; using Amazon; diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs index dc1ef02a..18de632a 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs index 268f6742..7c462dbe 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonResourceNameOptionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Codebelt.Extensions.Xunit; using Xunit; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs index ae73cbcf..185560f3 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/CommandTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Commands; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs index dce0df6a..cc3622f2 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/CommandExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs index 59cd9bb7..09a5a8b8 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Commands/Messaging/InMemoryCommandQueueTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Threading.Tasks; using Cuemon; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs index ec2e6693..68f5cc3b 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/Domain/DomainTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Domain; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs index b9145f0d..7f6c18b1 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/Cryptography/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs index c36de0af..00364357 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/CloudEvents/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs index 7158978f..de5f6219 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/Cryptography/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs index 985082bc..18b1efb6 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/EventDriven/Messaging/IntegrationEventExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using Cuemon.Extensions; using Cuemon.Extensions.IO; diff --git a/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs b/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs index 364fc99d..86237a5f 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs +++ b/test/Savvyio.Extensions.Text.Json.Tests/MetadataDictionaryTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon.Extensions.IO; using Cuemon.Extensions.Text.Json.Formatters; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.FunctionalTests/Assets/AccountData.cs b/test/Savvyio.FunctionalTests/Assets/AccountData.cs index f814a660..45af3d31 100644 --- a/test/Savvyio.FunctionalTests/Assets/AccountData.cs +++ b/test/Savvyio.FunctionalTests/Assets/AccountData.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Cuemon.Extensions; diff --git a/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs b/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs index 1406af5c..5aa2f2f9 100644 --- a/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs +++ b/test/Savvyio.FunctionalTests/DistributedMediatorTest.cs @@ -1,4 +1,4 @@ -using Amazon; +using Amazon; using Amazon.Runtime; using Codebelt.Extensions.Newtonsoft.Json.Formatters; using Codebelt.Extensions.Xunit; diff --git a/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs b/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs index 15953d35..1f8cb819 100644 --- a/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.FunctionalTests/Extensions/DependencyInjection/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Codebelt.Extensions.Xunit; using Codebelt.Extensions.Xunit.Hosting; diff --git a/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs b/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs index a3b8ce31..e10f026b 100644 --- a/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs +++ b/test/Savvyio.Queries.Tests/Assets/DefaultQuery.cs @@ -1,4 +1,4 @@ -namespace Savvyio.Queries.Assets; +namespace Savvyio.Queries.Assets; internal record DefaultQuery : Query { diff --git a/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs b/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs index 6376e4bd..341a13ea 100644 --- a/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs +++ b/test/Savvyio.Queries.Tests/Assets/DefaultQueryHandler.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Savvyio.Handlers; namespace Savvyio.Queries.Assets; diff --git a/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs b/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs index 3ae4eb32..6e9a4097 100644 --- a/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs +++ b/test/Savvyio.Queries.Tests/QueryDispatcherTest.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Savvyio.Dispatchers; diff --git a/test/Savvyio.Queries.Tests/QueryHandlerTest.cs b/test/Savvyio.Queries.Tests/QueryHandlerTest.cs index db47598d..a068d882 100644 --- a/test/Savvyio.Queries.Tests/QueryHandlerTest.cs +++ b/test/Savvyio.Queries.Tests/QueryHandlerTest.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; using Savvyio.Assets.Queries; using Savvyio.Queries.Assets; diff --git a/test/Savvyio.Queries.Tests/QueryTest.cs b/test/Savvyio.Queries.Tests/QueryTest.cs index 5cc8abce..ee3998a2 100644 --- a/test/Savvyio.Queries.Tests/QueryTest.cs +++ b/test/Savvyio.Queries.Tests/QueryTest.cs @@ -1,4 +1,4 @@ -using Cuemon.Extensions.Reflection; +using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Savvyio.Queries.Assets; using Xunit; diff --git a/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs b/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs index 6946e489..59620494 100644 --- a/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs +++ b/test/Savvyio.Queries.Tests/SavvyioOptionsExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Savvyio.Assets; using Xunit; From cb787dd5e4848eb6a9164331d5bda3e354336650 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 04:40:02 +0200 Subject: [PATCH 14/36] =?UTF-8?q?=F0=9F=8E=A8=20tidy=20whitespace=20and=20?= =?UTF-8?q?target-typed=20new=20in=20messaging=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply formatting-only cleanups to the NATS, RabbitMQ, and messaging code and tests, including target-typed new expressions and collection expression spacing. No behavior changes. --- .../Messaging/Cryptography/ISignedMessage.cs | 4 +- .../Reflection/AssemblyContext.cs | 172 +++++++++++++++++- .../EventDriven/NatsEventBus.cs | 4 +- .../EventDriven/RabbitMqEventBus.cs | 4 +- .../Commands/NatsCommandQueue.cs | 14 +- .../EventDriven/NatsEventBus.cs | 6 +- .../EventDriven/AzureEventBus.cs | 4 +- .../EventDriven/RabbitMqEventBus.cs | 4 +- .../Cryptography/SignedMessage.cs | 4 +- .../Cryptography/SignedMessageOptions.cs | 4 +- .../MetadataExtensionsTest.cs | 2 +- .../ServiceCollectionExtensionsTest.cs | 8 +- .../ServiceCollectionExtensionsTest.cs | 4 +- .../Commands/NatsCommandQueueTest.cs | 4 +- .../EventDriven/NatsEventBusTest.cs | 4 +- .../NatsMessageOptionsTest.cs | 2 +- .../ClientConfigExtensionsTest.cs | 4 +- 17 files changed, 206 insertions(+), 42 deletions(-) diff --git a/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs b/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs index ca8a1149..fdab9ad8 100644 --- a/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs +++ b/src/Savvyio.Core/Messaging/Cryptography/ISignedMessage.cs @@ -1,10 +1,10 @@ -namespace Savvyio.Messaging.Cryptography; +namespace Savvyio.Messaging.Cryptography; /// /// Defines a generic way to wrap an inside a cryptographically signed message. /// /// The type of the payload constraint to the interface. - public interface ISignedMessage : IMessage where T : IRequest +public interface ISignedMessage : IMessage where T : IRequest { /// /// Gets the cryptographic signature of the message. diff --git a/src/Savvyio.Core/Reflection/AssemblyContext.cs b/src/Savvyio.Core/Reflection/AssemblyContext.cs index 98a153fb..d7c187fe 100644 --- a/src/Savvyio.Core/Reflection/AssemblyContext.cs +++ b/src/Savvyio.Core/Reflection/AssemblyContext.cs @@ -1,10 +1,174 @@ -using Cuemon.Extensions.Collections.Generic; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Cuemon; namespace Savvyio.Reflection; /// /// Provides a set of static methods and properties to manage and filter assemblies in the current application domain. /// public static class AssemblyContext { private static readonly Lazy> AssemblyLoadFactory = new(() => AppDomain .CurrentDomain .GetAssemblies() .Where(AssemblyFilterCallback) .SelectMany(AssemblyDependenciesCallback) .Distinct() .Except(typeof(AssemblyContext).Assembly.Yield()) .ToList() .AsReadOnly()); private static Func _assemblyFilterCallback = DefaultAssemblyFilter; private static Func> _assemblyDependenciesCallback = DefaultAssemblyDependencies; private static Func _assemblyDependenciesFilterCallback = DefaultAssemblyDependenciesFilter; /// /// Gets or sets the function delegate that filters assemblies from the current application domain. /// /// The function delegate that filters assemblies from the current application domain. /// The default implementation filters away assemblies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyFilterCallback { get => _assemblyFilterCallback; set => _assemblyFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// The function delegate that recursively discover dependencies for an assembly in the current application domain. /// /// cannot be null. /// public static Func> AssemblyDependenciesCallback { get => _assemblyDependenciesCallback; set => _assemblyDependenciesCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets or sets the function delegate that filters assembly dependencies from the current application domain. /// /// The function delegate that filters assembly dependencies from the current application domain. /// The default implementation filters away assembly dependencies that suggest being part of the .NET runtime themselves. /// /// cannot be null. /// public static Func AssemblyDependenciesFilterCallback { get => _assemblyDependenciesFilterCallback; set => _assemblyDependenciesFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); } /// /// Gets the qualified assemblies from the current application domain. /// /// The qualified assemblies from the current application domain. /// This result of this property is coupled with and . public static IReadOnlyList CurrentDomainAssemblies => AssemblyLoadFactory.Value; private static bool DefaultAssemblyFilter(Assembly assembly) { return assembly.FullName != null && - !assembly.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && - !assembly.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); +using Cuemon.Extensions.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Cuemon; + +namespace Savvyio.Reflection; + + + + + + +/// +/// Provides a set of static methods and properties to manage and filter assemblies in the current application domain. +/// + public static class AssemblyContext +{ + private static readonly Lazy> AssemblyLoadFactory = new(() => AppDomain + .CurrentDomain + .GetAssemblies() + .Where(AssemblyFilterCallback) + .SelectMany(AssemblyDependenciesCallback) + .Distinct() + .Except(typeof(AssemblyContext).Assembly.Yield()) + .ToList() + .AsReadOnly()); + + private static Func _assemblyFilterCallback = DefaultAssemblyFilter; + private static Func> _assemblyDependenciesCallback = DefaultAssemblyDependencies; + private static Func _assemblyDependenciesFilterCallback = DefaultAssemblyDependenciesFilter; + + + + + + + + + + + + + + + + + + /// + /// Gets or sets the function delegate that filters assemblies from the current application domain. + /// + /// The function delegate that filters assemblies from the current application domain. + /// The default implementation filters away assemblies that suggest being part of the .NET runtime themselves. + /// + /// cannot be null. + /// + public static Func AssemblyFilterCallback + { + get => _assemblyFilterCallback; + set => _assemblyFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); + } + + + + + + + + + + + + + + + + /// + /// Gets or sets the function delegate that recursively discover dependencies for an assembly in the current application domain. + /// + /// The function delegate that recursively discover dependencies for an assembly in the current application domain. + /// + /// cannot be null. + /// + public static Func> AssemblyDependenciesCallback + { + get => _assemblyDependenciesCallback; + set => _assemblyDependenciesCallback = value ?? throw new ArgumentNullException(nameof(value)); + } + + + + + + + + + + + + + + + + + + /// + /// Gets or sets the function delegate that filters assembly dependencies from the current application domain. + /// + /// The function delegate that filters assembly dependencies from the current application domain. + /// The default implementation filters away assembly dependencies that suggest being part of the .NET runtime themselves. + /// + /// cannot be null. + /// + public static Func AssemblyDependenciesFilterCallback + { + get => _assemblyDependenciesFilterCallback; + set => _assemblyDependenciesFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); + } + + + + + + + + + + + + /// + /// Gets the qualified assemblies from the current application domain. + /// + /// The qualified assemblies from the current application domain. + /// This result of this property is coupled with and . + public static IReadOnlyList CurrentDomainAssemblies => AssemblyLoadFactory.Value; + + private static bool DefaultAssemblyFilter(Assembly assembly) + { + return assembly.FullName != null && + !assembly.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && + !assembly.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); } private static bool DefaultAssemblyDependenciesFilter(AssemblyName assemblyName) { return !assemblyName.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && !assemblyName.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); - } private static IEnumerable DefaultAssemblyDependencies(Assembly assembly) { var stack = new Stack(); var guard = new HashSet(); yield return assembly; stack.Push(assembly); guard.Add(assembly.FullName); while (stack.TryPop(out var assemblyToTraverse)) { foreach (var assemblyName in assemblyToTraverse.GetReferencedAssemblies().Where(AssemblyDependenciesFilterCallback)) { if (!guard.Add(assemblyName.FullName)) { continue; } if (Patterns.TryInvoke(() => Assembly.Load(assemblyName), out var referencedAssembly) && referencedAssembly != null) { stack.Push(referencedAssembly); yield return referencedAssembly; } } } } } \ No newline at end of file + } + + private static IEnumerable DefaultAssemblyDependencies(Assembly assembly) + { + var stack = new Stack(); + var guard = new HashSet(); + + yield return assembly; + + stack.Push(assembly); + guard.Add(assembly.FullName); + + while (stack.TryPop(out var assemblyToTraverse)) + { + foreach (var assemblyName in assemblyToTraverse.GetReferencedAssemblies().Where(AssemblyDependenciesFilterCallback)) + { + if (!guard.Add(assemblyName.FullName)) { continue; } + if (Patterns.TryInvoke(() => Assembly.Load(assemblyName), out var referencedAssembly) && referencedAssembly != null) + { + stack.Push(referencedAssembly); + yield return referencedAssembly; + } + } + } + } +} diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs index cdf372cc..4737e3e1 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/EventDriven/NatsEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using Savvyio.EventDriven; using Savvyio.Extensions.DependencyInjection.Messaging; using Savvyio.Extensions.NATS; @@ -13,7 +13,7 @@ namespace Savvyio.Extensions.DependencyInjection.NATS.EventDriven; /// public class NatsEventBus : NatsEventBus, IPublishSubscribeChannel { - + /// /// Initializes a new instance of the class. /// diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs index 7913b50a..18913050 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/EventDriven/RabbitMqEventBus.cs @@ -1,4 +1,4 @@ -using Savvyio.Extensions.RabbitMQ.EventDriven; +using Savvyio.Extensions.RabbitMQ.EventDriven; using System; using Savvyio.EventDriven; using Savvyio.Extensions.DependencyInjection.Messaging; @@ -13,7 +13,7 @@ namespace Savvyio.Extensions.DependencyInjection.RabbitMQ.EventDriven; /// public class RabbitMqEventBus : RabbitMqEventBus, IPublishSubscribeChannel { - + /// /// Initializes a new instance of the class. /// diff --git a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs index 2821fa41..d9404f05 100644 --- a/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs +++ b/src/Savvyio.Extensions.NATS/Commands/NatsCommandQueue.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.IO; using Cuemon.Extensions.Reflection; @@ -71,10 +71,10 @@ public async Task SendAsync(IEnumerable> messages, Action> ReceiveAsync(Action setup = null) { Validator.ThrowIfInvalidConfigurator(setup, out var options); - + var streamName = _options.StreamName; var consumerName = _options.ConsumerName; - + var consumer = await CreateConsumerAsync(new StreamConfig(streamName, [_options.Subject]) { Retention = StreamConfigRetention.Workqueue @@ -83,10 +83,10 @@ public async IAsyncEnumerable> ReceiveAsync(Action, CancellationT { Validator.ThrowIfInvalidConfigurator(setup, out var options); await foreach (var message in SubscribeMessagesAsync(_options.Subject, new NatsSubOpts() - { - }, cancellationToken: options.CancellationToken)) + { + }, cancellationToken: options.CancellationToken)) { var messageType = Type.GetType(message.Headers["type"]); var deserialized = Marshaller.Deserialize(await message.Data.FromBase64().ToStreamAsync().ConfigureAwait(false), messageType) as IMessage; diff --git a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs index 49592f95..92e6dd3d 100644 --- a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs +++ b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBus.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; @@ -141,7 +141,7 @@ private async Task InvokeHandlerAsync(Func, Cancella } } } - + /// /// Gets the representing the health check endpoint for the configured Azure Event Grid topic. /// diff --git a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs index 712eb692..c483ba85 100644 --- a/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs +++ b/src/Savvyio.Extensions.RabbitMQ/EventDriven/RabbitMqEventBus.cs @@ -1,4 +1,4 @@ -using Cuemon; +using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.IO; using Cuemon.Extensions.Reflection; @@ -95,7 +95,7 @@ public async Task SubscribeAsync(Func, CancellationT deserialized.Properties.Add(nameof(QueueDeclareOk.QueueName), queue.QueueName); await buffer.Writer.WriteAsync(deserialized, options.CancellationToken).ConfigureAwait(false); }; - + await RabbitMqChannel.BasicConsumeAsync(queue.QueueName, autoAck: true, consumer: consumer, options.CancellationToken).ConfigureAwait(false); while (await buffer.Reader.WaitToReadAsync(options.CancellationToken).ConfigureAwait(false)) diff --git a/src/Savvyio.Messaging/Cryptography/SignedMessage.cs b/src/Savvyio.Messaging/Cryptography/SignedMessage.cs index 28eb3018..2a5e8627 100644 --- a/src/Savvyio.Messaging/Cryptography/SignedMessage.cs +++ b/src/Savvyio.Messaging/Cryptography/SignedMessage.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; namespace Savvyio.Messaging.Cryptography; @@ -8,7 +8,7 @@ namespace Savvyio.Messaging.Cryptography; /// /// The type of the payload constraint to the interface. /// - public record SignedMessage : Acknowledgeable, ISignedMessage where T : IRequest +public record SignedMessage : Acknowledgeable, ISignedMessage where T : IRequest { /// /// Initializes a new instance of the class. diff --git a/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs b/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs index e4290817..43fcacac 100644 --- a/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs +++ b/src/Savvyio.Messaging/Cryptography/SignedMessageOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Cuemon; using Cuemon.Configuration; using Cuemon.Security.Cryptography; @@ -9,7 +9,7 @@ namespace Savvyio.Messaging.Cryptography; /// Configuration options that is related to wrapping an implementation inside a cryptographically signed message. /// /// - public class SignedMessageOptions : IValidatableParameterObject +public class SignedMessageOptions : IValidatableParameterObject { /// /// Initializes a new instance of the class. diff --git a/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs b/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs index 9d1eccb4..da6ec00a 100644 --- a/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs +++ b/test/Savvyio.Core.Tests/MetadataExtensionsTest.cs @@ -9,7 +9,7 @@ public class MetadataExtensionsTest : Test { public MetadataExtensionsTest(ITestOutputHelper output) : base(output) { - + } private class TestMetadata : IMetadata diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs index 7478cdac..69cba48f 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using Codebelt.Extensions.Xunit; +using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; using Savvyio.EventDriven; @@ -42,12 +42,12 @@ public void AddNatsCommandQueue_ShouldRegisterNatsCommandQueueAndConfigureOption var provider = services.BuildServiceProvider(); ConfiguredOptionsAssertions.Verify(provider); var queue = provider.GetService(); - - + + Assert.IsType(provider.GetRequiredService>()); Assert.IsType(provider.GetRequiredService>()); Assert.IsType(provider.GetRequiredService>()); - + Assert.NotNull(queue); } diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs index 06374502..d218828a 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/ServiceCollectionExtensionsTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using Codebelt.Extensions.Xunit; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; @@ -27,7 +27,7 @@ public ServiceCollectionExtensionsTest(ITestOutputHelper output) : base(output) public void AddRabbitMqCommandQueue_ShouldAddDefaultImplementation() { Action rabbitMqSetup = o => - { + { o.QueueName = "urn:queue"; }; diff --git a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs index da159e46..9f627f00 100644 --- a/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueTest.cs @@ -20,7 +20,7 @@ namespace Savvyio.Extensions.NATS.Commands; public class NatsCommandQueueTest : Test { private IMarshaller _marshaller = JsonMarshaller.Default; - private NatsCommandQueueOptions _options = new (); + private NatsCommandQueueOptions _options = new(); public NatsCommandQueueTest(ITestOutputHelper output) : base(output) { } @@ -54,7 +54,7 @@ public void Constructor_ShouldThrow_WhenOptionsIsNull() Assert.Throws(() => new NatsCommandQueue(_marshaller, null)); } - + [Fact] public void Constructor_ShouldThrow_WhenOptionsAreInvalid() { diff --git a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs index e0eeb948..6c20a1cd 100644 --- a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs @@ -18,7 +18,7 @@ namespace Savvyio.Extensions.NATS.EventDriven; public class NatsEventBusTest : Test { private IMarshaller _marshaller = JsonMarshaller.Default; - private NatsEventBusOptions _options = new (); + private NatsEventBusOptions _options = new(); public NatsEventBusTest(ITestOutputHelper output) : base(output) { } @@ -51,7 +51,7 @@ public void Constructor_ShouldThrow_WhenOptionsIsNull() Assert.Throws(() => new NatsEventBus(_marshaller, null)); } - + [Fact] public void Constructor_ShouldThrow_WhenOptionsAreInvalid() { diff --git a/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs index 3719e109..57d581f7 100644 --- a/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/NatsMessageOptionsTest.cs @@ -1,4 +1,4 @@ - using System; +using System; using Codebelt.Extensions.Xunit; using Cuemon; using Xunit; diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs b/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs index 03dfbeae..9af6950f 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs @@ -15,7 +15,7 @@ public ClientConfigExtensionsTest(ITestOutputHelper output) : base(output) [Fact] public void IsValid_Should_Return_True_When_Both_Aws_Client_Configurations_Are_Present() { - ClientConfig[] configurations = [ new AmazonSQSConfig(), new AmazonSimpleNotificationServiceConfig() ]; + ClientConfig[] configurations = [new AmazonSQSConfig(), new AmazonSimpleNotificationServiceConfig()]; Assert.True(configurations.IsValid()); Assert.IsType(configurations.SimpleQueueService()); @@ -25,7 +25,7 @@ public void IsValid_Should_Return_True_When_Both_Aws_Client_Configurations_Are_P [Fact] public void IsValid_Should_Return_False_When_Configurations_Are_Missing_Expected_Types() { - ClientConfig[] invalid = [ new AmazonSQSConfig() ]; + ClientConfig[] invalid = [new AmazonSQSConfig()]; Assert.False(invalid.IsValid()); Assert.NotNull(invalid.SimpleQueueService()); From 87facb108c8ee2a954fd5b8d340814447e8ef05f Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:32:36 +0200 Subject: [PATCH 15/36] =?UTF-8?q?=F0=9F=8E=A8=20normalize=20line=20endings?= =?UTF-8?q?=20and=20remove=20byte=20order=20marks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tracked text files were stored with mixed CRLF line endings and a UTF-8 byte order mark. Normalize them to LF without a BOM so diffs only show real changes and the new line ending check passes. --- .docfx/BuildDocfxImage.ps1 | 2 +- .docfx/api/dotnet/index.md | 2 +- .docfx/api/extensions/dotnet/index.md | 2 +- .../api/types/Savvyio.AsyncEventHandler`1.md | 2 +- .../Savvyio.Commands.CommandDispatcher.md | 2 +- ...Commands.Messaging.InMemoryCommandQueue.md | 2 +- .../Savvyio.Dispatchers.ServiceLocator.md | 2 +- .../Savvyio.Domain.DomainEventDispatcher.md | 2 +- ....Domain.DomainEventDispatcherExtensions.md | 2 +- ...vyio.Extensions.Dapper.DapperDataSource.md | 2 +- ...tensions.Dapper.DapperDataSourceOptions.md | 2 +- ...rExtensions.DapperExtensionsDataStore`1.md | 2 +- ...ection.Dapper.DapperDataSourceOptions`1.md | 2 +- ...encyInjection.Dapper.DapperDataSource`1.md | 2 +- ...rExtensions.DapperExtensionsDataStore`2.md | 2 +- ...rExtensions.ServiceCollectionExtensions.md | 2 +- ...Core.Domain.EfCoreAggregateDataSource`1.md | 2 +- ...Core.Domain.EfCoreAggregateRepository`3.md | 2 +- ...rcing.EfCoreTracedAggregateRepository`3.md | 2 +- ...entSourcing.ServiceCollectionExtensions.md | 2 +- ...Core.Domain.ServiceCollectionExtensions.md | 2 +- ...ection.EFCore.EfCoreDataSourceOptions`1.md | 2 +- ...encyInjection.EFCore.EfCoreDataSource`1.md | 2 +- ...dencyInjection.EFCore.EfCoreDataStore`2.md | 2 +- ...encyInjection.EFCore.EfCoreRepository`3.md | 2 +- ...tion.EFCore.ServiceCollectionExtensions.md | 2 +- ...n.Messaging.ServiceCollectionExtensions.md | 2 +- ...njection.NATS.Commands.NatsCommandQueue.md | 2 +- ...n.NATS.Commands.NatsCommandQueueOptions.md | 2 +- ...ection.NATS.ServiceCollectionExtensions.md | 2 +- ...on.RabbitMQ.ServiceCollectionExtensions.md | 2 +- ...ueueService.ServiceCollectionExtensions.md | 2 +- ....Domain.DomainEventDispatcherExtensions.md | 2 +- ...EFCore.Domain.EfCoreAggregateDataSource.md | 2 +- ...Core.Domain.EfCoreAggregateRepository`2.md | 2 +- ...g.EfCoreTracedAggregateEntityExtensions.md | 2 +- ...cing.EfCoreTracedAggregateEntityOptions.md | 2 +- ...tSourcing.EfCoreTracedAggregateEntity`2.md | 2 +- ...rcing.EfCoreTracedAggregateRepository`2.md | 2 +- ...in.EventSourcing.ModelBuilderExtensions.md | 2 +- ...entSourcing.TracedDomainEventExtensions.md | 2 +- ...yio.Extensions.EFCore.EfCoreDataStore`1.md | 2 +- ...vvyio.Extensions.EFCore.EfCoreDbContext.md | 2 +- ....Extensions.EFCore.EfCoreQueryOptions`1.md | 2 +- ...io.Extensions.EFCore.EfCoreRepository`2.md | 2 +- ....Json.Converters.AggregateRootConverter.md | 2 +- ....Converters.MetadataDictionaryConverter.md | 2 +- ...n.Converters.SingleValueObjectConverter.md | 2 +- .../types/Savvyio.HandlerDiscoveryModel.md | 2 +- .docfx/api/types/Savvyio.HandlerFactory.md | 2 +- .../Savvyio.HandlerServiceAssemblyModel.md | 2 +- ...o.HandlerServiceTypeImplementationModel.md | 2 +- ...o.Handlers.FireForgetRegistryExtensions.md | 2 +- ...Handlers.RequestReplyRegistryExtensions.md | 2 +- ...Savvyio.Messaging.AcknowledgedEventArgs.md | 2 +- ...essaging.Cryptography.MessageExtensions.md | 2 +- ...ng.Cryptography.SignedMessageExtensions.md | 2 +- .../Savvyio.Messaging.MessageExtensions.md | 2 +- .../api/types/Savvyio.MetadataExtensions.md | 2 +- .docfx/api/types/Savvyio.MetadataFactory.md | 2 +- .docfx/api/types/Savvyio.TaskExtensions.md | 2 +- .docfx/filterConfig.yml | 4 +- .docfx/includes/availability-modern.md | 2 +- .docfx/templates/savvyio/layout/_master.tmpl | 2 +- .docfx/templates/savvyio/public/main.js | 2 +- .gitattributes | 2 +- .github/CODE_OF_CONDUCT.md | 4 +- .github/codecov.yml | 2 +- Directory.Build.targets | 2 +- Directory.Packages.props | 2 +- src/Savvyio.App/Savvyio.App.csproj | 2 +- .../Savvyio.Commands.Messaging.csproj | 2 +- src/Savvyio.Commands/Savvyio.Commands.csproj | 2 +- src/Savvyio.Core/AsyncEventHandler.cs | 14 +++--- .../Messaging/IAcknowledgeable.cs | 28 +++++------ src/Savvyio.Core/Savvyio.Core.csproj | 2 +- .../Savvyio.Domain.EventSourcing.csproj | 2 +- .../Savvyio.EventDriven.Messaging.csproj | 2 +- .../Savvyio.EventDriven.csproj | 2 +- .../Savvyio.Extensions.Dapper.csproj | 2 +- ...Savvyio.Extensions.DapperExtensions.csproj | 2 +- ...tensions.DependencyInjection.Domain.csproj | 4 +- ...jection.EFCore.Domain.EventSourcing.csproj | 2 +- ...s.DependencyInjection.EFCore.Domain.csproj | 4 +- ...tensions.DependencyInjection.EFCore.csproj | 2 +- ...Extensions.DependencyInjection.NATS.csproj | 2 +- ...DependencyInjection.Newtonsoft.Json.csproj | 2 +- ...ns.DependencyInjection.QueueStorage.csproj | 2 +- ...nsions.DependencyInjection.RabbitMQ.csproj | 2 +- ...sions.DependencyInjection.Text.Json.csproj | 2 +- ...vyio.Extensions.DependencyInjection.csproj | 2 +- ...ensions.EFCore.Domain.EventSourcing.csproj | 2 +- .../Savvyio.Extensions.EFCore.Domain.csproj | 2 +- .../Savvyio.Extensions.EFCore.csproj | 2 +- .../Savvyio.Extensions.NATS.csproj | 2 +- .../AzureQueueOptions.cs | 46 +++++++++---------- .../EventDriven/AzureEventBusOptions.cs | 4 +- .../Savvyio.Extensions.QueueStorage.csproj | 2 +- .../Savvyio.Extensions.RabbitMQ.csproj | 2 +- ...vvyio.Extensions.SimpleQueueService.csproj | 2 +- .../Savvyio.Extensions.Text.Json.csproj | 2 +- .../Savvyio.Messaging.csproj | 2 +- .../Savvyio.Assets.EfCore.Tests.csproj | 2 +- .../Savvyio.Assets.Tests.csproj | 2 +- .../Savvyio.Core.Tests.csproj | 2 +- .../TracedAggregateRootTest.cs | 22 ++++----- .../Savvyio.Extensions.Dapper.Tests.csproj | 2 +- ...ns.DependencyInjection.Dapper.Tests.csproj | 2 +- ...ns.DependencyInjection.EFCore.Tests.csproj | 2 +- ....DependencyInjection.RabbitMQ.Tests.csproj | 2 +- ...avvyio.Extensions.Dispatchers.Tests.csproj | 2 +- .../Savvyio.Extensions.EFCore.Tests.csproj | 2 +- ...nsions.QueueStorage.FunctionalTests.csproj | 2 +- ...vvyio.Extensions.QueueStorage.Tests.csproj | 2 +- .../Savvyio.Extensions.RabbitMQ.Tests.csproj | 4 +- ....SimpleQueueService.FunctionalTests.csproj | 4 +- ...Extensions.SimpleQueueService.Tests.csproj | 2 +- .../Savvyio.Extensions.Text.Json.Tests.csproj | 2 +- .../Savvyio.FunctionalTests.csproj | 2 +- .../Savvyio.Queries.Tests.csproj | 2 +- 120 files changed, 178 insertions(+), 178 deletions(-) diff --git a/.docfx/BuildDocfxImage.ps1 b/.docfx/BuildDocfxImage.ps1 index 5d9f365a..861021cd 100644 --- a/.docfx/BuildDocfxImage.ps1 +++ b/.docfx/BuildDocfxImage.ps1 @@ -1,4 +1,4 @@ -[CmdletBinding()] +[CmdletBinding()] param() $ErrorActionPreference = 'Stop' diff --git a/.docfx/api/dotnet/index.md b/.docfx/api/dotnet/index.md index c54e3a90..62e7c764 100644 --- a/.docfx/api/dotnet/index.md +++ b/.docfx/api/dotnet/index.md @@ -1,4 +1,4 @@ ---- +--- uid: dotnet-md title: Savvy I/O API --- diff --git a/.docfx/api/extensions/dotnet/index.md b/.docfx/api/extensions/dotnet/index.md index 1b8a42b7..57bf3feb 100644 --- a/.docfx/api/extensions/dotnet/index.md +++ b/.docfx/api/extensions/dotnet/index.md @@ -1,4 +1,4 @@ ---- +--- uid: extensions-dotnet-md title: Extensions for Savvy I/O API --- diff --git a/.docfx/api/types/Savvyio.AsyncEventHandler`1.md b/.docfx/api/types/Savvyio.AsyncEventHandler`1.md index 3ac34e7b..bc29ed52 100644 --- a/.docfx/api/types/Savvyio.AsyncEventHandler`1.md +++ b/.docfx/api/types/Savvyio.AsyncEventHandler`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.AsyncEventHandler`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Commands.CommandDispatcher.md b/.docfx/api/types/Savvyio.Commands.CommandDispatcher.md index d36e3c0f..236ebfd0 100644 --- a/.docfx/api/types/Savvyio.Commands.CommandDispatcher.md +++ b/.docfx/api/types/Savvyio.Commands.CommandDispatcher.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Commands.CommandDispatcher example: - *content diff --git a/.docfx/api/types/Savvyio.Commands.Messaging.InMemoryCommandQueue.md b/.docfx/api/types/Savvyio.Commands.Messaging.InMemoryCommandQueue.md index d30a0c50..d1fdbff4 100644 --- a/.docfx/api/types/Savvyio.Commands.Messaging.InMemoryCommandQueue.md +++ b/.docfx/api/types/Savvyio.Commands.Messaging.InMemoryCommandQueue.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Commands.Messaging.InMemoryCommandQueue example: - *content diff --git a/.docfx/api/types/Savvyio.Dispatchers.ServiceLocator.md b/.docfx/api/types/Savvyio.Dispatchers.ServiceLocator.md index efbab22e..6f8bdd81 100644 --- a/.docfx/api/types/Savvyio.Dispatchers.ServiceLocator.md +++ b/.docfx/api/types/Savvyio.Dispatchers.ServiceLocator.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Dispatchers.ServiceLocator example: - *content diff --git a/.docfx/api/types/Savvyio.Domain.DomainEventDispatcher.md b/.docfx/api/types/Savvyio.Domain.DomainEventDispatcher.md index 0a5bfbd4..446b5321 100644 --- a/.docfx/api/types/Savvyio.Domain.DomainEventDispatcher.md +++ b/.docfx/api/types/Savvyio.Domain.DomainEventDispatcher.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Domain.DomainEventDispatcher example: - *content diff --git a/.docfx/api/types/Savvyio.Domain.DomainEventDispatcherExtensions.md b/.docfx/api/types/Savvyio.Domain.DomainEventDispatcherExtensions.md index 7d377f85..8836c97a 100644 --- a/.docfx/api/types/Savvyio.Domain.DomainEventDispatcherExtensions.md +++ b/.docfx/api/types/Savvyio.Domain.DomainEventDispatcherExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Domain.DomainEventDispatcherExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSource.md b/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSource.md index 09d9d207..3153fe1f 100644 --- a/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSource.md +++ b/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSource.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.Dapper.DapperDataSource example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSourceOptions.md b/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSourceOptions.md index c323090a..13ee8c1d 100644 --- a/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSourceOptions.md +++ b/.docfx/api/types/Savvyio.Extensions.Dapper.DapperDataSourceOptions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.Dapper.DapperDataSourceOptions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore`1.md b/.docfx/api/types/Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore`1.md index c36b7547..86c9796d 100644 --- a/.docfx/api/types/Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSourceOptions`1.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSourceOptions`1.md index 225fd9d7..1cf70d31 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSourceOptions`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSourceOptions`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSourceOptions`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSource`1.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSource`1.md index 90248c4c..0bfa39df 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSource`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSource`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.Dapper.DapperDataSource`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.DapperExtensionsDataStore`2.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.DapperExtensionsDataStore`2.md index e65ac74f..bca7808b 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.DapperExtensionsDataStore`2.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.DapperExtensionsDataStore`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.DapperExtensions.DapperExtensionsDataStore`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.ServiceCollectionExtensions.md index 11309ab3..5295e6e8 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.DapperExtensions.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.DapperExtensions.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateDataSource`1.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateDataSource`1.md index 4e4f2517..fb368961 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateDataSource`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateDataSource`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateDataSource`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateRepository`3.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateRepository`3.md index a496cd43..16b1bbde 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateRepository`3.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateRepository`3.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.Domain.EfCoreAggregateRepository`3 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`3.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`3.md index 05389353..c398c232 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`3.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`3.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`3 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.ServiceCollectionExtensions.md index b08c73c4..0a80eeb2 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.ServiceCollectionExtensions.md index 01df2407..cf1a9492 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.Domain.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.Domain.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSourceOptions`1.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSourceOptions`1.md index 1f4894e4..1b0c9ce4 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSourceOptions`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSourceOptions`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSourceOptions`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSource`1.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSource`1.md index 9b49dc9a..5261137a 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSource`1.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSource`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataSource`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataStore`2.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataStore`2.md index ba29154a..948bec25 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataStore`2.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataStore`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.EfCoreDataStore`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreRepository`3.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreRepository`3.md index d0a1a3b6..46f7ec7b 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreRepository`3.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.EfCoreRepository`3.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.EfCoreRepository`3 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.ServiceCollectionExtensions.md index 7cc7bca3..b1f8e16a 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.EFCore.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.EFCore.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Messaging.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Messaging.ServiceCollectionExtensions.md index 15d14380..1e096364 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Messaging.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.Messaging.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.Messaging.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueue.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueue.md index c547923f..5016a642 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueue.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueue.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueue`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueueOptions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueueOptions.md index 52ad703c..f5937651 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueueOptions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueueOptions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.NATS.Commands.NatsCommandQueueOptions`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.ServiceCollectionExtensions.md index 0ac40834..604271fc 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.NATS.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.NATS.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.RabbitMQ.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.RabbitMQ.ServiceCollectionExtensions.md index 7c9a6a0c..e6e9e0e7 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.RabbitMQ.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.RabbitMQ.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.RabbitMQ.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.SimpleQueueService.ServiceCollectionExtensions.md b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.SimpleQueueService.ServiceCollectionExtensions.md index 1ecdd8c8..def7d775 100644 --- a/.docfx/api/types/Savvyio.Extensions.DependencyInjection.SimpleQueueService.ServiceCollectionExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.DependencyInjection.SimpleQueueService.ServiceCollectionExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.DependencyInjection.SimpleQueueService.ServiceCollectionExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.DomainEventDispatcherExtensions.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.DomainEventDispatcherExtensions.md index 42898d32..6025ff4e 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.DomainEventDispatcherExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.DomainEventDispatcherExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.DomainEventDispatcherExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateDataSource.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateDataSource.md index 02b6b7e8..307db654 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateDataSource.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateDataSource.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EfCoreAggregateDataSource example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateRepository`2.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateRepository`2.md index 1b57e519..0a849f15 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateRepository`2.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EfCoreAggregateRepository`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EfCoreAggregateRepository`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityExtensions.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityExtensions.md index d036ae39..4642dda6 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityOptions.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityOptions.md index ad51ce50..be5e9430 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityOptions.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityOptions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntityOptions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntity`2.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntity`2.md index a1de460a..564d29ce 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntity`2.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntity`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateEntity`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`2.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`2.md index b5357827..16e3c579 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`2.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.EfCoreTracedAggregateRepository`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.ModelBuilderExtensions.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.ModelBuilderExtensions.md index 11051a6c..e2188d53 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.ModelBuilderExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.ModelBuilderExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.ModelBuilderExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.TracedDomainEventExtensions.md b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.TracedDomainEventExtensions.md index 9dfd6b74..0d59a696 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.TracedDomainEventExtensions.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.Domain.EventSourcing.TracedDomainEventExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.Domain.EventSourcing.TracedDomainEventExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDataStore`1.md b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDataStore`1.md index 68bf111f..bb86795c 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDataStore`1.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDataStore`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.EfCoreDataStore`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDbContext.md b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDbContext.md index 6f155954..c364b802 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDbContext.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreDbContext.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.EfCoreDbContext example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreQueryOptions`1.md b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreQueryOptions`1.md index 16376496..e50f56cd 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreQueryOptions`1.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreQueryOptions`1.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.EfCoreQueryOptions`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreRepository`2.md b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreRepository`2.md index 45529072..53948509 100644 --- a/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreRepository`2.md +++ b/.docfx/api/types/Savvyio.Extensions.EFCore.EfCoreRepository`2.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.EFCore.EfCoreRepository`2 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.Newtonsoft.Json.Converters.AggregateRootConverter.md b/.docfx/api/types/Savvyio.Extensions.Newtonsoft.Json.Converters.AggregateRootConverter.md index 50ba6c6a..5d28d3c3 100644 --- a/.docfx/api/types/Savvyio.Extensions.Newtonsoft.Json.Converters.AggregateRootConverter.md +++ b/.docfx/api/types/Savvyio.Extensions.Newtonsoft.Json.Converters.AggregateRootConverter.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.Newtonsoft.Json.Converters.AggregateRootConverter`1 example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.MetadataDictionaryConverter.md b/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.MetadataDictionaryConverter.md index f85b97eb..7e7f5d6e 100644 --- a/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.MetadataDictionaryConverter.md +++ b/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.MetadataDictionaryConverter.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.Text.Json.Converters.MetadataDictionaryConverter example: - *content diff --git a/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.SingleValueObjectConverter.md b/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.SingleValueObjectConverter.md index 320d5118..3b2938c3 100644 --- a/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.SingleValueObjectConverter.md +++ b/.docfx/api/types/Savvyio.Extensions.Text.Json.Converters.SingleValueObjectConverter.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Extensions.Text.Json.Converters.SingleValueObjectConverter example: - *content diff --git a/.docfx/api/types/Savvyio.HandlerDiscoveryModel.md b/.docfx/api/types/Savvyio.HandlerDiscoveryModel.md index e5b57e5b..fb3c285b 100644 --- a/.docfx/api/types/Savvyio.HandlerDiscoveryModel.md +++ b/.docfx/api/types/Savvyio.HandlerDiscoveryModel.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.HandlerDiscoveryModel example: - *content diff --git a/.docfx/api/types/Savvyio.HandlerFactory.md b/.docfx/api/types/Savvyio.HandlerFactory.md index 9dfb94cf..c1702bd7 100644 --- a/.docfx/api/types/Savvyio.HandlerFactory.md +++ b/.docfx/api/types/Savvyio.HandlerFactory.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.HandlerFactory example: - *content diff --git a/.docfx/api/types/Savvyio.HandlerServiceAssemblyModel.md b/.docfx/api/types/Savvyio.HandlerServiceAssemblyModel.md index 01c271c1..8c9bc633 100644 --- a/.docfx/api/types/Savvyio.HandlerServiceAssemblyModel.md +++ b/.docfx/api/types/Savvyio.HandlerServiceAssemblyModel.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.HandlerServiceAssemblyModel example: - *content diff --git a/.docfx/api/types/Savvyio.HandlerServiceTypeImplementationModel.md b/.docfx/api/types/Savvyio.HandlerServiceTypeImplementationModel.md index 26e92450..4c7c532b 100644 --- a/.docfx/api/types/Savvyio.HandlerServiceTypeImplementationModel.md +++ b/.docfx/api/types/Savvyio.HandlerServiceTypeImplementationModel.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.HandlerServiceTypeImplementationModel example: - *content diff --git a/.docfx/api/types/Savvyio.Handlers.FireForgetRegistryExtensions.md b/.docfx/api/types/Savvyio.Handlers.FireForgetRegistryExtensions.md index 75b10d30..c5b70a62 100644 --- a/.docfx/api/types/Savvyio.Handlers.FireForgetRegistryExtensions.md +++ b/.docfx/api/types/Savvyio.Handlers.FireForgetRegistryExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Handlers.FireForgetRegistryExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Handlers.RequestReplyRegistryExtensions.md b/.docfx/api/types/Savvyio.Handlers.RequestReplyRegistryExtensions.md index 3ad24664..dee19f07 100644 --- a/.docfx/api/types/Savvyio.Handlers.RequestReplyRegistryExtensions.md +++ b/.docfx/api/types/Savvyio.Handlers.RequestReplyRegistryExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Handlers.RequestReplyRegistryExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Messaging.AcknowledgedEventArgs.md b/.docfx/api/types/Savvyio.Messaging.AcknowledgedEventArgs.md index c8239b2c..10e46128 100644 --- a/.docfx/api/types/Savvyio.Messaging.AcknowledgedEventArgs.md +++ b/.docfx/api/types/Savvyio.Messaging.AcknowledgedEventArgs.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Messaging.AcknowledgedEventArgs example: - *content diff --git a/.docfx/api/types/Savvyio.Messaging.Cryptography.MessageExtensions.md b/.docfx/api/types/Savvyio.Messaging.Cryptography.MessageExtensions.md index 0f1fd64e..6485ee51 100644 --- a/.docfx/api/types/Savvyio.Messaging.Cryptography.MessageExtensions.md +++ b/.docfx/api/types/Savvyio.Messaging.Cryptography.MessageExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Messaging.Cryptography.MessageExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Messaging.Cryptography.SignedMessageExtensions.md b/.docfx/api/types/Savvyio.Messaging.Cryptography.SignedMessageExtensions.md index 0329b3e2..1e6cbd7f 100644 --- a/.docfx/api/types/Savvyio.Messaging.Cryptography.SignedMessageExtensions.md +++ b/.docfx/api/types/Savvyio.Messaging.Cryptography.SignedMessageExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Messaging.Cryptography.SignedMessageExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.Messaging.MessageExtensions.md b/.docfx/api/types/Savvyio.Messaging.MessageExtensions.md index fb603d8c..85412ba7 100644 --- a/.docfx/api/types/Savvyio.Messaging.MessageExtensions.md +++ b/.docfx/api/types/Savvyio.Messaging.MessageExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.Messaging.MessageExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.MetadataExtensions.md b/.docfx/api/types/Savvyio.MetadataExtensions.md index 37cf6905..1ea7b828 100644 --- a/.docfx/api/types/Savvyio.MetadataExtensions.md +++ b/.docfx/api/types/Savvyio.MetadataExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.MetadataExtensions example: - *content diff --git a/.docfx/api/types/Savvyio.MetadataFactory.md b/.docfx/api/types/Savvyio.MetadataFactory.md index 9db0a481..767b506f 100644 --- a/.docfx/api/types/Savvyio.MetadataFactory.md +++ b/.docfx/api/types/Savvyio.MetadataFactory.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.MetadataFactory example: - *content diff --git a/.docfx/api/types/Savvyio.TaskExtensions.md b/.docfx/api/types/Savvyio.TaskExtensions.md index 67e1a3b0..8772baa7 100644 --- a/.docfx/api/types/Savvyio.TaskExtensions.md +++ b/.docfx/api/types/Savvyio.TaskExtensions.md @@ -1,4 +1,4 @@ ---- +--- uid: Savvyio.TaskExtensions example: - *content diff --git a/.docfx/filterConfig.yml b/.docfx/filterConfig.yml index 837050d4..bab37623 100644 --- a/.docfx/filterConfig.yml +++ b/.docfx/filterConfig.yml @@ -1,4 +1,4 @@ -apiRules: +apiRules: - exclude: uidRegex: ^System\.Object - type: Type \ No newline at end of file + type: Type diff --git a/.docfx/includes/availability-modern.md b/.docfx/includes/availability-modern.md index db9549d4..a13a3f63 100644 --- a/.docfx/includes/availability-modern.md +++ b/.docfx/includes/availability-modern.md @@ -1 +1 @@ -Availability: .NET 11 and .NET 10 \ No newline at end of file +Availability: .NET 11 and .NET 10 diff --git a/.docfx/templates/savvyio/layout/_master.tmpl b/.docfx/templates/savvyio/layout/_master.tmpl index bea28ce5..c987bb72 100644 --- a/.docfx/templates/savvyio/layout/_master.tmpl +++ b/.docfx/templates/savvyio/layout/_master.tmpl @@ -152,4 +152,4 @@ {{/redirect_url}} - \ No newline at end of file + diff --git a/.docfx/templates/savvyio/public/main.js b/.docfx/templates/savvyio/public/main.js index 801e9b2d..438e0797 100644 --- a/.docfx/templates/savvyio/public/main.js +++ b/.docfx/templates/savvyio/public/main.js @@ -6,4 +6,4 @@ export default { title: 'GitHub' } ] - } \ No newline at end of file + } diff --git a/.gitattributes b/.gitattributes index 1ff0c423..6f3fcbdd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,7 @@ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### -* text=auto +* text=auto eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index e27edb40..1fa464ec 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,4 +1,4 @@ -# Contributor Covenant Code of Conduct +# Contributor Covenant Code of Conduct This document is adapted from the Contributor Covenant which is used by many open source projects, including those under the [.NET Foundation](https://dotnetfoundation.org/code-of-conduct). @@ -132,4 +132,4 @@ at [https://www.contributor-covenant.org/translations][translations]. [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations \ No newline at end of file +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/codecov.yml b/.github/codecov.yml index c0a00374..b52d0c49 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,2 +1,2 @@ ignore: - - "test" \ No newline at end of file + - "test" diff --git a/Directory.Build.targets b/Directory.Build.targets index 00bb68a3..f6a6a003 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,4 +1,4 @@ - + $([System.IO.File]::ReadAllText('$(PackageReleaseNotesFile)')) diff --git a/Directory.Packages.props b/Directory.Packages.props index c96d061a..4c57a099 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -55,4 +55,4 @@ - \ No newline at end of file + diff --git a/src/Savvyio.App/Savvyio.App.csproj b/src/Savvyio.App/Savvyio.App.csproj index 4eaf40d6..d265459d 100644 --- a/src/Savvyio.App/Savvyio.App.csproj +++ b/src/Savvyio.App/Savvyio.App.csproj @@ -1,4 +1,4 @@ - + false diff --git a/src/Savvyio.Commands.Messaging/Savvyio.Commands.Messaging.csproj b/src/Savvyio.Commands.Messaging/Savvyio.Commands.Messaging.csproj index bfd43845..b21967cc 100644 --- a/src/Savvyio.Commands.Messaging/Savvyio.Commands.Messaging.csproj +++ b/src/Savvyio.Commands.Messaging/Savvyio.Commands.Messaging.csproj @@ -1,4 +1,4 @@ - + Provides ways to scale out Commands using distributed subsystems. diff --git a/src/Savvyio.Commands/Savvyio.Commands.csproj b/src/Savvyio.Commands/Savvyio.Commands.csproj index e5ef97a6..f9d202f7 100644 --- a/src/Savvyio.Commands/Savvyio.Commands.csproj +++ b/src/Savvyio.Commands/Savvyio.Commands.csproj @@ -1,4 +1,4 @@ - + Provides the fundamental classes to work with the Command part of the CQRS pattern (Command and Query Responsibility Segregation). diff --git a/src/Savvyio.Core/AsyncEventHandler.cs b/src/Savvyio.Core/AsyncEventHandler.cs index fb119c07..3729c2bd 100644 --- a/src/Savvyio.Core/AsyncEventHandler.cs +++ b/src/Savvyio.Core/AsyncEventHandler.cs @@ -3,11 +3,11 @@ namespace Savvyio; -/// -/// Represents the method that will handle an event when the event provides data asynchronously. -/// -/// The type of the event data generated by the event. -/// The source of the event. -/// An object that contains the event data. -/// A task that represents the asynchronous operation. +/// +/// Represents the method that will handle an event when the event provides data asynchronously. +/// +/// The type of the event data generated by the event. +/// The source of the event. +/// An object that contains the event data. +/// A task that represents the asynchronous operation. public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; diff --git a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs index c13f9ede..d14aa339 100644 --- a/src/Savvyio.Core/Messaging/IAcknowledgeable.cs +++ b/src/Savvyio.Core/Messaging/IAcknowledgeable.cs @@ -3,25 +3,25 @@ namespace Savvyio.Messaging; -/// -/// Defines a generic way to make a message acknowledgeable. -/// +/// +/// Defines a generic way to make a message acknowledgeable. +/// public interface IAcknowledgeable { - /// - /// Occurs when the method is called. - /// + /// + /// Occurs when the method is called. + /// event AsyncEventHandler Acknowledged; - /// - /// Share state between components during message processing. - /// - /// The state between components during message processing. + /// + /// Share state between components during message processing. + /// + /// The state between components during message processing. IDictionary Properties { get; } - /// - /// Acknowledges that this message was processed successfully. - /// - /// A task that represents the asynchronous operation. + /// + /// Acknowledges that this message was processed successfully. + /// + /// A task that represents the asynchronous operation. Task AcknowledgeAsync(); } diff --git a/src/Savvyio.Core/Savvyio.Core.csproj b/src/Savvyio.Core/Savvyio.Core.csproj index b69fa2f1..57b8b9f8 100644 --- a/src/Savvyio.Core/Savvyio.Core.csproj +++ b/src/Savvyio.Core/Savvyio.Core.csproj @@ -1,4 +1,4 @@ - + Savvyio diff --git a/src/Savvyio.Domain.EventSourcing/Savvyio.Domain.EventSourcing.csproj b/src/Savvyio.Domain.EventSourcing/Savvyio.Domain.EventSourcing.csproj index a0aee09e..26536ea6 100644 --- a/src/Savvyio.Domain.EventSourcing/Savvyio.Domain.EventSourcing.csproj +++ b/src/Savvyio.Domain.EventSourcing/Savvyio.Domain.EventSourcing.csproj @@ -1,4 +1,4 @@ - + Provides the default implementation of an Aggregate Root that is Event Sourced enabled. Complements the concepts of DDD (Domain Driven Design). diff --git a/src/Savvyio.EventDriven.Messaging/Savvyio.EventDriven.Messaging.csproj b/src/Savvyio.EventDriven.Messaging/Savvyio.EventDriven.Messaging.csproj index f4be9bcb..0d41e495 100644 --- a/src/Savvyio.EventDriven.Messaging/Savvyio.EventDriven.Messaging.csproj +++ b/src/Savvyio.EventDriven.Messaging/Savvyio.EventDriven.Messaging.csproj @@ -1,4 +1,4 @@ - + Provides ways to scale out Integration Events for a distributed architecture. diff --git a/src/Savvyio.EventDriven/Savvyio.EventDriven.csproj b/src/Savvyio.EventDriven/Savvyio.EventDriven.csproj index c6341fb9..a7ca6666 100644 --- a/src/Savvyio.EventDriven/Savvyio.EventDriven.csproj +++ b/src/Savvyio.EventDriven/Savvyio.EventDriven.csproj @@ -1,4 +1,4 @@ - + Provides the fundamental classes to work with the concepts of Integration Events that complements both CQRS (Command and Query Responsibility Segregation) and DDD (Domain Driven Design). diff --git a/src/Savvyio.Extensions.Dapper/Savvyio.Extensions.Dapper.csproj b/src/Savvyio.Extensions.Dapper/Savvyio.Extensions.Dapper.csproj index 1cc9a018..fa723051 100644 --- a/src/Savvyio.Extensions.Dapper/Savvyio.Extensions.Dapper.csproj +++ b/src/Savvyio.Extensions.Dapper/Savvyio.Extensions.Dapper.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Dapper. diff --git a/src/Savvyio.Extensions.DapperExtensions/Savvyio.Extensions.DapperExtensions.csproj b/src/Savvyio.Extensions.DapperExtensions/Savvyio.Extensions.DapperExtensions.csproj index 9124fb6a..c046bfdc 100644 --- a/src/Savvyio.Extensions.DapperExtensions/Savvyio.Extensions.DapperExtensions.csproj +++ b/src/Savvyio.Extensions.DapperExtensions/Savvyio.Extensions.DapperExtensions.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Dapper and automapping of Plain Old CLR Objects (POCO) by DapperExtensions. diff --git a/src/Savvyio.Extensions.DependencyInjection.Domain/Savvyio.Extensions.DependencyInjection.Domain.csproj b/src/Savvyio.Extensions.DependencyInjection.Domain/Savvyio.Extensions.DependencyInjection.Domain.csproj index 876601a6..d12a265a 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Domain/Savvyio.Extensions.DependencyInjection.Domain.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.Domain/Savvyio.Extensions.DependencyInjection.Domain.csproj @@ -1,5 +1,5 @@ - - + + Extend the Savvy I/O support for Microsoft Dependency Injection - optimized for DDD (Domain Driven Design). ddd domain-driven-design event-sourcing es aggregate-repository traced-aggregate-repository di depedency-injection marker data-store dao data-access-object diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.csproj b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.csproj index 8feb7577..29177d02 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing/Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing.csproj @@ -1,5 +1,5 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with Microsoft Entity Framework Core implementation - optimized for Domain Driven Design and Event Sourcing. event-sourcing es ddd domain-driven-design traced-aggregate-repository efcore entity-framework-core di depedency-injection marker data-store dao data-access-object repository diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/Savvyio.Extensions.DependencyInjection.EFCore.Domain.csproj b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/Savvyio.Extensions.DependencyInjection.EFCore.Domain.csproj index a54261c7..1aff82c1 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/Savvyio.Extensions.DependencyInjection.EFCore.Domain.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore.Domain/Savvyio.Extensions.DependencyInjection.EFCore.Domain.csproj @@ -1,10 +1,10 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with Microsoft Entity Framework Core implementation - optimized for DDD (Domain Driven Design). ddd domain-driven-design aggregate-repository efcore entity-framework-core di depedency-injection marker data-store dao data-access-object repository - + diff --git a/src/Savvyio.Extensions.DependencyInjection.EFCore/Savvyio.Extensions.DependencyInjection.EFCore.csproj b/src/Savvyio.Extensions.DependencyInjection.EFCore/Savvyio.Extensions.DependencyInjection.EFCore.csproj index 50f8276d..35fcd197 100644 --- a/src/Savvyio.Extensions.DependencyInjection.EFCore/Savvyio.Extensions.DependencyInjection.EFCore.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.EFCore/Savvyio.Extensions.DependencyInjection.EFCore.csproj @@ -1,5 +1,5 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with Microsoft Entity Framework Core implementation. efcore entity-framework-core di depedency-injection marker data-store dao data-access-object repository diff --git a/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj b/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj index 9ed94a20..c5b1bdcd 100644 --- a/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.NATS/Savvyio.Extensions.DependencyInjection.NATS.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with NATS Work-Queue Stream and NATS Core Publish-Subscribe implementations. diff --git a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.csproj b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.csproj index a2fffda6..070f2d5d 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json/Savvyio.Extensions.DependencyInjection.Newtonsoft.Json.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with support for Newtonsoft JSON implementations. diff --git a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Savvyio.Extensions.DependencyInjection.QueueStorage.csproj b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Savvyio.Extensions.DependencyInjection.QueueStorage.csproj index f615606a..e28a5f2a 100644 --- a/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Savvyio.Extensions.DependencyInjection.QueueStorage.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.QueueStorage/Savvyio.Extensions.DependencyInjection.QueueStorage.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with Azure Queue Storage paired with Azure Event Grid implementations. diff --git a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Savvyio.Extensions.DependencyInjection.RabbitMQ.csproj b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Savvyio.Extensions.DependencyInjection.RabbitMQ.csproj index 23f83cbb..15762055 100644 --- a/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Savvyio.Extensions.DependencyInjection.RabbitMQ.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.RabbitMQ/Savvyio.Extensions.DependencyInjection.RabbitMQ.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with RabbitMQ Worker Queue and Publish/Subscribe implementations. diff --git a/src/Savvyio.Extensions.DependencyInjection.Text.Json/Savvyio.Extensions.DependencyInjection.Text.Json.csproj b/src/Savvyio.Extensions.DependencyInjection.Text.Json/Savvyio.Extensions.DependencyInjection.Text.Json.csproj index 1901465b..e2897d3a 100644 --- a/src/Savvyio.Extensions.DependencyInjection.Text.Json/Savvyio.Extensions.DependencyInjection.Text.Json.csproj +++ b/src/Savvyio.Extensions.DependencyInjection.Text.Json/Savvyio.Extensions.DependencyInjection.Text.Json.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Dependency Injection with support for official built-in JSON implementations. diff --git a/src/Savvyio.Extensions.DependencyInjection/Savvyio.Extensions.DependencyInjection.csproj b/src/Savvyio.Extensions.DependencyInjection/Savvyio.Extensions.DependencyInjection.csproj index 84597f35..ba4f3e73 100644 --- a/src/Savvyio.Extensions.DependencyInjection/Savvyio.Extensions.DependencyInjection.csproj +++ b/src/Savvyio.Extensions.DependencyInjection/Savvyio.Extensions.DependencyInjection.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Microsoft Dependency Injection. diff --git a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/Savvyio.Extensions.EFCore.Domain.EventSourcing.csproj b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/Savvyio.Extensions.EFCore.Domain.EventSourcing.csproj index 71b9faaa..d5759c30 100644 --- a/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/Savvyio.Extensions.EFCore.Domain.EventSourcing.csproj +++ b/src/Savvyio.Extensions.EFCore.Domain.EventSourcing/Savvyio.Extensions.EFCore.Domain.EventSourcing.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Entity Framework Core - optimized for Domain Driven Design and Event Sourcing. diff --git a/src/Savvyio.Extensions.EFCore.Domain/Savvyio.Extensions.EFCore.Domain.csproj b/src/Savvyio.Extensions.EFCore.Domain/Savvyio.Extensions.EFCore.Domain.csproj index c2b0440f..d0e3857b 100644 --- a/src/Savvyio.Extensions.EFCore.Domain/Savvyio.Extensions.EFCore.Domain.csproj +++ b/src/Savvyio.Extensions.EFCore.Domain/Savvyio.Extensions.EFCore.Domain.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O support for Microsoft Entity Framework Core - optimized for DDD (Domain Driven Design). diff --git a/src/Savvyio.Extensions.EFCore/Savvyio.Extensions.EFCore.csproj b/src/Savvyio.Extensions.EFCore/Savvyio.Extensions.EFCore.csproj index d9964525..022abddb 100644 --- a/src/Savvyio.Extensions.EFCore/Savvyio.Extensions.EFCore.csproj +++ b/src/Savvyio.Extensions.EFCore/Savvyio.Extensions.EFCore.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Microsoft Entity Framework Core. diff --git a/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj b/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj index 0dcd2a3b..034518e9 100644 --- a/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj +++ b/src/Savvyio.Extensions.NATS/Savvyio.Extensions.NATS.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for NATS Work-Queue Stream and NATS Core Publish-Subscribe. diff --git a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs index 5587c1db..2d8c548b 100644 --- a/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/AzureQueueOptions.cs @@ -9,19 +9,19 @@ namespace Savvyio.Extensions.QueueStorage; -/// +/// /// Configuration options for . -/// +/// public class AzureQueueOptions : IValidatableParameterObject { - /// + /// /// The maximum number of messages that Azure Queue Storage supports when retrieving. - /// + /// public const int MaxNumberOfMessages = 32; - /// + /// /// The maximum visibility timeout for messages in Azure Queue Storage. - /// + /// public static readonly TimeSpan MaxVisibilityTimeout = TimeSpan.FromDays(7); private Action _clientCallback; @@ -85,27 +85,27 @@ public AzureQueueOptions() SendContext = new AzureQueueSendOptions(); } - /// + /// /// Gets the options for receiving messages from the queue. - /// + /// public AzureQueueReceiveOptions ReceiveContext { get; } - /// + /// /// Gets the options for sending messages to the queue. - /// + /// public AzureQueueSendOptions SendContext { get; } - /// + /// /// Gets or sets the name of the storage account. - /// + /// public string StorageAccountName { get; set; } - /// + /// /// Gets or sets the name of the queue. - /// + /// public string QueueName { get; set; } - /// + /// /// Gets or sets the credential used to authenticate with Azure. /// /// Setting this property will nullify and as they are mutually exclusive. @@ -120,7 +120,7 @@ public TokenCredential Credential } } - /// + /// /// Gets or sets the SAS credential used to authenticate with Azure. /// /// Setting this property will nullify and as they are mutually exclusive. @@ -135,7 +135,7 @@ public AzureSasCredential SasCredential } } - /// + /// /// Gets or sets the storage key credential used to authenticate with Azure. /// /// Setting this property will nullify and as they are mutually exclusive. @@ -150,14 +150,14 @@ public StorageSharedKeyCredential StorageKeyCredential } } - /// + /// /// Gets or sets the connection string used to connect to the Azure storage account. - /// + /// public string ConnectionString { get; set; } - /// + /// /// Gets the settings for the >. - /// + /// public QueueClientOptions Settings { get; } /// @@ -177,8 +177,8 @@ internal void SetConfiguredClient(QueueClient client) _clientCallback?.Invoke(client); } - /// - /// Validates the options to ensure they are in a valid state. + /// + /// Validates the options to ensure they are in a valid state. /// /// /// cannot be null, empty, or consists only of white-space characters when was specified -or- diff --git a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs index 039aad66..5f364ca8 100644 --- a/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs +++ b/src/Savvyio.Extensions.QueueStorage/EventDriven/AzureEventBusOptions.cs @@ -8,9 +8,9 @@ namespace Savvyio.Extensions.QueueStorage.EventDriven; -/// +/// /// Configuration options for . -/// +/// public class AzureEventBusOptions : IValidatableParameterObject { private TokenCredential _credential; diff --git a/src/Savvyio.Extensions.QueueStorage/Savvyio.Extensions.QueueStorage.csproj b/src/Savvyio.Extensions.QueueStorage/Savvyio.Extensions.QueueStorage.csproj index 714680aa..f8a9de89 100644 --- a/src/Savvyio.Extensions.QueueStorage/Savvyio.Extensions.QueueStorage.csproj +++ b/src/Savvyio.Extensions.QueueStorage/Savvyio.Extensions.QueueStorage.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Azure Queue Storage paired with Azure Event Grid. diff --git a/src/Savvyio.Extensions.RabbitMQ/Savvyio.Extensions.RabbitMQ.csproj b/src/Savvyio.Extensions.RabbitMQ/Savvyio.Extensions.RabbitMQ.csproj index 5299f41f..bd077a80 100644 --- a/src/Savvyio.Extensions.RabbitMQ/Savvyio.Extensions.RabbitMQ.csproj +++ b/src/Savvyio.Extensions.RabbitMQ/Savvyio.Extensions.RabbitMQ.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for RabbitMQ Work Queue and RabbitMQ Publish/Subscribe. diff --git a/src/Savvyio.Extensions.SimpleQueueService/Savvyio.Extensions.SimpleQueueService.csproj b/src/Savvyio.Extensions.SimpleQueueService/Savvyio.Extensions.SimpleQueueService.csproj index 538ecff1..78b5961b 100644 --- a/src/Savvyio.Extensions.SimpleQueueService/Savvyio.Extensions.SimpleQueueService.csproj +++ b/src/Savvyio.Extensions.SimpleQueueService/Savvyio.Extensions.SimpleQueueService.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for Amazon Simple Queue Service (AWS SQS) paired with Amazon Simple Notification Service (AWS SNS). diff --git a/src/Savvyio.Extensions.Text.Json/Savvyio.Extensions.Text.Json.csproj b/src/Savvyio.Extensions.Text.Json/Savvyio.Extensions.Text.Json.csproj index d553bcac..a1cff0c3 100644 --- a/src/Savvyio.Extensions.Text.Json/Savvyio.Extensions.Text.Json.csproj +++ b/src/Savvyio.Extensions.Text.Json/Savvyio.Extensions.Text.Json.csproj @@ -1,4 +1,4 @@ - + Extend the Savvy I/O core assemblies with support for official built-in JSON. diff --git a/src/Savvyio.Messaging/Savvyio.Messaging.csproj b/src/Savvyio.Messaging/Savvyio.Messaging.csproj index cc7dbfce..239a7760 100644 --- a/src/Savvyio.Messaging/Savvyio.Messaging.csproj +++ b/src/Savvyio.Messaging/Savvyio.Messaging.csproj @@ -1,4 +1,4 @@ - + Provides the fundamental classes to work with Messaging in a distributed architecture. diff --git a/test/Savvyio.Assets.EfCore.Tests/Savvyio.Assets.EfCore.Tests.csproj b/test/Savvyio.Assets.EfCore.Tests/Savvyio.Assets.EfCore.Tests.csproj index f693c479..bd0fd02c 100644 --- a/test/Savvyio.Assets.EfCore.Tests/Savvyio.Assets.EfCore.Tests.csproj +++ b/test/Savvyio.Assets.EfCore.Tests/Savvyio.Assets.EfCore.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Assets diff --git a/test/Savvyio.Assets.Tests/Savvyio.Assets.Tests.csproj b/test/Savvyio.Assets.Tests/Savvyio.Assets.Tests.csproj index a0116fe6..0b71b9ce 100644 --- a/test/Savvyio.Assets.Tests/Savvyio.Assets.Tests.csproj +++ b/test/Savvyio.Assets.Tests/Savvyio.Assets.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Assets diff --git a/test/Savvyio.Core.Tests/Savvyio.Core.Tests.csproj b/test/Savvyio.Core.Tests/Savvyio.Core.Tests.csproj index c12e8521..80b0275a 100644 --- a/test/Savvyio.Core.Tests/Savvyio.Core.Tests.csproj +++ b/test/Savvyio.Core.Tests/Savvyio.Core.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio diff --git a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs index 6700db35..368302f4 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs @@ -157,36 +157,36 @@ public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToSto Assert.Equal(name, sut5.FullName); Assert.Equal("root@gimlichael.dev", sut5.EmailAddress); - Assert.True(Match(@"Model: + Assert.True(Match(@"Model: EntityType: EfCoreTracedAggregateEntity - Properties: + Properties: Id (_id, Guid) Required PK AfterSave:Throw - Annotations: + Annotations: Relational:ColumnName: id Relational:ColumnType: uniqueidentifier Version (_version, long) Required PK AfterSave:Throw - Annotations: + Annotations: Relational:ColumnName: version Relational:ColumnType: int Payload (_payload, byte[]) - Annotations: + Annotations: Relational:ColumnName: payload Relational:ColumnType: varchar(max) Timestamp (_timestamp, DateTime) Required - Annotations: + Annotations: Relational:ColumnName: timestamp Relational:ColumnType: datetime Type (_type, string) - Annotations: + Annotations: Relational:ColumnName: clrtype Relational:ColumnType: varchar(1024) - Keys: + Keys: Id, Version PK - Annotations: - Relational:Schema: + Annotations: + Relational:Schema: Relational:TableName: TracedAccount_DomainEvents RelationshipDiscoveryConvention:NavigationCandidates: Microsoft.EntityFrameworkCore.Utilities.OrderedDictionary`2[System.Reflection.PropertyInfo,System.ValueTuple`2[System.Type,System.Nullable`1[System.Boolean]]] -Annotations: +Annotations: BaseTypeDiscoveryConvention:DerivedTypes: System.Collections.Generic.Dictionary`2[System.Type,System.Collections.Generic.List`1[Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType]] InversePropertyAttributeConvention:InverseNavigations: System.Collections.Generic.Dictionary`2[System.Type,System.Collections.Generic.SortedSet`1[System.Type]] NonNullableConventionState: System.Reflection.NullabilityInfoContext diff --git a/test/Savvyio.Extensions.Dapper.Tests/Savvyio.Extensions.Dapper.Tests.csproj b/test/Savvyio.Extensions.Dapper.Tests/Savvyio.Extensions.Dapper.Tests.csproj index cc8078d6..dfa56e3a 100644 --- a/test/Savvyio.Extensions.Dapper.Tests/Savvyio.Extensions.Dapper.Tests.csproj +++ b/test/Savvyio.Extensions.Dapper.Tests/Savvyio.Extensions.Dapper.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/Savvyio.Extensions.DependencyInjection.Dapper.Tests.csproj b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/Savvyio.Extensions.DependencyInjection.Dapper.Tests.csproj index 9fcb7449..be0dd610 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/Savvyio.Extensions.DependencyInjection.Dapper.Tests.csproj +++ b/test/Savvyio.Extensions.DependencyInjection.Dapper.Tests/Savvyio.Extensions.DependencyInjection.Dapper.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.DependencyInjection.Dapper diff --git a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/Savvyio.Extensions.DependencyInjection.EFCore.Tests.csproj b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/Savvyio.Extensions.DependencyInjection.EFCore.Tests.csproj index ee485ec4..9aca8821 100644 --- a/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/Savvyio.Extensions.DependencyInjection.EFCore.Tests.csproj +++ b/test/Savvyio.Extensions.DependencyInjection.EFCore.Tests/Savvyio.Extensions.DependencyInjection.EFCore.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.DependencyInjection.EFCore diff --git a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests.csproj b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests.csproj index f286ad51..5b6e1170 100644 --- a/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests.csproj +++ b/test/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests/Savvyio.Extensions.DependencyInjection.RabbitMQ.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/test/Savvyio.Extensions.Dispatchers.Tests/Savvyio.Extensions.Dispatchers.Tests.csproj b/test/Savvyio.Extensions.Dispatchers.Tests/Savvyio.Extensions.Dispatchers.Tests.csproj index e6f65113..86ad7ef1 100644 --- a/test/Savvyio.Extensions.Dispatchers.Tests/Savvyio.Extensions.Dispatchers.Tests.csproj +++ b/test/Savvyio.Extensions.Dispatchers.Tests/Savvyio.Extensions.Dispatchers.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.Dispatchers diff --git a/test/Savvyio.Extensions.EFCore.Tests/Savvyio.Extensions.EFCore.Tests.csproj b/test/Savvyio.Extensions.EFCore.Tests/Savvyio.Extensions.EFCore.Tests.csproj index 5630ca53..1aa5063b 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/Savvyio.Extensions.EFCore.Tests.csproj +++ b/test/Savvyio.Extensions.EFCore.Tests/Savvyio.Extensions.EFCore.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.EFCore diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj index b4ea1ca2..01ce4ce3 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.QueueStorage diff --git a/test/Savvyio.Extensions.QueueStorage.Tests/Savvyio.Extensions.QueueStorage.Tests.csproj b/test/Savvyio.Extensions.QueueStorage.Tests/Savvyio.Extensions.QueueStorage.Tests.csproj index 1721dc39..824ad05b 100644 --- a/test/Savvyio.Extensions.QueueStorage.Tests/Savvyio.Extensions.QueueStorage.Tests.csproj +++ b/test/Savvyio.Extensions.QueueStorage.Tests/Savvyio.Extensions.QueueStorage.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.QueueStorage diff --git a/test/Savvyio.Extensions.RabbitMQ.Tests/Savvyio.Extensions.RabbitMQ.Tests.csproj b/test/Savvyio.Extensions.RabbitMQ.Tests/Savvyio.Extensions.RabbitMQ.Tests.csproj index a98d7561..0e0661db 100644 --- a/test/Savvyio.Extensions.RabbitMQ.Tests/Savvyio.Extensions.RabbitMQ.Tests.csproj +++ b/test/Savvyio.Extensions.RabbitMQ.Tests/Savvyio.Extensions.RabbitMQ.Tests.csproj @@ -3,7 +3,7 @@ Savvyio.Extensions.RabbitMQ - + @@ -17,5 +17,5 @@ - + diff --git a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj index 76211483..0ca44ebc 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj +++ b/test/Savvyio.Extensions.SimpleQueueService.FunctionalTests/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.SimpleQueueService @@ -17,5 +17,5 @@ - + diff --git a/test/Savvyio.Extensions.SimpleQueueService.Tests/Savvyio.Extensions.SimpleQueueService.Tests.csproj b/test/Savvyio.Extensions.SimpleQueueService.Tests/Savvyio.Extensions.SimpleQueueService.Tests.csproj index 2eee987f..bdead28d 100644 --- a/test/Savvyio.Extensions.SimpleQueueService.Tests/Savvyio.Extensions.SimpleQueueService.Tests.csproj +++ b/test/Savvyio.Extensions.SimpleQueueService.Tests/Savvyio.Extensions.SimpleQueueService.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.SimpleQueueService diff --git a/test/Savvyio.Extensions.Text.Json.Tests/Savvyio.Extensions.Text.Json.Tests.csproj b/test/Savvyio.Extensions.Text.Json.Tests/Savvyio.Extensions.Text.Json.Tests.csproj index d879bb94..b75ce740 100644 --- a/test/Savvyio.Extensions.Text.Json.Tests/Savvyio.Extensions.Text.Json.Tests.csproj +++ b/test/Savvyio.Extensions.Text.Json.Tests/Savvyio.Extensions.Text.Json.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Extensions.Text.Json diff --git a/test/Savvyio.FunctionalTests/Savvyio.FunctionalTests.csproj b/test/Savvyio.FunctionalTests/Savvyio.FunctionalTests.csproj index 12a5f955..0bbe5f5e 100644 --- a/test/Savvyio.FunctionalTests/Savvyio.FunctionalTests.csproj +++ b/test/Savvyio.FunctionalTests/Savvyio.FunctionalTests.csproj @@ -1,4 +1,4 @@ - + Savvyio diff --git a/test/Savvyio.Queries.Tests/Savvyio.Queries.Tests.csproj b/test/Savvyio.Queries.Tests/Savvyio.Queries.Tests.csproj index 5f1fdd55..d2cc5cf1 100644 --- a/test/Savvyio.Queries.Tests/Savvyio.Queries.Tests.csproj +++ b/test/Savvyio.Queries.Tests/Savvyio.Queries.Tests.csproj @@ -1,4 +1,4 @@ - + Savvyio.Queries From 8693d0780960ca488b164eb6fa914529971590a7 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:32:42 +0200 Subject: [PATCH 16/36] =?UTF-8?q?=F0=9F=91=B7=20add=20line=20ending=20chec?= =?UTF-8?q?k=20and=20move=20runners=20to=20ubuntu=2026.04?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new line_endings job fails the test quality gate when tracked text files are not stored with LF line endings. The CI jobs move from ubuntu-24.04 to ubuntu-26.04 to match the current runner image. --- .github/workflows/ci-pipeline.yml | 37 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 46a3a37c..82a25009 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -23,7 +23,7 @@ permissions: jobs: init: name: initialize - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 outputs: run-mac-tests: ${{ steps.vars.outputs.run-mac-tests }} run-privileged-jobs: ${{ steps.vars.outputs.run-privileged-jobs }} @@ -50,9 +50,26 @@ jobs: echo "build-switches=" >> "$GITHUB_OUTPUT" fi + line_endings: + name: 📏 Line Endings + runs-on: ubuntu-26.04 + steps: + - name: Checkout + uses: codebeltnet/git-checkout@v1 + + - name: Require LF line endings for tracked text files + shell: bash + run: | + violations=$(git ls-files --eol | awk '$1 != "i/lf" && $1 != "i/-text" && $1 != "i/none" { print }') + if [[ -n "$violations" ]]; then + echo "$violations" + echo "::error::Tracked text files must use LF line endings (see .editorconfig and .gitattributes)." + exit 1 + fi + prepare_test: name: 📜 Prepare Test - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 outputs: json: ${{ steps.test-projects.outputs.result }} steps: @@ -87,7 +104,7 @@ jobs: uses: codebeltnet/jobs-dotnet-build/.github/workflows/default.yml@v3 with: include-preview: true - runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} + runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-26.04-arm' || 'ubuntu-26.04' }} configuration: ${{ matrix.configuration }} strong-name-key-filename: ${{ needs.init.outputs.strong-name-key-filename }} build-switches: ${{ needs.init.outputs.build-switches }} @@ -119,7 +136,7 @@ jobs: uses: codebeltnet/jobs-dotnet-test/.github/workflows/default.yml@v3 with: include-preview: true - runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} + runs-on: ${{ matrix.arch == 'ARM64' && 'ubuntu-26.04-arm' || 'ubuntu-26.04' }} configuration: ${{ matrix.configuration }} projects: ${{ matrix.project }} build-switches: -p:SkipSignAssembly=true @@ -171,13 +188,14 @@ jobs: test_qualitygate: if: ${{ always() }} name: test-qualitygate - needs: [init, test_linux, test_windows, test_mac] - runs-on: ubuntu-24.04 + needs: [init, line_endings, test_linux, test_windows, test_mac] + runs-on: ubuntu-26.04 steps: - name: Evaluate test results shell: bash env: RUN_MAC_TESTS: ${{ needs.init.outputs.run-mac-tests }} + LINE_ENDINGS_RESULT: ${{ needs.line_endings.result }} TEST_LINUX_RESULT: ${{ needs.test_linux.result }} TEST_WINDOWS_RESULT: ${{ needs.test_windows.result }} TEST_MAC_RESULT: ${{ needs.test_mac.result }} @@ -208,6 +226,7 @@ jobs: fi } + require_success "line_endings" "$LINE_ENDINGS_RESULT" require_success "test_linux" "$TEST_LINUX_RESULT" require_success "test_windows" "$TEST_WINDOWS_RESULT" require_success_or_skip "test_mac" "$RUN_MAC_TESTS" "$TEST_MAC_RESULT" @@ -219,7 +238,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-24.04, windows-2025] + os: [ubuntu-26.04, windows-2025] configuration: [Release] project: [ test/**/Savvyio.FunctionalTests.csproj, test/**/Savvyio.Extensions.SimpleQueueService.FunctionalTests.csproj, test/**/Savvyio.Extensions.QueueStorage.FunctionalTests.csproj ] runs-on: ${{ matrix.os }} @@ -261,7 +280,7 @@ jobs: integration_test_rabbitmq: name: ⚗️ Integration Test - RabbitMQ needs: [build] - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 15 steps: - name: Checkout @@ -312,7 +331,7 @@ jobs: integration_test_nats: name: ⚗️ Integration Test - NATS needs: [build] - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 15 steps: - name: Checkout From 436e9ca6dfcda6a5dcdd378bd4279d0db649f02a Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:32:46 +0200 Subject: [PATCH 17/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20switch=20assembly=20?= =?UTF-8?q?scanning=20to=20cuemon=20assembly=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Savvyio's own AssemblyContext duplicated the scanning logic now provided by Cuemon. The dispatcher, handler, and cloud event converters use Cuemon's implementation and exclude the Savvyio core assembly from brute-force scanning. --- .../SavvyioOptionsExtensions.cs | 6 +++--- .../Converters/MessageConverter.cs | 4 ++-- .../Converters/MessageConverter.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs index aaa83f2b..e1d90c70 100644 --- a/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs +++ b/src/Savvyio.Extensions.Dispatchers/SavvyioOptionsExtensions.cs @@ -5,8 +5,8 @@ using Savvyio.Queries; using System.Linq; using System.Reflection; -using Savvyio.Reflection; using System.Runtime.CompilerServices; +using Cuemon.Reflection; namespace Savvyio.Extensions; @@ -43,7 +43,7 @@ public static SavvyioOptions UseAutomaticDispatcherDiscovery(this SavvyioOptions { if (bruteAssemblyScanning) { - options.AddDispatchers(AssemblyContext.CurrentDomainAssemblies.ToArray()); + options.AddDispatchers(AssemblyContext.GetCurrentDomainAssemblies(o => o.ExcludedAssemblies.Add(typeof(SavvyioOptions).Assembly)).ToArray()); } else { @@ -63,7 +63,7 @@ public static SavvyioOptions UseAutomaticHandlerDiscovery(this SavvyioOptions op { if (bruteAssemblyScanning) { - options.AddHandlers(AssemblyContext.CurrentDomainAssemblies.ToArray()); + options.AddHandlers(AssemblyContext.GetCurrentDomainAssemblies(o => o.ExcludedAssemblies.Add(typeof(SavvyioOptions).Assembly)).ToArray()); } else { diff --git a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs index 72fd86de..c4bae6ea 100644 --- a/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Newtonsoft.Json/Converters/MessageConverter.cs @@ -4,6 +4,7 @@ using System.Reflection; using Cuemon.Extensions; using Codebelt.Extensions.Newtonsoft.Json; +using Cuemon.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Savvyio.EventDriven; @@ -11,7 +12,6 @@ using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; using Savvyio.Messaging; using Savvyio.Messaging.Cryptography; -using Savvyio.Reflection; namespace Savvyio.Extensions.Newtonsoft.Json.Converters; @@ -21,7 +21,7 @@ namespace Savvyio.Extensions.Newtonsoft.Json.Converters; /// public class MessageConverter : JsonConverter { - internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && + internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.GetCurrentDomainAssemblies(o => o.ExcludedAssemblies.Add(typeof(IMessage<>).Assembly)).SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && ti is { IsAbstract: false, IsInterface: false })).ToList()); /// diff --git a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs index c9e464cd..0b2a1afb 100644 --- a/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs +++ b/src/Savvyio.Extensions.Text.Json/Converters/MessageConverter.cs @@ -7,12 +7,12 @@ using Cuemon.Extensions; using Cuemon.Extensions.Reflection; using Cuemon.Extensions.Text.Json; +using Cuemon.Reflection; using Savvyio.EventDriven; using Savvyio.EventDriven.Messaging.CloudEvents; using Savvyio.EventDriven.Messaging.CloudEvents.Cryptography; using Savvyio.Messaging; using Savvyio.Messaging.Cryptography; -using Savvyio.Reflection; namespace Savvyio.Extensions.Text.Json.Converters; @@ -22,7 +22,7 @@ namespace Savvyio.Extensions.Text.Json.Converters; /// public class MessageConverter : JsonConverterFactory { - internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.CurrentDomainAssemblies.SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && + internal static readonly Lazy> CloudEventTypes = new(() => AssemblyContext.GetCurrentDomainAssemblies(o => o.ExcludedAssemblies.Add(typeof(IMessage<>).Assembly)).SelectMany(a => a.DefinedTypes.Where(ti => ti.HasInterfaces(typeof(ICloudEvent<>)) && ti is { IsAbstract: false, IsInterface: false })).ToList()); /// From 548da28df115122d432cd6c7e7231ee849583ece Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 24 Oct 2026 05:32:51 +0200 Subject: [PATCH 18/36] =?UTF-8?q?=F0=9F=94=A5=20remove=20savvyio=20assembl?= =?UTF-8?q?y=20context=20and=20its=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assembly scanning now uses Cuemon's AssemblyContext, so the Savvyio.Reflection copy is no longer needed. Its tests are rewritten against the Cuemon implementation. --- .../Reflection/AssemblyContext.cs | 174 ---------- .../Reflection/AssemblyContextBehaviorTest.cs | 323 ++++++++++++------ .../Reflection/AssemblyContextTest.cs | 189 +++++----- 3 files changed, 301 insertions(+), 385 deletions(-) delete mode 100644 src/Savvyio.Core/Reflection/AssemblyContext.cs diff --git a/src/Savvyio.Core/Reflection/AssemblyContext.cs b/src/Savvyio.Core/Reflection/AssemblyContext.cs deleted file mode 100644 index d7c187fe..00000000 --- a/src/Savvyio.Core/Reflection/AssemblyContext.cs +++ /dev/null @@ -1,174 +0,0 @@ -using Cuemon.Extensions.Collections.Generic; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Cuemon; - -namespace Savvyio.Reflection; - - - - - - -/// -/// Provides a set of static methods and properties to manage and filter assemblies in the current application domain. -/// - public static class AssemblyContext -{ - private static readonly Lazy> AssemblyLoadFactory = new(() => AppDomain - .CurrentDomain - .GetAssemblies() - .Where(AssemblyFilterCallback) - .SelectMany(AssemblyDependenciesCallback) - .Distinct() - .Except(typeof(AssemblyContext).Assembly.Yield()) - .ToList() - .AsReadOnly()); - - private static Func _assemblyFilterCallback = DefaultAssemblyFilter; - private static Func> _assemblyDependenciesCallback = DefaultAssemblyDependencies; - private static Func _assemblyDependenciesFilterCallback = DefaultAssemblyDependenciesFilter; - - - - - - - - - - - - - - - - - - /// - /// Gets or sets the function delegate that filters assemblies from the current application domain. - /// - /// The function delegate that filters assemblies from the current application domain. - /// The default implementation filters away assemblies that suggest being part of the .NET runtime themselves. - /// - /// cannot be null. - /// - public static Func AssemblyFilterCallback - { - get => _assemblyFilterCallback; - set => _assemblyFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); - } - - - - - - - - - - - - - - - - /// - /// Gets or sets the function delegate that recursively discover dependencies for an assembly in the current application domain. - /// - /// The function delegate that recursively discover dependencies for an assembly in the current application domain. - /// - /// cannot be null. - /// - public static Func> AssemblyDependenciesCallback - { - get => _assemblyDependenciesCallback; - set => _assemblyDependenciesCallback = value ?? throw new ArgumentNullException(nameof(value)); - } - - - - - - - - - - - - - - - - - - /// - /// Gets or sets the function delegate that filters assembly dependencies from the current application domain. - /// - /// The function delegate that filters assembly dependencies from the current application domain. - /// The default implementation filters away assembly dependencies that suggest being part of the .NET runtime themselves. - /// - /// cannot be null. - /// - public static Func AssemblyDependenciesFilterCallback - { - get => _assemblyDependenciesFilterCallback; - set => _assemblyDependenciesFilterCallback = value ?? throw new ArgumentNullException(nameof(value)); - } - - - - - - - - - - - - /// - /// Gets the qualified assemblies from the current application domain. - /// - /// The qualified assemblies from the current application domain. - /// This result of this property is coupled with and . - public static IReadOnlyList CurrentDomainAssemblies => AssemblyLoadFactory.Value; - - private static bool DefaultAssemblyFilter(Assembly assembly) - { - return assembly.FullName != null && - !assembly.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && - !assembly.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); - } - - private static bool DefaultAssemblyDependenciesFilter(AssemblyName assemblyName) - { - return !assemblyName.FullName.StartsWith(nameof(System), StringComparison.Ordinal) && - !assemblyName.FullName.StartsWith(nameof(Microsoft), StringComparison.Ordinal); - } - - private static IEnumerable DefaultAssemblyDependencies(Assembly assembly) - { - var stack = new Stack(); - var guard = new HashSet(); - - yield return assembly; - - stack.Push(assembly); - guard.Add(assembly.FullName); - - while (stack.TryPop(out var assemblyToTraverse)) - { - foreach (var assemblyName in assemblyToTraverse.GetReferencedAssemblies().Where(AssemblyDependenciesFilterCallback)) - { - if (!guard.Add(assemblyName.FullName)) { continue; } - if (Patterns.TryInvoke(() => Assembly.Load(assemblyName), out var referencedAssembly) && referencedAssembly != null) - { - stack.Push(referencedAssembly); - yield return referencedAssembly; - } - } - } - } -} diff --git a/test/Savvyio.Core.Tests/Reflection/AssemblyContextBehaviorTest.cs b/test/Savvyio.Core.Tests/Reflection/AssemblyContextBehaviorTest.cs index a586f8e1..8926efe5 100644 --- a/test/Savvyio.Core.Tests/Reflection/AssemblyContextBehaviorTest.cs +++ b/test/Savvyio.Core.Tests/Reflection/AssemblyContextBehaviorTest.cs @@ -1,15 +1,20 @@ #nullable enable using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; using System.Runtime.Loader; using Codebelt.Extensions.Xunit; using Cuemon; +using Savvyio; using Savvyio.Commands; using Xunit; -namespace Savvyio.Reflection; +namespace Cuemon.Reflection; public class AssemblyContextBehaviorTest : Test { @@ -19,212 +24,304 @@ public AssemblyContextBehaviorTest(ITestOutputHelper output) : base(output) [Theory] [InlineData(null, false)] + [InlineData("", false)] [InlineData("System.Application", false)] [InlineData("Microsoft.Application", false)] [InlineData("Application.System", true)] [InlineData("system.Application", true)] [InlineData("microsoft.Application", true)] - public void AssemblyFilterCallback_ShouldUseOrdinalPrefixFiltering(string? fullName, bool expected) + public void AssemblyFilter_ShouldUseOrdinalPrefixFiltering(string? fullName, bool expected) { - using var context = new IsolatedAssemblyContext(); + Assert.Equal(expected, new AssemblyContextOptions().AssemblyFilter(new ExportedTypesAssembly(fullName))); + } - Assert.Equal(expected, context.AssemblyFilter(new ReferencedAssembly(fullName))); + [Fact] + public void AssemblyFilter_ShouldRejectNullAssembly() + { + Assert.False(new AssemblyContextOptions().AssemblyFilter(null!)); } [Theory] + [InlineData(null, false)] [InlineData("System.Application", false)] [InlineData("Microsoft.Application", false)] [InlineData("Application.System", true)] [InlineData("system.Application", true)] [InlineData("microsoft.Application", true)] - public void AssemblyDependenciesFilterCallback_ShouldUseOrdinalPrefixFiltering(string name, bool expected) + public void ReferencedAssemblyFilter_ShouldUseOrdinalPrefixFiltering(string? name, bool expected) { - using var context = new IsolatedAssemblyContext(); + var assemblyName = name is null ? null : new AssemblyName(name); - Assert.Equal(expected, context.ReferenceFilter(new AssemblyName(name))); + Assert.Equal(expected, new AssemblyContextOptions().ReferencedAssemblyFilter(assemblyName!)); } [Theory] - [InlineData(nameof(AssemblyContext.AssemblyFilterCallback))] - [InlineData(nameof(AssemblyContext.AssemblyDependenciesCallback))] - [InlineData(nameof(AssemblyContext.AssemblyDependenciesFilterCallback))] - public void Callback_ShouldRejectNullAndPreservePreviousDelegate(string propertyName) + [InlineData(typeof(string), false)] + [InlineData(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException), false)] + [InlineData(typeof(SavvyioOptions), true)] + public void AssemblyFilter_ShouldInspectExportedRootNamespaces(Type exportedType, bool expected) { - using var context = new IsolatedAssemblyContext(); - var property = context.Type.GetProperty(propertyName)!; - var original = property.GetValue(null); + var assembly = new ExportedTypesAssembly($"Application.NamespaceFilter.{exportedType.FullName}", () => [exportedType]); - var error = Assert.Throws(() => property.SetValue(null, null)); + Assert.Equal(expected, new AssemblyContextOptions().AssemblyFilter(assembly)); + } + + [Theory] + [InlineData(typeof(string), false)] + [InlineData(typeof(SavvyioOptions), true)] + public void AssemblyFilter_ShouldInspectLoadableTypes_WhenSomeExportedTypesCannotLoad(Type exportedType, bool expected) + { + var assembly = new ExportedTypesAssembly($"Application.PartialLoad.{exportedType.FullName}", () => + throw new ReflectionTypeLoadException([null, exportedType], [new TypeLoadException()])); - Assert.Equal("value", Assert.IsType(error.InnerException).ParamName); - Assert.Same(original, property.GetValue(null)); + Assert.Equal(expected, new AssemblyContextOptions().AssemblyFilter(assembly)); } [Fact] - public void AssemblyDependenciesCallback_ShouldTraverseTransitiveReferences() + public void AssemblyFilter_ShouldAllowAssembly_WhenExportedTypeScanHasRecoverableFailure() + { + var assembly = new ExportedTypesAssembly("Application.RecoverableTypeScanFailure", () => throw new NotSupportedException()); + + Assert.True(new AssemblyContextOptions().AssemblyFilter(assembly)); + } + + [Fact] + public void AssemblyFilter_ShouldAllowAssembly_WhenExportedTypesAreUnavailable() + { + var assembly = new ExportedTypesAssembly("Application.UnavailableExportedTypes", () => null!); + + Assert.True(new AssemblyContextOptions().AssemblyFilter(assembly)); + } + + [Fact] + public void GetCurrentDomainAssemblies_ShouldTraverseTransitiveReferences() { - using var context = new IsolatedAssemblyContext(); var root = typeof(Command).Assembly; - var core = typeof(AssemblyContext).Assembly; - var transitive = typeof(Cuemon.Reflection.AssemblyContext).Assembly; + var core = typeof(SavvyioOptions).Assembly; + var transitive = typeof(AssemblyContext).Assembly; // Commands references Savvyio.Core, which in turn references Cuemon.Core. Assert.DoesNotContain(root.GetReferencedAssemblies(), name => name.FullName == transitive.FullName); - var assemblies = context.Dependencies(root).ToList(); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.ExcludedAssemblies.Clear(); + }); - Assert.Equal(root, assemblies[0]); - Assert.Contains(assemblies, assembly => assembly.FullName == core.FullName); - Assert.Contains(assemblies, assembly => assembly.FullName == transitive.FullName); + Assert.Same(root, assemblies[0]); + Assert.Contains(core, assemblies); + Assert.Contains(transitive, assemblies); Assert.Equal(assemblies.Count, assemblies.Distinct().Count()); Assert.DoesNotContain(assemblies, assembly => assembly.FullName!.StartsWith("System", StringComparison.Ordinal)); Assert.DoesNotContain(assemblies, assembly => assembly.FullName!.StartsWith("Microsoft", StringComparison.Ordinal)); } [Fact] - public void AssemblyDependenciesCallback_ShouldSkipSelfReferencesAndDuplicates() + public void GetCurrentDomainAssemblies_ShouldSkipSelfReferencesAndDuplicates() { - using var context = new IsolatedAssemblyContext(); var dependency = typeof(Validator).Assembly; - var root = new ReferencedAssembly("Application.Root", new AssemblyName("Application.Root"), dependency.GetName(), dependency.GetName()); - context.ReferenceFilter = name => name.Name is "Application.Root" or "Cuemon.Kernel"; + var rootName = new AssemblyName("Savvyio.Tests.AssemblyContext.SelfReferences") { Version = new Version(1, 0, 0, 0) }; + using var fixture = new ReferencedAssemblyFixture(rootName, rootName, dependency.GetName(), dependency.GetName()); + var root = fixture.Assembly; + var inspected = new List(); + Assert.Equal(3, root.GetReferencedAssemblies().Length); + Assert.Equal(root.FullName, root.GetReferencedAssemblies()[0].FullName); + + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.ReferencedAssemblyFilter = name => + { + inspected.Add(name); + return name.FullName == root.FullName || name.FullName == dependency.FullName; + }; + }); - Assert.Equal(new Assembly[] { root, dependency }, context.Dependencies(root)); + Assert.Equal(new[] { root, dependency }, assemblies); + Assert.Equal(root.GetReferencedAssemblies().Concat(dependency.GetReferencedAssemblies()).Select(name => name.FullName), + inspected.Select(name => name.FullName)); } [Fact] - public void AssemblyDependenciesCallback_ShouldContinueAfterUnresolvableReference() + public void GetCurrentDomainAssemblies_ShouldContinueAfterUnresolvableReference() { - using var context = new IsolatedAssemblyContext(); var dependency = typeof(Validator).Assembly; - var root = new ReferencedAssembly("Application.Root", new AssemblyName("Savvyio.Tests.NonexistentDependency.8d9b24a2"), dependency.GetName()); - context.ReferenceFilter = name => name.Name == "Savvyio.Tests.NonexistentDependency.8d9b24a2" || name.FullName == dependency.FullName; + var missing = new AssemblyName("Savvyio.Tests.NonexistentDependency.8d9b24a2"); + using var fixture = new ReferencedAssemblyFixture(new AssemblyName("Savvyio.Tests.AssemblyContext.MissingReference"), missing, dependency.GetName()); + var root = fixture.Assembly; + + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.ReferencedAssemblyFilter = name => name.Name == missing.Name || name.FullName == dependency.FullName; + }); - Assert.Equal(new Assembly[] { root, dependency }, context.Dependencies(root)); + Assert.Equal(new[] { root, dependency }, assemblies); } [Fact] - public void AssemblyDependenciesCallback_ShouldApplyCustomFilterWithoutFilteringRoot() + public void GetCurrentDomainAssemblies_ShouldApplyReferenceFilterWithoutFilteringRoot() { - using var context = new IsolatedAssemblyContext(); var root = typeof(Command).Assembly; var inspected = new List(); - context.ReferenceFilter = name => - { - inspected.Add(name); - return false; - }; - Assert.Same(root, Assert.Single(context.Dependencies(root))); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.ReferencedAssemblyFilter = name => + { + inspected.Add(name); + return false; + }; + }); + + Assert.Same(root, Assert.Single(assemblies)); Assert.Equal(root.GetReferencedAssemblies().Select(name => name.FullName), inspected.Select(name => name.FullName)); } [Fact] - public void CurrentDomainAssemblies_ShouldFilterExpandDeduplicateAndExcludeOwnAssembly() + public void GetCurrentDomainAssemblies_ShouldFilterExpandDeduplicateAndExcludeInfrastructureAssemblies() { - using var context = new IsolatedAssemblyContext(); - var root = typeof(AssemblyContextBehaviorTest).Assembly; var dependency = typeof(Command).Assembly; + var savvyioCore = typeof(SavvyioOptions).Assembly; + var cuemonCore = typeof(AssemblyContext).Assembly; + using var fixture = new ReferencedAssemblyFixture(new AssemblyName("Savvyio.Tests.AssemblyContext.SharedReferences"), + dependency.GetName(), dependency.GetName(), savvyioCore.GetName(), cuemonCore.GetName()); + var root = fixture.Assembly; var expanded = new List(); - context.AssemblyFilter = assembly => assembly == root; - context.Dependencies = assembly => - { - expanded.Add(assembly); - return [assembly, dependency, dependency, context.Type.Assembly]; - }; - var assemblies = context.CurrentDomainAssemblies; - - Assert.Same(root, Assert.Single(expanded)); - Assert.Equal(new[] { root, dependency }, assemblies); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => + { + if (assembly != root && assembly != dependency) { return false; } + expanded.Add(assembly); + return true; + }; + options.ReferencedAssemblyFilter = name => name.FullName == dependency.FullName || + name.FullName == savvyioCore.FullName || name.FullName == cuemonCore.FullName; + options.ExcludedAssemblies.Add(savvyioCore); + }); + + Assert.Equal(2, expanded.Count); + Assert.Contains(root, expanded); + Assert.Contains(dependency, expanded); + Assert.Equal(2, assemblies.Count); + Assert.Contains(root, assemblies); + Assert.Contains(dependency, assemblies); + Assert.DoesNotContain(savvyioCore, assemblies); + Assert.DoesNotContain(cuemonCore, assemblies); Assert.Throws(() => ((IList)assemblies).Add(root)); } [Fact] - public void CurrentDomainAssemblies_ShouldCacheFirstResultDespiteCallbackChanges() + public void GetCurrentDomainAssemblies_ShouldSkipTraversal_WhenReferencesAreDisabled() { - using var context = new IsolatedAssemblyContext(); - var root = typeof(AssemblyContextBehaviorTest).Assembly; - context.AssemblyFilter = assembly => assembly == root; - context.Dependencies = assembly => [assembly]; - var first = context.CurrentDomainAssemblies; + var root = typeof(Command).Assembly; - context.AssemblyFilter = _ => throw new InvalidOperationException("Must not rescan."); - context.Dependencies = _ => throw new InvalidOperationException("Must not traverse again."); - context.ReferenceFilter = _ => throw new InvalidOperationException("Must not refilter."); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.IncludeReferencedAssemblies = false; + options.ReferencedAssemblyFilter = _ => throw new InvalidOperationException("Must not traverse references."); + }); - Assert.Same(first, context.CurrentDomainAssemblies); - Assert.Same(root, Assert.Single(first)); + Assert.Same(root, Assert.Single(assemblies)); } [Fact] - public void CurrentDomainAssemblies_ShouldAllowEmptyResult() + public void GetCurrentDomainAssemblies_ShouldUseFreshOptionsAndResultsForEachCall() { - using var context = new IsolatedAssemblyContext(); - context.AssemblyFilter = _ => false; - context.Dependencies = _ => throw new InvalidOperationException("No assembly passed the filter."); + var firstRoot = typeof(Command).Assembly; + var secondRoot = typeof(SavvyioOptions).Assembly; + var first = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == firstRoot; + options.IncludeReferencedAssemblies = false; + options.ExcludedAssemblies.Add(secondRoot); + }); + + var second = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == secondRoot; + options.ReferencedAssemblyFilter = _ => false; + }); - Assert.Empty(context.CurrentDomainAssemblies); + Assert.NotSame(first, second); + Assert.Same(firstRoot, Assert.Single(first)); + Assert.Same(secondRoot, Assert.Single(second)); } [Fact] - public void CurrentDomainAssemblies_ShouldCacheCallbackFailure() + public void GetCurrentDomainAssemblies_ShouldAllowEmptyResult() { - using var context = new IsolatedAssemblyContext(); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = _ => false; + options.ReferencedAssemblyFilter = _ => throw new InvalidOperationException("No assembly passed the filter."); + }); + + Assert.Empty(assemblies); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void GetCurrentDomainAssemblies_ShouldPropagateFilterFailureWithoutCachingIt(bool failReferenceFilter) + { + var root = typeof(Command).Assembly; var expected = new InvalidOperationException("Assembly filter failed."); - context.AssemblyFilter = _ => throw expected; - var first = Assert.Throws(() => context.CurrentDomainAssemblies); - context.AssemblyFilter = _ => false; - var second = Assert.Throws(() => context.CurrentDomainAssemblies); + var error = Assert.Throws(() => AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => failReferenceFilter ? assembly == root : throw expected; + options.ReferencedAssemblyFilter = _ => throw expected; + })); + var next = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.IncludeReferencedAssemblies = false; + }); - Assert.Same(expected, first.InnerException); - Assert.Same(expected, second.InnerException); + Assert.Same(expected, error); + Assert.Same(root, Assert.Single(next)); } - private sealed class ReferencedAssembly(string? fullName, params AssemblyName[] references) : Assembly + private sealed class ExportedTypesAssembly(string? fullName, Func? exportedTypes = null) : Assembly { public override string? FullName => fullName; - public override AssemblyName[] GetReferencedAssemblies() => references; + public override Type[] GetExportedTypes() => exportedTypes is null ? [typeof(SavvyioOptions)] : exportedTypes(); } - // A separate load context gives each test fresh static callbacks and Lazy state. - // This avoids resetting private fields or changing the application's global scan. - private sealed class IsolatedAssemblyContext : IDisposable + // Real in-memory metadata lets the public scanner traverse self, duplicate and missing + // references without invoking private helpers or altering global configuration. + private sealed class ReferencedAssemblyFixture : IDisposable { private readonly AssemblyLoadContext _loadContext = new(null, isCollectible: true); - public IsolatedAssemblyContext() - { - Type = _loadContext.LoadFromAssemblyPath(typeof(AssemblyContext).Assembly.Location) - .GetType(typeof(AssemblyContext).FullName!, throwOnError: true)!; - } - - public Type Type { get; } - - public Func AssemblyFilter - { - get => Get>(nameof(AssemblyContext.AssemblyFilterCallback)); - set => Set(nameof(AssemblyContext.AssemblyFilterCallback), value); - } - - public Func> Dependencies + public ReferencedAssemblyFixture(AssemblyName name, params AssemblyName[] references) { - get => Get>>(nameof(AssemblyContext.AssemblyDependenciesCallback)); - set => Set(nameof(AssemblyContext.AssemblyDependenciesCallback), value); + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString(name.Name!), default, default, default); + metadata.AddAssembly(metadata.GetOrAddString(name.Name!), name.Version ?? new Version(1, 0, 0, 0), + default, default, default, default); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), + default, MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + foreach (var reference in references) + { + metadata.AddAssemblyReference(metadata.GetOrAddString(reference.Name!), reference.Version ?? new Version(1, 0, 0, 0), + metadata.GetOrAddString(reference.CultureName ?? ""), metadata.GetOrAddBlob(reference.GetPublicKeyToken() ?? []), + default, default); + } + var image = new BlobBuilder(); + new ManagedPEBuilder(new PEHeaderBuilder(imageCharacteristics: Characteristics.Dll), + new MetadataRootBuilder(metadata), new BlobBuilder()).Serialize(image); + using var stream = new MemoryStream(image.ToArray()); + Assembly = _loadContext.LoadFromStream(stream); } - public Func ReferenceFilter - { - get => Get>(nameof(AssemblyContext.AssemblyDependenciesFilterCallback)); - set => Set(nameof(AssemblyContext.AssemblyDependenciesFilterCallback), value); - } - - public IReadOnlyList CurrentDomainAssemblies => Get>(nameof(AssemblyContext.CurrentDomainAssemblies)); - - private T Get(string name) => (T)Type.GetProperty(name)!.GetValue(null)!; - - private void Set(string name, object value) => Type.GetProperty(name)!.SetValue(null, value); + public Assembly Assembly { get; } public void Dispose() => _loadContext.Unload(); } diff --git a/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs b/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs index 8da5005d..2a5e09db 100644 --- a/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs +++ b/test/Savvyio.Core.Tests/Reflection/AssemblyContextTest.cs @@ -1,11 +1,11 @@ +#nullable enable using System; -using System.Linq; using System.Reflection; using Codebelt.Extensions.Xunit; -using Savvyio.Reflection; +using Savvyio; using Xunit; -namespace Savvyio.Reflection; +namespace Cuemon.Reflection; public class AssemblyContextTest : Test { @@ -14,171 +14,164 @@ public AssemblyContextTest(ITestOutputHelper output) : base(output) } [Fact] - public void CurrentDomainAssemblies_ShouldReturnNonEmptyList() + public void GetCurrentDomainAssemblies_ShouldReturnNonEmptyList() { - var assemblies = AssemblyContext.CurrentDomainAssemblies; + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(); Assert.NotNull(assemblies); Assert.NotEmpty(assemblies); + Assert.Contains(typeof(AssemblyContextTest).Assembly, assemblies); } [Fact] - public void CurrentDomainAssemblies_ShouldNotContainSavvyioCoreAssembly() + public void GetCurrentDomainAssemblies_ShouldExcludeCuemonCoreByDefault() { - var savvyioCoreAssembly = typeof(AssemblyContext).Assembly; + Assert.DoesNotContain(typeof(AssemblyContext).Assembly, AssemblyContext.GetCurrentDomainAssemblies()); + } + + [Fact] + public void GetCurrentDomainAssemblies_ShouldExcludeSavvyioCore_WhenConfigured() + { + var savvyioCore = typeof(SavvyioOptions).Assembly; - Assert.DoesNotContain(savvyioCoreAssembly, AssemblyContext.CurrentDomainAssemblies); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == savvyioCore; + options.ExcludedAssemblies.Add(savvyioCore); + }); + + Assert.DoesNotContain(savvyioCore, assemblies); + Assert.DoesNotContain(typeof(AssemblyContext).Assembly, assemblies); } [Fact] - public void CurrentDomainAssemblies_ShouldNotContainSystemOrMicrosoftAssemblies() + public void GetCurrentDomainAssemblies_ShouldNotContainSystemOrMicrosoftAssemblies() { - foreach (var assembly in AssemblyContext.CurrentDomainAssemblies) + Assert.All(AssemblyContext.GetCurrentDomainAssemblies(), assembly => { Assert.False(assembly.FullName?.StartsWith(nameof(System), StringComparison.Ordinal), $"Assembly '{assembly.FullName}' should have been filtered out."); Assert.False(assembly.FullName?.StartsWith(nameof(Microsoft), StringComparison.Ordinal), $"Assembly '{assembly.FullName}' should have been filtered out."); - } + }); } [Fact] - public void AssemblyFilterCallback_ShouldReturnDefaultNonNullDelegate() + public void AssemblyContextOptions_ShouldHaveValidDefaults() { - var callback = AssemblyContext.AssemblyFilterCallback; + var options = new AssemblyContextOptions(); - Assert.NotNull(callback); + Assert.True(options.IncludeReferencedAssemblies); + Assert.NotNull(options.AssemblyFilter); + Assert.NotNull(options.ReferencedAssemblyFilter); + Assert.Equal(new[] { typeof(AssemblyContext).Assembly }, options.ExcludedAssemblies); + options.ValidateOptions(); } [Fact] - public void AssemblyFilterCallback_ShouldAcceptCustomDelegate() + public void AssemblyFilter_ShouldAcceptCustomDelegate() { - var original = AssemblyContext.AssemblyFilterCallback; - try - { - Func custom = _ => true; - AssemblyContext.AssemblyFilterCallback = custom; + var options = new AssemblyContextOptions(); + Func custom = _ => true; - Assert.Same(custom, AssemblyContext.AssemblyFilterCallback); - } - finally - { - AssemblyContext.AssemblyFilterCallback = original; - } - } + options.AssemblyFilter = custom; - [Fact] - public void AssemblyFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() - { - Assert.Throws(() => AssemblyContext.AssemblyFilterCallback = null); + Assert.Same(custom, options.AssemblyFilter); + options.ValidateOptions(); } [Fact] - public void AssemblyDependenciesCallback_ShouldReturnDefaultNonNullDelegate() + public void ReferencedAssemblyFilter_ShouldAcceptCustomDelegate() { - var callback = AssemblyContext.AssemblyDependenciesCallback; + var options = new AssemblyContextOptions(); + Func custom = _ => true; + + options.ReferencedAssemblyFilter = custom; - Assert.NotNull(callback); + Assert.Same(custom, options.ReferencedAssemblyFilter); + options.ValidateOptions(); } [Fact] - public void AssemblyDependenciesCallback_ShouldAcceptCustomDelegate() + public void AssemblyContextOptions_ShouldKeepConfigurationLocalToEachInstance() { - var original = AssemblyContext.AssemblyDependenciesCallback; - try + var first = new AssemblyContextOptions { - Func> custom = a => Enumerable.Repeat(a, 1); - AssemblyContext.AssemblyDependenciesCallback = custom; + AssemblyFilter = _ => false, + ReferencedAssemblyFilter = _ => false, + IncludeReferencedAssemblies = false + }; + first.ExcludedAssemblies.Clear(); + var second = new AssemblyContextOptions(); - Assert.Same(custom, AssemblyContext.AssemblyDependenciesCallback); - } - finally - { - AssemblyContext.AssemblyDependenciesCallback = original; - } + Assert.NotSame(first.AssemblyFilter, second.AssemblyFilter); + Assert.NotSame(first.ReferencedAssemblyFilter, second.ReferencedAssemblyFilter); + Assert.True(second.IncludeReferencedAssemblies); + Assert.Equal(new[] { typeof(AssemblyContext).Assembly }, second.ExcludedAssemblies); } - [Fact] - public void AssemblyDependenciesCallback_ShouldThrowArgumentNullException_WhenAssignedNull() + [Theory] + [InlineData(nameof(AssemblyContextOptions.AssemblyFilter))] + [InlineData(nameof(AssemblyContextOptions.ReferencedAssemblyFilter))] + [InlineData(nameof(AssemblyContextOptions.ExcludedAssemblies))] + public void ValidateOptions_ShouldRejectNullConfiguration(string propertyName) { - Assert.Throws(() => AssemblyContext.AssemblyDependenciesCallback = null); - } + var options = new AssemblyContextOptions(); + typeof(AssemblyContextOptions).GetProperty(propertyName)!.SetValue(options, null); - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldReturnDefaultNonNullDelegate() - { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; + var error = Assert.Throws(options.ValidateOptions); - Assert.NotNull(callback); + Assert.Contains(propertyName, error.Message); } - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldAcceptCustomDelegate() + [Theory] + [InlineData(nameof(AssemblyContextOptions.AssemblyFilter))] + [InlineData(nameof(AssemblyContextOptions.ReferencedAssemblyFilter))] + [InlineData(nameof(AssemblyContextOptions.ExcludedAssemblies))] + public void GetCurrentDomainAssemblies_ShouldRejectInvalidConfiguration(string propertyName) { - var original = AssemblyContext.AssemblyDependenciesFilterCallback; - try - { - Func custom = _ => true; - AssemblyContext.AssemblyDependenciesFilterCallback = custom; - - Assert.Same(custom, AssemblyContext.AssemblyDependenciesFilterCallback); - } - finally - { - AssemblyContext.AssemblyDependenciesFilterCallback = original; - } - } + var error = Assert.Throws(() => AssemblyContext.GetCurrentDomainAssemblies(options => + typeof(AssemblyContextOptions).GetProperty(propertyName)!.SetValue(options, null))); - [Fact] - public void AssemblyDependenciesFilterCallback_ShouldThrowArgumentNullException_WhenAssignedNull() - { - Assert.Throws(() => AssemblyContext.AssemblyDependenciesFilterCallback = null); + Assert.Equal("setup", error.ParamName); + Assert.Contains(propertyName, Assert.IsType(error.InnerException).Message); } [Fact] - public void AssemblyFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssembly() + public void AssemblyFilter_ShouldIncludeSavvyioAssembly() { - var callback = AssemblyContext.AssemblyFilterCallback; - var savvyioAssembly = typeof(AssemblyContext).Assembly; - - Assert.True(callback(savvyioAssembly)); + Assert.True(new AssemblyContextOptions().AssemblyFilter(typeof(SavvyioOptions).Assembly)); } [Fact] - public void AssemblyFilterCallback_DefaultFilter_ShouldExcludeSystemAssembly() + public void AssemblyFilter_ShouldExcludeSystemAssembly() { - var callback = AssemblyContext.AssemblyFilterCallback; - var systemAssembly = typeof(string).Assembly; - - Assert.False(callback(systemAssembly)); + Assert.False(new AssemblyContextOptions().AssemblyFilter(typeof(string).Assembly)); } [Fact] - public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldIncludeNonSystemAssemblyName() + public void ReferencedAssemblyFilter_ShouldIncludeSavvyioAssemblyName() { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; - var assemblyName = typeof(AssemblyContext).Assembly.GetName(); - - Assert.True(callback(assemblyName)); + Assert.True(new AssemblyContextOptions().ReferencedAssemblyFilter(typeof(SavvyioOptions).Assembly.GetName())); } [Fact] - public void AssemblyDependenciesFilterCallback_DefaultFilter_ShouldExcludeSystemAssemblyName() + public void ReferencedAssemblyFilter_ShouldExcludeSystemAssemblyName() { - var callback = AssemblyContext.AssemblyDependenciesFilterCallback; - var assemblyName = typeof(string).Assembly.GetName(); - - Assert.False(callback(assemblyName)); + Assert.False(new AssemblyContextOptions().ReferencedAssemblyFilter(typeof(string).Assembly.GetName())); } [Fact] - public void AssemblyDependenciesCallback_DefaultCallback_ShouldYieldAtLeastTheInputAssembly() + public void GetCurrentDomainAssemblies_ShouldIncludeRoot_WhenAllReferencesAreFilteredOut() { - var callback = AssemblyContext.AssemblyDependenciesCallback; - var assembly = typeof(AssemblyContext).Assembly; + var root = typeof(SavvyioOptions).Assembly; - var result = callback(assembly).ToList(); + var assemblies = AssemblyContext.GetCurrentDomainAssemblies(options => + { + options.AssemblyFilter = assembly => assembly == root; + options.ReferencedAssemblyFilter = _ => false; + }); - Assert.Contains(assembly, result); + Assert.Same(root, Assert.Single(assemblies)); } } From 10295f084c95ffd9748355ee17b4640a59015ec1 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:54:23 +0200 Subject: [PATCH 19/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20use=20cuemon=20confi?= =?UTF-8?q?gured=20options=20in=20test=20call=20sites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configured options are now provided by Cuemon's AddConfiguredOptions, so these test files import Cuemon.Extensions.DependencyInjection instead of relying on the Savvyio copy that is being removed. --- test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs | 1 + .../ServiceCollectionExtensionsTest.cs | 1 + .../Commands/NatsCommandQueueJsonSerializerContextTest.cs | 1 + .../NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs | 1 + .../EventDriven/NatsEventBusJsonSerializerContextTest.cs | 1 + .../NatsEventBusNewtonsoftJsonSerializerContextTest.cs | 1 + .../Commands/AzureCommandQueueJsonSerializerContextTest.cs | 1 + .../AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs | 1 + .../Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs | 1 + .../RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs | 1 + .../EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs | 1 + .../RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs | 1 + 12 files changed, 12 insertions(+) diff --git a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs index a58aa425..9e9450cb 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/EfCoreDataSourceTest.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit; +using Cuemon.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Savvyio.Assets; diff --git a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs index 9fedf1f3..dbba757d 100644 --- a/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.EFCore.Tests/ServiceCollectionExtensionsTest.cs @@ -1,5 +1,6 @@ using System; using Codebelt.Extensions.Xunit; +using Cuemon.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs index c3b0329d..682969ad 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueJsonSerializerContextTest.cs @@ -18,6 +18,7 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using Cuemon.Extensions.DependencyInjection; using Xunit; namespace Savvyio.Extensions.NATS.Commands; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs index dbba0585..0ddb3c23 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/Commands/NatsCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -18,6 +18,7 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using Cuemon.Extensions.DependencyInjection; using Xunit; namespace Savvyio.Extensions.NATS.Commands; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs index 47924aa3..dbe6746f 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusJsonSerializerContextTest.cs @@ -6,6 +6,7 @@ using Codebelt.Extensions.Xunit.Hosting; using Cuemon; using Cuemon.Extensions; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.IO; using Cuemon.Threading; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs index a72ce811..14040013 100644 --- a/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.NATS.FunctionalTests/EventDriven/NatsEventBusNewtonsoftJsonSerializerContextTest.cs @@ -6,6 +6,7 @@ using Codebelt.Extensions.Xunit.Hosting; using Cuemon; using Cuemon.Extensions; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.IO; using Cuemon.Threading; using Microsoft.Extensions.DependencyInjection; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs index cd7f4c65..0f39bd25 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueJsonSerializerContextTest.cs @@ -14,6 +14,7 @@ using Cuemon.Extensions.Text.Json.Formatters; using Codebelt.Extensions.Xunit; using Codebelt.Extensions.Xunit.Hosting; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; using Savvyio.Commands.Messaging; diff --git a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs index bf99ff71..1d5430ae 100644 --- a/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.QueueStorage.FunctionalTests/Commands/AzureCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -13,6 +13,7 @@ using Cuemon.Extensions.Reflection; using Codebelt.Extensions.Xunit; using Codebelt.Extensions.Xunit.Hosting; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json.Serialization; using Savvyio.Commands; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs index 944e5bb9..3455c1b3 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueJsonSerializerContextTest.cs @@ -7,6 +7,7 @@ using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.Collections.Generic; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.IO; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs index 1e6531ef..64705dfa 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/Commands/RabbitMqCommandQueueNewtonsoftJsonSerializerContextTest.cs @@ -7,6 +7,7 @@ using Cuemon; using Cuemon.Extensions; using Cuemon.Extensions.Collections.Generic; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.IO; using Microsoft.Extensions.DependencyInjection; using Savvyio.Commands; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs index 4b401a06..493e9036 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusJsonSerializerContextTest.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Threading.Channels; using System.Threading.Tasks; +using Cuemon.Extensions.DependencyInjection; using Cuemon.Extensions.IO; using Xunit; diff --git a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs index c160bd5c..519828b5 100644 --- a/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs +++ b/test/Savvyio.Extensions.RabbitMQ.FunctionalTests/EventDriven/RabbitMqEventBusNewtonsoftJsonSerializerContextTest.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Threading.Channels; using System.Threading.Tasks; +using Cuemon.Extensions.DependencyInjection; using Xunit; namespace Savvyio.Extensions.RabbitMQ.EventDriven; From d253936ac8084f5422de45b33fa51ea1c0209d54 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:54:28 +0200 Subject: [PATCH 20/36] =?UTF-8?q?=F0=9F=92=A5=20remove=20savvyio=20configu?= =?UTF-8?q?red=20options=20in=20favor=20of=20cuemon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AddConfiguredOptions now comes from Cuemon.Extensions.DependencyInjection, which shares one options instance across TOptions and IOptions. Removing the Savvyio copy is a breaking change for callers that used it from this package. --- .../ServiceCollectionExtensions.cs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs index 912e1fb1..eb670138 100644 --- a/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Savvyio.Extensions.DependencyInjection/ServiceCollectionExtensions.cs @@ -17,30 +17,6 @@ namespace Savvyio.Extensions.DependencyInjection; /// public static class ServiceCollectionExtensions { - /// - /// Registers the specified as a triple-configuration for both compatibility with (and outside the confines of) Microsoft Dependency Injection e.g., IOptions<TOptions>, Action<TOptions> and TOptions. - /// - /// The options type to be configured. - /// The to add the services to. - /// The which need to be configured by the delegate. - /// A reference to so that additional calls can be chained. - /// - /// cannot be null -or- - /// cannot be null. - /// - /// - /// are not in a valid state. - /// - public static IServiceCollection AddConfiguredOptions(this IServiceCollection services, Action setup) where TOptions : class, IParameterObject, new() - { - Validator.ThrowIfNull(services); - Validator.ThrowIfInvalidConfigurator(setup, out var options); - return services - .Configure(setup) // support for IOptions - .AddSingleton(setup) // support for Action - .AddSingleton(options); // support for TOptions - } - /// /// Adds an implementation of to the specified . /// From 02bcca1bed3e3e16444078edc05212e18c5456c8 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:54:28 +0200 Subject: [PATCH 21/36] =?UTF-8?q?=E2=9C=85=20cover=20shared=20configured?= =?UTF-8?q?=20options=20behavior=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cuemon configured options share one instance between direct options and IOptions.Value, and defer setup until materialization. The tests now assert that behavior instead of the previous eager, separate instance. --- .../ServiceCollectionExtensionsTest.cs | 16 +++- .../ConfiguredOptionsTest.cs | 92 ++++++++++++------- .../ServiceCollectionRegistrationTest.cs | 1 + test/Shared/ConfiguredOptionsAssertions.cs | 4 +- 4 files changed, 73 insertions(+), 40 deletions(-) diff --git a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs index 69cba48f..36555891 100644 --- a/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.NATS.Tests/ServiceCollectionExtensionsTest.cs @@ -38,9 +38,11 @@ public void AddNatsCommandQueue_ShouldRegisterNatsCommandQueueAndConfigureOption }); // Assert - Assert.True(natsSetupCalled); + Assert.False(natsSetupCalled); var provider = services.BuildServiceProvider(); + Assert.False(natsSetupCalled); ConfiguredOptionsAssertions.Verify(provider); + Assert.True(natsSetupCalled); var queue = provider.GetService(); @@ -69,9 +71,11 @@ public void AddNatsCommandQueue_Generic_ShouldRegisterNatsCommandQueueAndConfigu }); // Assert - Assert.True(natsSetupCalled); + Assert.False(natsSetupCalled); var provider = services.BuildServiceProvider(); + Assert.False(natsSetupCalled); ConfiguredOptionsAssertions.Verify>(provider); + Assert.True(natsSetupCalled); var queue = provider.GetService>(); Assert.IsType>(provider.GetRequiredService>()); @@ -97,9 +101,11 @@ public void AddNatsEventBus_ShouldRegisterNatsEventBusAndConfigureOptions() }); // Assert - Assert.True(natsSetupCalled); + Assert.False(natsSetupCalled); var provider = services.BuildServiceProvider(); + Assert.False(natsSetupCalled); ConfiguredOptionsAssertions.Verify(provider); + Assert.True(natsSetupCalled); var bus = provider.GetService(); Assert.IsType(provider.GetRequiredService>()); @@ -125,9 +131,11 @@ public void AddNatsEventBus_Generic_ShouldRegisterNatsEventBusAndConfigureOption }); // Assert - Assert.True(natsSetupCalled); + Assert.False(natsSetupCalled); var provider = services.BuildServiceProvider(); + Assert.False(natsSetupCalled); ConfiguredOptionsAssertions.Verify>(provider); + Assert.True(natsSetupCalled); var bus = provider.GetService>(); Assert.IsType>(provider.GetRequiredService>()); diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/ConfiguredOptionsTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/ConfiguredOptionsTest.cs index 7c39d445..fa058b1c 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/ConfiguredOptionsTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/ConfiguredOptionsTest.cs @@ -1,9 +1,9 @@ #nullable enable using System; using System.Collections.Generic; -using System.Linq; using Codebelt.Extensions.Xunit; using Cuemon.Configuration; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Xunit; @@ -21,7 +21,7 @@ public void AddConfiguredOptions_ShouldRejectNullServicesBeforeInvokingSetup() { var called = false; - var error = Assert.Throws(() => ServiceCollectionExtensions.AddConfiguredOptions(null!, _ => called = true)); + var error = Assert.Throws(() => Cuemon.Extensions.DependencyInjection.ServiceCollectionExtensions.AddConfiguredOptions(null!, _ => called = true)); Assert.Equal("services", error.ParamName); Assert.False(called); @@ -59,55 +59,77 @@ public void AddConfiguredOptions_ShouldReturnSameCollectionAndRegisterThreeConsu Assert.Same(direct, scope.ServiceProvider.GetRequiredService()); Assert.Same(callback, scope.ServiceProvider.GetRequiredService>()); Assert.Same(microsoft, scope.ServiceProvider.GetRequiredService>()); - Assert.NotSame(direct, microsoft.Value); + Assert.Same(direct, microsoft.Value); Assert.Equal(ServiceLifetime.Singleton, Assert.Single(services, descriptor => descriptor.ServiceType == typeof(Options)).Lifetime); Assert.Equal(ServiceLifetime.Singleton, Assert.Single(services, descriptor => descriptor.ServiceType == typeof(Action)).Lifetime); } - [Fact] - public void AddConfiguredOptions_ShouldConfigureEagerlyAndAgainWhenMicrosoftOptionsAreMaterialized() + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AddConfiguredOptions_ShouldConfigureOnceWhenDefaultOptionsAreMaterialized(bool resolveDirectFirst) { var services = new ServiceCollection(); var invocations = 0; services.AddConfiguredOptions(options => options.Value = (++invocations).ToString()); - Assert.Equal(1, invocations); - using var provider = services.BuildServiceProvider(); - Assert.Equal("1", provider.GetRequiredService().Value); - Assert.Equal(1, invocations); + Assert.Equal(0, invocations); + using var provider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true, ValidateOnBuild = true }); var options = provider.GetRequiredService>(); + Assert.Equal(0, invocations); + var first = resolveDirectFirst ? provider.GetRequiredService() : options.Value; + var second = resolveDirectFirst ? options.Value : provider.GetRequiredService(); + + Assert.Equal("1", first.Value); + Assert.Same(first, second); + Assert.Same(first, provider.GetRequiredService()); + Assert.Same(first, options.Value); Assert.Equal(1, invocations); - Assert.Equal("2", options.Value.Value); - Assert.Same(options.Value, options.Value); - Assert.Equal(2, invocations); } - [Fact] - public void AddConfiguredOptions_ShouldValidateEagerlyAndWrapInvalidStateWithoutRegisteringServices() + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AddConfiguredOptions_ShouldReportInvalidStateWhenOptionsAreMaterialized(bool resolveDirect) { var services = new ServiceCollection(); - var error = Assert.Throws(() => services.AddConfiguredOptions(options => options.Value = "invalid")); + services.AddConfiguredOptions(options => options.Value = "invalid"); + using var provider = services.BuildServiceProvider(); - Assert.Equal("setup", error.ParamName); - Assert.IsType(error.InnerException); - Assert.Empty(services); + var error = Assert.Throws(() => + { + if (resolveDirect) { provider.GetRequiredService(); } + else { _ = provider.GetRequiredService>().Value; } + }); + + Assert.Equal(Microsoft.Extensions.Options.Options.DefaultName, error.OptionsName); + Assert.Equal(typeof(ValidatedOptions), error.OptionsType); + Assert.Equal("Value must be valid.", Assert.Single(error.Failures)); } - [Fact] - public void AddConfiguredOptions_ShouldPropagateSetupFailureWithoutRegisteringServices() + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AddConfiguredOptions_ShouldPropagateSetupFailureWhenOptionsAreMaterialized(bool resolveDirect) { var services = new ServiceCollection(); var expected = new InvalidOperationException("Configuration failed."); - var actual = Record.Exception(() => services.AddConfiguredOptions(_ => throw expected)); + services.AddConfiguredOptions(_ => throw expected); + using var provider = services.BuildServiceProvider(); + + var actual = Record.Exception(() => + { + if (resolveDirect) { provider.GetRequiredService(); } + else { _ = provider.GetRequiredService>().Value; } + }); Assert.Same(expected, actual); - Assert.Empty(services); } [Fact] - public void AddConfiguredOptions_ShouldPostConfigureThenValidateOnlyTheEagerInstance() + public void AddConfiguredOptions_ShouldPostConfigureThenValidateSharedOptionsAndExposeRawSetup() { var services = new ServiceCollection(); services.AddConfiguredOptions(options => @@ -123,29 +145,32 @@ public void AddConfiguredOptions_ShouldPostConfigureThenValidateOnlyTheEagerInst provider.GetRequiredService>()(manual); Assert.Equal(new[] { "configure", "postconfigure", "validate" }, direct.Stages); - Assert.Equal(new[] { "configure" }, microsoft.Stages); + Assert.Same(direct, microsoft); Assert.Equal(new[] { "configure" }, manual.Stages); } [Fact] - public void AddConfiguredOptions_ShouldAppendRepeatedRegistrationsAndComposeMicrosoftConfigurations() + public void AddConfiguredOptions_ShouldKeepFirstSetupAndRegisterEachConsumptionFormOnce() { var services = new ServiceCollection(); Action first = options => options.Value += "first"; Action second = options => options.Value += "second"; services.AddConfiguredOptions(first); services.AddConfiguredOptions(second); + services.AddConfiguredOptions(first); using var provider = services.BuildServiceProvider(); - Assert.Equal(new[] { "first", "second" }, provider.GetServices().Select(options => options.Value)); - Assert.Equal("second", provider.GetRequiredService().Value); - Assert.Same(second, provider.GetRequiredService>()); - Assert.Equal(new[] { first, second }, provider.GetServices>()); - Assert.Equal("firstsecond", provider.GetRequiredService>().Value.Value); + var direct = Assert.Single(provider.GetServices()); + Assert.Equal("first", direct.Value); + Assert.Same(first, Assert.Single(provider.GetServices>())); + Assert.Same(direct, provider.GetRequiredService>().Value); + var manual = new Options(); + provider.GetRequiredService>()(manual); + Assert.Equal("first", manual.Value); } [Fact] - public void AddConfiguredOptions_ShouldComposeMicrosoftConfigureAndPostConfigureWithoutChangingDirectOptions() + public void AddConfiguredOptions_ShouldComposeMicrosoftConfigureAndPostConfigureForSharedOptions() { var services = new ServiceCollection(); services.Configure(options => options.Value += "before;"); @@ -154,8 +179,9 @@ public void AddConfiguredOptions_ShouldComposeMicrosoftConfigureAndPostConfigure services.PostConfigure(options => options.Value += "post;"); using var provider = services.BuildServiceProvider(); - Assert.Equal("primary;", provider.GetRequiredService().Value); - Assert.Equal("before;primary;after;post;", provider.GetRequiredService>().Value.Value); + var direct = provider.GetRequiredService(); + Assert.Equal("before;primary;after;post;", direct.Value); + Assert.Same(direct, provider.GetRequiredService>().Value); var manual = new Options(); provider.GetRequiredService>()(manual); Assert.Equal("primary;", manual.Value); diff --git a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs index ea9a95b2..2b93da6f 100644 --- a/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs +++ b/test/Savvyio.Extensions.DependencyInjection.Tests/ServiceCollectionRegistrationTest.cs @@ -3,6 +3,7 @@ using System.IO; using Codebelt.Extensions.Xunit; using Cuemon.Configuration; +using Cuemon.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Savvyio.Dispatchers; diff --git a/test/Shared/ConfiguredOptionsAssertions.cs b/test/Shared/ConfiguredOptionsAssertions.cs index a3a8f0e3..19b40c0f 100644 --- a/test/Shared/ConfiguredOptionsAssertions.cs +++ b/test/Shared/ConfiguredOptionsAssertions.cs @@ -17,10 +17,8 @@ internal static class ConfiguredOptionsAssertions var manual = new TOptions(); callback(manual); - Assert.Equivalent(direct, microsoft, strict: true); + Assert.Same(direct, microsoft); Assert.Equivalent(direct, manual, strict: true); - // Characterize the current separate eager instance before the Cuemon migration. - Assert.NotSame(direct, microsoft); using var scope = provider.CreateScope(); Assert.Same(direct, scope.ServiceProvider.GetRequiredService()); Assert.Same(callback, scope.ServiceProvider.GetRequiredService>()); From 7101fe2d9c76e7c5af6506ea7f61ff97c2baffa9 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:54:28 +0200 Subject: [PATCH 22/36] =?UTF-8?q?=F0=9F=92=AC=20update=20changelog=20for?= =?UTF-8?q?=206.0.0=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the .NET 11 baseline, the removal of .NET 9 support, and the move of configured options to Cuemon so consumers can see the breaking changes in the release notes. --- CHANGELOG.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b688596..c70f46ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,22 +6,27 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba ## [6.0.0] - 2026-11-10 +This major release adds .NET 11 support, removes .NET 9 support, and aligns configured options with Microsoft Options integration so direct options and `IOptions.Value` share one configuration and validation pipeline. + ### Added - .NET 11 support alongside .NET 10 across packages and tests, with matching .NET 11 Entity Framework Core, SQLite, logging abstractions, and cryptography dependencies for net11.0. ### Changed -- CI provisions preview SDKs and tests .NET 11, preserving the single-target CI policy; local tests cover both supported targets; the local test container uses the .NET 11 SDK with the .NET 10 runtime and Microsoft Testing Platform arguments. -- Updated Codebelt.Coverlet.MTP from 10.1.0 to 10.1.1. -- Updated framework availability in contributor guidance, package READMEs, and DocFX includes; retained .NET 10 for DocFX metadata generation. -- Service-update automation preserves pending major/minor release versions and uses the modern framework availability fallback. -- Set the MinVer minimum major/minor to 6.0 for the breaking framework baseline change; release versions remain Git-tag derived. +- CI provisions preview SDKs and tests .NET 11, preserving the single-target CI policy; local tests cover both supported targets; the local test container uses the .NET 11 SDK with the .NET 10 runtime and Microsoft Testing Platform arguments, +- Updated Codebelt.Coverlet.MTP from 10.1.0 to 10.1.1, +- Updated framework availability in contributor guidance, package READMEs, and DocFX includes; retained .NET 10 for DocFX metadata generation, +- Service-update automation preserves pending major/minor release versions and uses the modern framework availability fallback, +- Set the MinVer minimum major/minor to 6.0 for the breaking framework baseline change; release versions remain Git-tag derived, +- Configured options now use Cuemon's `AddConfiguredOptions`: direct `TOptions` and the default `IOptions.Value` share one instance and the Microsoft configuration, post-configuration, and validation pipeline, avoiding the previous separate eager instance and repeated setup execution for these two consumption forms, +- Options configuration and validation are deferred until materialization; recoverable parameter-object validation failures surface as `OptionsValidationException` instead of `ArgumentException` during registration. The first `AddConfiguredOptions` registration per options type is retained; use `Configure` for additional composition. Injectable `Action` remains the original setup delegate and does not include the Microsoft pipeline. ### Removed -- .NET 9 support. Consumers must target .NET 10 or later. -- The .NET 9-only System.Linq.Async reference; both supported frameworks provide async LINQ. +- .NET 9 support. Consumers must target .NET 10 or later, +- The .NET 9-only System.Linq.Async reference; both supported frameworks provide async LINQ, +- `Savvyio.Extensions.DependencyInjection.ServiceCollectionExtensions.AddConfiguredOptions`; import `Cuemon.Extensions.DependencyInjection` or update fully qualified calls to use the Cuemon implementation. ## [5.0.13] - 2026-10-18 @@ -1190,6 +1195,7 @@ Noticeable highlights: - QueryHandler class in the Savvyio.Queries namespace that defines a generic and consistent way of handling Query objects that implements the IQuery interface - SavvyioOptionsExtensions class in the Savvyio.Queries namespace that consist of extension methods for the SavvyioOptions class: AddQueryHandler, AddQueryDispatcher +[6.0.0]: https://github.com/codebeltnet/savvyio/compare/v5.0.13...v6.0.0 [5.0.13]: https://github.com/codebeltnet/savvyio/compare/v5.0.12...v5.0.13 [5.0.12]: https://github.com/codebeltnet/savvyio/compare/v5.0.11...v5.0.12 [5.0.11]: https://github.com/codebeltnet/savvyio/compare/v5.0.10...v5.0.11 From e41828482692b88e30b1a29cc4f514d74d649e89 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sat, 24 Oct 2026 05:54:28 +0200 Subject: [PATCH 23/36] =?UTF-8?q?=F0=9F=94=A5=20remove=20benchmark=20copil?= =?UTF-8?q?ot=20prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The benchmark fixture prompt is removed from the repository prompts folder, so benchmark guidance is no longer generated from this file. --- .github/prompts/benchmark.prompt.md | 164 ---------------------------- 1 file changed, 164 deletions(-) delete mode 100644 .github/prompts/benchmark.prompt.md diff --git a/.github/prompts/benchmark.prompt.md b/.github/prompts/benchmark.prompt.md deleted file mode 100644 index 22d1c9db..00000000 --- a/.github/prompts/benchmark.prompt.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -mode: agent -description: 'Writing Performance Benchmarks' ---- - -# Benchmark Fixture Prompt (Tuning Benchmarks) - -This prompt defines how to generate performance tests (“benchmarks”) for a project/solution using BenchmarkDotNet. -Benchmarks are *not* unit tests — they are micro- or component-level performance measurements that belong under the `tuning/` directory and follow strict conventions. - -Copilot must follow these guidelines when generating benchmark fixtures. - ---- - -## 1. Naming and Placement - -- All benchmark projects live under the `tuning/` folder. - Examples: - - `tuning/.Benchmarks/` - - `tuning/.Console.Benchmarks/` - -- **Namespaces must NOT end with `.Benchmarks`.** - They must mirror the production assembly’s namespace. - - Example: - If benchmarking a type inside `YourProject.Console`, then: - - ```csharp - namespace YourProject.Console - { - public class Sha512256Benchmark { … } - } - ``` - -* **Benchmark class names must end with `Benchmark`.** - Example: `DateSpanBenchmark`, `FowlerNollVoBenchmark`. - -* Benchmark files should be located in the matching benchmark project - (e.g., benchmarks for `YourProject.Console` go in `YourProject.Console.Benchmarks.csproj`). - -* In the `.csproj` for each benchmark project, set the root namespace to the production namespace, for example: - - ```xml - YourProject.Console - ``` - ---- - -## 2. Attributes and Configuration - -Each benchmark class should use: - -```csharp -[MemoryDiagnoser] -[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] -``` - -Optional but strongly recommended where meaningful: - -* `[Params(...)]` — define small, medium, large input sizes. -* `[GlobalSetup]` — deterministic initialization of benchmark data. -* `[Benchmark(Description = "...")]` — always add descriptions. -* `[Benchmark(Baseline = true)]` — when comparing two implementations. - -Avoid complex global configs; prefer explicit attributes inside the class. - ---- - -## 3. Structure and Best Practices - -A benchmark fixture must: - -* Measure a **single logical operation** per benchmark method. -* Avoid I/O, networking, disk access, logging, or side effects. -* Avoid expensive setup inside `[Benchmark]` methods. -* Use deterministic data (e.g., seeded RNG or predefined constants). -* Use `[GlobalSetup]` to allocate buffers, random payloads, or reusable test data only once. -* Avoid shared mutable state unless reset per iteration. - -Use representative input sizes such as: - -```csharp -[Params(8, 256, 4096)] -public int Count { get; set; } -``` - -BenchmarkDotNet will run each benchmark for each parameter value. - ---- - -## 4. Method Naming Conventions - -Use descriptive names that communicate intent: - -* `Parse_Short` -* `Parse_Long` -* `ComputeHash_Small` -* `ComputeHash_Large` -* `Serialize_Optimized` -* `Serialize_Baseline` - -When comparing approaches, always list them clearly and tag one as the baseline. - ---- - -## 5. Example Benchmark Fixture - -```csharp -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; - -namespace YourProject -{ - [MemoryDiagnoser] - [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] - public class SampleOperationBenchmark - { - [Params(8, 256, 4096)] - public int Count { get; set; } - - private byte[] _payload; - - [GlobalSetup] - public void Setup() - { - _payload = new byte[Count]; - // deterministic initialization - } - - [Benchmark(Baseline = true, Description = "Operation - baseline")] - public int Operation_Baseline() => SampleOperation.Process(_payload); - - [Benchmark(Description = "Operation - optimized")] - public int Operation_Optimized() => SampleOperation.ProcessOptimized(_payload); - } -} -``` - ---- - -## 6. Reporting and CI - -* Benchmark projects live exclusively under `tuning/`. They must not affect production builds. -* Heavy BenchmarkDotNet runs should *not* run in CI unless explicitly configured. -* Reports are produced by the benchmark runner and stored under the configured artifacts directory. - ---- - -## 7. Additional Guidelines - -* Keep benchmark fixtures focused and readable. -* Document non-obvious reasoning in short comments. -* Prefer realistic but deterministic data sets. -* When benchmarks reveal regressions or improvements, reference the associated PR or issue in a comment. -* Shared benchmark helpers belong in `tuning/` projects, not in production code. - ---- - -## Final Notes - -* Benchmarks are performance tests, not unit tests. -* Use `[Benchmark]` only for pure performance measurement. -* Avoid `MethodImplOptions.NoInlining` unless absolutely necessary. -* Use small sets of meaningful benchmark scenarios — avoid combinatorial explosion. From b042234b80b559b902bc549f4910dfcac848104a Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sat, 24 Oct 2026 05:58:22 +0200 Subject: [PATCH 24/36] update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c70f46ae..71c9c4a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ This major release adds .NET 11 support, removes .NET 9 support, and aligns conf - .NET 9 support. Consumers must target .NET 10 or later, - The .NET 9-only System.Linq.Async reference; both supported frameworks provide async LINQ, +- `Savvyio.Reflection.AssemblyContext`; dispatcher, handler, and message converter discovery now calls `AssemblyContext.GetCurrentDomainAssemblies` from `Cuemon.Reflection`, - `Savvyio.Extensions.DependencyInjection.ServiceCollectionExtensions.AddConfiguredOptions`; import `Cuemon.Extensions.DependencyInjection` or update fully qualified calls to use the Cuemon implementation. ## [5.0.13] - 2026-10-18 From 195a7f2c81de004af942f4e22c61bbbcc4414f6f Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 25 Oct 2026 15:14:17 +0100 Subject: [PATCH 25/36] =?UTF-8?q?=F0=9F=90=9B=20honor=20cancellation=20bef?= =?UTF-8?q?ore=20publishing=20nats=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PublishAsync now checks the cancellation token before serializing and sending, so a cancelled publish no longer reaches the NATS server. The test asserts the bus publishes nothing and surfaces the original cancellation token. --- src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs | 1 + .../EventDriven/NatsEventBusTest.cs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs index 506bb3a4..f0e27aef 100644 --- a/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs +++ b/src/Savvyio.Extensions.NATS/EventDriven/NatsEventBus.cs @@ -49,6 +49,7 @@ public NatsEventBus(IMarshaller marshaller, NatsEventBusOptions options) : base( public async Task PublishAsync(IMessage message, Action setup = null) { Validator.ThrowIfInvalidConfigurator(setup, out var options); + options.CancellationToken.ThrowIfCancellationRequested(); await PublishMessageAsync(_options.Subject, (await Marshaller.Serialize(message).ToByteArrayAsync().ConfigureAwait(false)).ToBase64String(), new NatsHeaders() { { "type", message.GetType().ToFullNameIncludingAssemblyName() } diff --git a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs index 6c20a1cd..d4270756 100644 --- a/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs +++ b/test/Savvyio.Extensions.NATS.Tests/EventDriven/NatsEventBusTest.cs @@ -76,7 +76,7 @@ public async Task PublishAsync_WithPreCancelledToken_ShouldThrowOperationCancele using var cts = new CancellationTokenSource(); cts.Cancel(); - var bus = new NatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); + await using var bus = new TestableNatsEventBus(_marshaller, new NatsEventBusOptions { Subject = "subject" }); var message = new Message( Guid.NewGuid().ToString("N"), new Uri("urn:test"), @@ -87,7 +87,10 @@ public async Task PublishAsync_WithPreCancelledToken_ShouldThrowOperationCancele () => bus.PublishAsync(message, o => o.CancellationToken = cts.Token)); Assert.NotNull(ex); - Assert.IsAssignableFrom(ex); + Assert.Equal(cts.Token, Assert.IsAssignableFrom(ex).CancellationToken); + Assert.Null(bus.PublishedSubject); + Assert.Null(bus.PublishedMessage); + Assert.Null(bus.PublishedHeaders); } [Fact] From 611bcac74b616232870eb45f0c2bc5bfb53744ec Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 25 Oct 2026 15:14:17 +0100 Subject: [PATCH 26/36] =?UTF-8?q?=E2=9C=85=20trim=20trailing=20whitespace?= =?UTF-8?q?=20in=20traced=20schema=20assertion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The schema comparison now normalizes line endings and trims trailing whitespace before matching, so the assertion does not fail on whitespace differences in the EF Core model output. --- .../TracedAggregateRootTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs index 368302f4..790f7a9e 100644 --- a/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs +++ b/test/Savvyio.Domain.EventSourcing.Tests/TracedAggregateRootTest.cs @@ -157,6 +157,8 @@ public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToSto Assert.Equal(name, sut5.FullName); Assert.Equal("root@gimlichael.dev", sut5.EmailAddress); + var normalizedSchema = string.Join(Environment.NewLine, schema.ReplaceLineEndings().Split(Environment.NewLine).Select(line => line.TrimEnd())); + Assert.True(Match(@"Model: EntityType: EfCoreTracedAggregateEntity Properties: @@ -190,7 +192,7 @@ public async Task EfCoreDataStore_ShouldRaiseDomainEventsAndDehydrateEventsToSto BaseTypeDiscoveryConvention:DerivedTypes: System.Collections.Generic.Dictionary`2[System.Type,System.Collections.Generic.List`1[Microsoft.EntityFrameworkCore.Metadata.IConventionEntityType]] InversePropertyAttributeConvention:InverseNavigations: System.Collections.Generic.Dictionary`2[System.Type,System.Collections.Generic.SortedSet`1[System.Type]] NonNullableConventionState: System.Reflection.NullabilityInfoContext - ProductVersion: *".ReplaceLineEndings(), schema.ReplaceLineEndings(), o => o.ThrowOnNoMatch = true)); + ProductVersion: *".ReplaceLineEndings(), normalizedSchema, o => o.ThrowOnNoMatch = true)); } [Fact] From e92b1fffa13da9a13ab3ababed6a8c8d9f776a24 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 25 Oct 2026 15:14:17 +0100 Subject: [PATCH 27/36] =?UTF-8?q?=F0=9F=94=A7=20split=20docker=20test=20en?= =?UTF-8?q?vironments=20by=20dotnet=20target?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The single Docker test environment is split into separate net10.0 and net11.0 runners, each using its matching testrunner image. The Ubuntu WSL distribution is also moved to Ubuntu-26.04. --- testenvironments.json | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/testenvironments.json b/testenvironments.json index 66f3fcdb..7f57f177 100644 --- a/testenvironments.json +++ b/testenvironments.json @@ -4,12 +4,18 @@ { "name": "WSL-Ubuntu", "type": "wsl", - "wslDistribution": "Ubuntu-24.04" + "wslDistribution": "Ubuntu-26.04" }, { - "name": "Docker-Ubuntu", + "name": "Docker-Ubuntu (net10.0)", "type": "docker", - "dockerImage": "codebeltnet/ubuntu-testrunner:8-9-10-11", + "dockerImage": "codebeltnet/ubuntu-testrunner:10", + "dockerArgs": "--network savvyio-test -e AWS__CallerIdentity -e AWS__IAM__AccessKey -e AWS__IAM__SecretKey -e SAVVYIO_NATS_URL=nats://nats:4222 -e SAVVYIO_RABBITMQ_URL=amqp://rabbitmq:5672 -e SAVVYIO_RABBITMQ_MANAGEMENT_URL=http://rabbitmq:15672" + }, + { + "name": "Docker-Ubuntu (net11.0)", + "type": "docker", + "dockerImage": "codebeltnet/ubuntu-testrunner:11", "dockerArgs": "--network savvyio-test -e AWS__CallerIdentity -e AWS__IAM__AccessKey -e AWS__IAM__SecretKey -e SAVVYIO_NATS_URL=nats://nats:4222 -e SAVVYIO_RABBITMQ_URL=amqp://rabbitmq:5672 -e SAVVYIO_RABBITMQ_MANAGEMENT_URL=http://rabbitmq:15672" } ] From 45bbf72b0ad7dfc7eb9466066134091a464f20e9 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 1 Nov 2026 15:52:08 +0100 Subject: [PATCH 28/36] =?UTF-8?q?=20=F0=9F=94=8D=EF=B8=8FsonarAnalyzer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.props | 1 + Directory.Packages.props | 1 + 2 files changed, 2 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index f60da6f7..17472915 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -46,6 +46,7 @@ + diff --git a/Directory.Packages.props b/Directory.Packages.props index 4c57a099..4e6f704e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,6 +36,7 @@ + From 6c3feb5c8e6a00a498f3bb683f170dc9274bf141 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 1 Nov 2026 16:02:07 +0100 Subject: [PATCH 29/36] =?UTF-8?q?=E2=9C=A8=20add=20date=20validation=20for?= =?UTF-8?q?=20changelog=20version=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/service-update.yml | 29 ++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/service-update.yml b/.github/workflows/service-update.yml index 3a0877fa..2dbfe5b7 100644 --- a/.github/workflows/service-update.yml +++ b/.github/workflows/service-update.yml @@ -50,6 +50,7 @@ jobs: import re import subprocess import sys + from datetime import date tag_pattern = re.compile(r"^v(\d+)\.(\d+)\.(\d+)$") tags = subprocess.check_output(["git", "tag", "--list"], text=True).splitlines() @@ -72,30 +73,37 @@ jobs: with open("CHANGELOG.md", encoding="utf-8") as changelog_file: changelog = changelog_file.read() - heading = re.search(r"(?m)^## \[(\d+\.\d+\.\d+)\] - ([^\r\n]+)[ \t]*$", changelog) + heading = re.search(r"(?m)^## \[(\d+\.\d+\.\d+)\]([^\r\n]*)$", changelog) if not heading: print("::error::CHANGELOG.md has no versioned heading to compare with Git tags.") sys.exit(1) - current_version, current_status = heading.groups() - current_status = current_status.strip() - if current_status.upper() != "TBD" and not re.fullmatch(r"\d{4}-\d{2}-\d{2}", current_status): - print(f"::error::Unsupported CHANGELOG.md version status: {current_status}") + current_version = heading.group(1) + status_match = re.fullmatch(r" - (TBD|\d{4}-\d{2}-\d{2})[ \t]*", heading.group(2), re.IGNORECASE) + if not status_match: + print(f"::error::Unsupported or missing CHANGELOG.md version status: {heading.group(2).strip()}") sys.exit(1) + current_status = status_match.group(1) + if current_status.upper() != "TBD": + try: + date.fromisoformat(current_status) + except ValueError: + print(f"::error::Invalid CHANGELOG.md release date: {current_status}") + sys.exit(1) pending_version = tuple(int(part) for part in current_version.split(".")) released_version = (major, minor, patch) - if pending_version > released_version and current_status.upper() == "TBD": + if pending_version > released_version: # Preserve an explicitly planned patch, minor, or major release. new_version = current_version - elif current_version == latest_version and current_status.upper() != "TBD": + elif pending_version == released_version and current_status.upper() != "TBD": # The changelog is at the latest released tag; start the next patch release. new_version = next_version else: print( f"::error::CHANGELOG.md starts at {current_version} ({current_status}), " f"but the latest stable Git tag is {latest_tag}. Expected either " - f"[{latest_version}] with a release date or a newer version marked TBD." + f"[{latest_version}] with a release date or a newer version with a date or TBD." ) sys.exit(1) @@ -107,6 +115,7 @@ jobs: output.write(f"current={current_version}\n") output.write(f"new={new_version}\n") output.write(f"branch={branch}\n") + PY - name: Generate codebelt-aicia token id: app-token @@ -144,9 +153,9 @@ jobs: service_note = "This release also includes a service update focused on package dependencies." with open("CHANGELOG.md", encoding="utf-8") as f: content = f.read() - heading = re.search(r"(?m)^## \[(\d+\.\d+\.\d+)\] - (TBD|\d{4}-\d{2}-\d{2})[ \t]*$", content) + heading = re.search(r"(?m)^## \[(\d+\.\d+\.\d+)\] - (TBD|\d{4}-\d{2}-\d{2})[ \t]*$", content, re.IGNORECASE) if heading and heading.group(1) == new_ver: - if heading.group(2) == "TBD": + if heading.group(2).upper() == "TBD": content = content[:heading.start(2)] + today + content[heading.end(2):] heading = re.search(r"(?m)^## \[(\d+\.\d+\.\d+)\] - \d{4}-\d{2}-\d{2}[ \t]*$", content) section_end = re.search(r"(?m)^## \[", content[heading.end():]) From 39c05d63fc5aac618d9aeb22eb2d6b28a1e8f5b7 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 1 Nov 2026 16:05:29 +0100 Subject: [PATCH 30/36] =?UTF-8?q?=F0=9F=94=A7=20update=20test=20environmen?= =?UTF-8?q?ts=20in=20contributing=20guidelines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/CONTRIBUTING.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6c72b7d1..c0780699 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -15,7 +15,7 @@ This repository is part of the Codebelt .NET library estate. The instructions be - `test/` contains xUnit v3 test projects. - `Savvyio.slnx` is the solution used for local development. - `.github/workflows/ci-pipeline.yml` is the CI workflow and the authority for the test matrix. -- `testenvironments.json` declares the supported `WSL-Ubuntu` and `Docker-Ubuntu` test environments. +- `testenvironments.json` declares the supported `WSL-Ubuntu`, `Docker-Ubuntu (net10.0)`, and `Docker-Ubuntu (net11.0)` test environments. ## Build @@ -44,8 +44,9 @@ The CI test plan currently runs **28** project(s) and excludes **8** project(s). ## Integration and infrastructure -- `WSL-Ubuntu` — WSL distribution `Ubuntu-24.04`. -- `Docker-Ubuntu` — Docker image `codebeltnet/ubuntu-testrunner:8-9-10-11`. +- `WSL-Ubuntu` — WSL distribution `Ubuntu-26.04`. +- `Docker-Ubuntu (net10.0)` — Docker image `codebeltnet/ubuntu-testrunner:10`. +- `Docker-Ubuntu (net11.0)` — Docker image `codebeltnet/ubuntu-testrunner:11`. This repository has `docker-compose.yml` with these services: `awscli, localstack, nats, rabbitmq`. @@ -85,7 +86,7 @@ Package-specific release notes live under `.nuget//PackageReleaseNo ## Issues -Include the affected project, target framework, operating system, SDK version, exact command, expected result, actual result, and a minimal reproduction. Identify whether the behavior differs between local Windows/WSL, Docker-Ubuntu and GitHub Actions. +Include the affected project, target framework, operating system, SDK version, exact command, expected result, actual result, and a minimal reproduction. Identify whether the behavior differs between local Windows/WSL, the Docker test environments, and GitHub Actions. ## Coding guidelines From d290efc5c8278a8a6bf3e8bc3d2df71d003b9e3c Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 1 Nov 2026 16:05:39 +0100 Subject: [PATCH 31/36] =?UTF-8?q?=F0=9F=94=A7=20update=20changelog=20to=20?= =?UTF-8?q?remove=20redundant=20local=20test=20container=20details?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71c9c4a2..e05bf1e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,10 @@ This major release adds .NET 11 support, removes .NET 9 support, and aligns conf ### Changed -- CI provisions preview SDKs and tests .NET 11, preserving the single-target CI policy; local tests cover both supported targets; the local test container uses the .NET 11 SDK with the .NET 10 runtime and Microsoft Testing Platform arguments, +- CI provisions preview SDKs and tests .NET 11, preserving the single-target CI policy; local tests cover both supported targets, - Updated Codebelt.Coverlet.MTP from 10.1.0 to 10.1.1, - Updated framework availability in contributor guidance, package READMEs, and DocFX includes; retained .NET 10 for DocFX metadata generation, - Service-update automation preserves pending major/minor release versions and uses the modern framework availability fallback, -- Set the MinVer minimum major/minor to 6.0 for the breaking framework baseline change; release versions remain Git-tag derived, - Configured options now use Cuemon's `AddConfiguredOptions`: direct `TOptions` and the default `IOptions.Value` share one instance and the Microsoft configuration, post-configuration, and validation pipeline, avoiding the previous separate eager instance and repeated setup execution for these two consumption forms, - Options configuration and validation are deferred until materialization; recoverable parameter-object validation failures surface as `OptionsValidationException` instead of `ArgumentException` during registration. The first `AddConfiguredOptions` registration per options type is retained; use `Configure` for additional composition. Injectable `Action` remains the original setup delegate and does not include the Microsoft pipeline. From bed4d6683437c5288ffe0042626a0807d91ae15e Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 1 Nov 2026 16:25:41 +0100 Subject: [PATCH 32/36] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20central=20?= =?UTF-8?q?package=20versions=20to=20latest=20releases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligns the central NuGet versions with the latest stable and release-candidate listings for .NET 10 and .NET 11, including the pinned System.Security.Cryptography.Pkcs baseline, so the test and build matrix runs against current packages. --- Directory.Packages.props | 50 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4e6f704e..e71523d3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,32 +4,32 @@ true - - + + - - - - - - - + + + + + + + - + - - - + + + @@ -39,21 +39,21 @@ - - - - - - + + + + + + - - - - - - + + + + + + From 7069907e0a7fe4896e9323481ac0b976029da015 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 1 Nov 2026 16:25:42 +0100 Subject: [PATCH 33/36] =?UTF-8?q?=F0=9F=94=A7=20enforce=20file-scoped=20na?= =?UTF-8?q?mespaces=20as=20errors=20in=20editorconfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit File-scoped namespaces are mandatory for C# files in this repository. Setting IDE0161 to error makes the analyzer enforce the rule at build time instead of only flagging it as a suggestion. --- .editorconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index e6ec61ef..886ea153 100644 --- a/.editorconfig +++ b/.editorconfig @@ -37,7 +37,7 @@ dotnet_diagnostic.IDE0063.severity = none dotnet_diagnostic.IDE0071.severity = none # S3267: Loops should be simplified with "LINQ" expressions -# https://rules.sonarsource.com/csharp/RSPEC-3267 +# https://sonarcloud.io/organizations/sonarcloud/rules?open=csharpsquid:S3267&rule_key=csharpsquid:S3267 dotnet_diagnostic.S3267.severity = none # CA1859: Use concrete types when possible for improved performance @@ -57,8 +57,10 @@ indent_size = 4 # IDE0161: Namespace declaration preferences # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0161 +# File-scoped namespaces are mandatory for new and existing C# files. [*.cs] csharp_style_namespace_declarations = file_scoped:error +dotnet_diagnostic.IDE0161.severity = error # Top-level statements: DO NOT USE # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0210-ide0211 From 3b5052f1378d298ba96bcde44eca30159ee9499a Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 1 Nov 2026 16:25:42 +0100 Subject: [PATCH 34/36] =?UTF-8?q?=F0=9F=8E=A8=20remove=20trailing=20whites?= =?UTF-8?q?pace=20from=20gitattributes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trims trailing spaces in comments of the .gitattributes file. The change has no effect on Git behavior and keeps the file clean for future diffs. --- .gitattributes | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 6f3fcbdd..0ea8d1bd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,7 +17,7 @@ # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following +# the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below @@ -46,9 +46,9 @@ ############################################################################### # diff behavior for common document formats -# +# # Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the +# is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain From 9a1fe10fa00172bd98ee98ab18fa299542a4cec4 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 1 Nov 2026 16:25:42 +0100 Subject: [PATCH 35/36] =?UTF-8?q?=F0=9F=92=AC=20update=20contributing=20gu?= =?UTF-8?q?idelines=20for=20current=20test=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contributors read this guide to learn which frameworks and test environments CI covers. The targets are listed in sorted order, the CI description no longer claims a specific local framework split, and the issue template now names the Docker-Ubuntu environment. --- .github/CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c0780699..013ff856 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -5,7 +5,7 @@ This repository is part of the Codebelt .NET library estate. The instructions be ## Before you start - Read the repository `README.md` and open an issue before starting a non-trivial feature or behavioral change. -- Use an installed .NET SDK that can build the target frameworks listed below. This repository currently targets: **net11.0, net10.0**. +- Use an installed .NET SDK that can build the target frameworks listed below. This repository currently targets: **net10.0, net11.0**. - The solution is `Savvyio.slnx`. Central package versions are maintained in `Directory.Packages.props`. - The shared build behavior is in `Directory.Build.props` and `Directory.Build.targets`; repository-specific TFMs, package references and metadata remain local to this library. @@ -40,7 +40,7 @@ foreach ($project in $testProjects) { } ``` -The CI test plan currently runs **28** project(s) and excludes **8** project(s). The workflow also has an optional macOS test job. CI tests the newest supported framework (net11.0); local runs cover both net11.0 and net10.0. Run cloud integration projects one framework at a time with `--framework` because their queues are shared across targets. +The CI test plan currently runs **28** project(s) and excludes **8** project(s). The workflow also has an optional macOS test job. Run cloud integration projects one framework at a time with `--framework` because their queues are shared across targets. ## Integration and infrastructure @@ -86,7 +86,7 @@ Package-specific release notes live under `.nuget//PackageReleaseNo ## Issues -Include the affected project, target framework, operating system, SDK version, exact command, expected result, actual result, and a minimal reproduction. Identify whether the behavior differs between local Windows/WSL, the Docker test environments, and GitHub Actions. +Include the affected project, target framework, operating system, SDK version, exact command, expected result, actual result, and a minimal reproduction. Identify whether the behavior differs between local Windows/WSL, Docker-Ubuntu and GitHub Actions. ## Coding guidelines From cdfa292e7797c34beefbb2a5eb885c677101e5c8 Mon Sep 17 00:00:00 2001 From: aicia-bot Date: Sun, 1 Nov 2026 16:25:42 +0100 Subject: [PATCH 36/36] =?UTF-8?q?=F0=9F=93=9D=20clarify=20which=20files=20?= =?UTF-8?q?in=20bot=20folder=20are=20tracked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .bot folder is local-only by default, but this README is intentionally tracked. Stating that exception keeps future contributors from ignoring or moving it by mistake. --- .bot/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bot/README.md b/.bot/README.md index f7e13f00..9f9afdab 100644 --- a/.bot/README.md +++ b/.bot/README.md @@ -7,4 +7,4 @@ This folder is reserved for local-only AI working material such as: - design alternatives - temporary agent state -Keep this folder out of source control. Move only finalized, non-confidential guidance into `AGENTS.md`. +The `.bot/README.md` file itself is intentionally tracked in source control. All other `.bot/` working material remains local-only and excluded from source control. Move only finalized, non-confidential guidance into `AGENTS.md`.