diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..0d1a9ae
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,562 @@
+; EditorConfig to support per-solution formatting.
+; Use the EditorConfig VS add-in to make this work.
+; http://editorconfig.org/
+;
+; Here are some resources for what's supported for .NET/C#
+; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
+; https://learn.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference
+;
+; Be **careful** editing this because some of the rules don't support adding a severity level
+; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`)
+; then the rule will be silently ignored.
+
+; This is the default for the codeline.
+root = true
+
+[*]
+indent_style = space
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+spelling_exclusion_path = spelling.dic
+
+[*.cs]
+# gago - rules - begin
+dotnet_style_qualification_for_field = true:Error
+dotnet_style_qualification_for_property = true:Error
+dotnet_style_qualification_for_method = true:Error
+dotnet_style_qualification_for_event = true:Error
+
+dotnet_code_quality.null_check_validation_methods = Dawn.Guard.Argument(ParamType).NotNull() | Argument | NotNull
+
+dotnet_public_api_analyzer.require_api_files = true
+# gago - rules - end
+
+indent_size = 4
+dotnet_sort_system_directives_first = true
+
+
+
+# use int x = .. over Int32
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+
+# use int.MaxValue over Int32.MaxValue
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# Require var all the time.
+csharp_style_var_for_built_in_types = true:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = true:suggestion
+
+# Disallow throw expressions.
+csharp_style_throw_expression = false:suggestion
+
+# Newline settings
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+
+# Namespace settings
+csharp_style_namespace_declarations = file_scoped:silent
+
+# Brace settings
+csharp_prefer_braces = true:silent# Prefer curly braces even for one line of code
+
+# name all constant fields using PascalCase
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = warning
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+# static fields should have s_ prefix
+dotnet_naming_rule.static_fields_should_have_prefix.severity = warning
+dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
+dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
+dotnet_naming_style.static_prefix_style.required_prefix = s_
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
+
+# internal and private fields should be _camelCase
+dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
+dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
+# dotnet_naming_style.camel_case_underscore_style.required_prefix = _
+# dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+csharp_indent_labels = one_less_than_current
+csharp_using_directive_placement = outside_namespace:warning
+csharp_prefer_simple_using_statement = true:silent
+csharp_style_prefer_method_group_conversion = true:suggestion
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_prefer_primary_constructors = true:suggestion
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_style_prefer_null_check_over_type_check = true:suggestion
+csharp_prefer_simple_default_expression = true:warning
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+csharp_style_prefer_index_operator = true:suggestion
+csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
+csharp_style_prefer_range_operator = true:suggestion
+csharp_style_prefer_utf8_string_literals = true:suggestion
+csharp_style_prefer_tuple_swap = true:suggestion
+csharp_style_deconstructed_variable_declaration = false:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:warning
+csharp_style_unused_value_expression_statement_preference = discard_variable:warning
+csharp_prefer_static_local_function = true:suggestion
+csharp_style_prefer_readonly_struct = true:suggestion
+csharp_prefer_static_anonymous_function = true:suggestion
+csharp_style_prefer_readonly_struct_member = true:suggestion
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
+csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
+csharp_style_conditional_delegate_call = true:suggestion
+csharp_style_prefer_switch_expression = true:suggestion
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_prefer_pattern_matching = true:silent
+csharp_style_prefer_not_pattern = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_prefer_extended_property_pattern = true:suggestion
+csharp_space_around_binary_operators = before_and_after
+
+[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_size = 2
+
+[*.json]
+indent_size = 2
+
+[*.{ps1,psm1}]
+indent_size = 4
+
+[*.sh]
+indent_size = 4
+end_of_line = lf
+
+[*.{razor,cshtml}]
+charset = utf-8-bom
+
+[*.{cs,vb}]
+
+# SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time
+dotnet_diagnostic.SYSLIB1054.severity = warning
+
+# CA1018: Mark attributes with AttributeUsageAttribute
+dotnet_diagnostic.CA1018.severity = warning
+
+# CA1047: Do not declare protected member in sealed type
+dotnet_diagnostic.CA1047.severity = warning
+
+# CA1305: Specify IFormatProvider
+dotnet_diagnostic.CA1305.severity = warning
+
+# CA1507: Use nameof to express symbol names
+dotnet_diagnostic.CA1507.severity = warning
+
+# CA1510: Use ArgumentNullException throw helper
+dotnet_diagnostic.CA1510.severity = warning
+
+# CA1511: Use ArgumentException throw helper
+dotnet_diagnostic.CA1511.severity = warning
+
+# CA1512: Use ArgumentOutOfRangeException throw helper
+dotnet_diagnostic.CA1512.severity = warning
+
+# CA1513: Use ObjectDisposedException throw helper
+dotnet_diagnostic.CA1513.severity = warning
+
+# CA1725: Parameter names should match base declaration
+dotnet_diagnostic.CA1725.severity = suggestion
+
+# CA1802: Use literals where appropriate
+dotnet_diagnostic.CA1802.severity = warning
+
+# CA1805: Do not initialize unnecessarily
+dotnet_diagnostic.CA1805.severity = warning
+
+# CA1810: Do not initialize unnecessarily
+dotnet_diagnostic.CA1810.severity = warning
+
+# CA1821: Remove empty Finalizers
+dotnet_diagnostic.CA1821.severity = warning
+
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = warning
+dotnet_code_quality.CA1822.api_surface = private, internal
+
+# CA1823: Avoid unused private fields
+dotnet_diagnostic.CA1823.severity = warning
+
+# CA1825: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = warning
+
+# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
+dotnet_diagnostic.CA1826.severity = warning
+
+# CA1827: Do not use Count() or LongCount() when Any() can be used
+dotnet_diagnostic.CA1827.severity = warning
+
+# CA1828: Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used
+dotnet_diagnostic.CA1828.severity = warning
+
+# CA1829: Use Length/Count property instead of Count() when available
+dotnet_diagnostic.CA1829.severity = warning
+
+# CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder
+dotnet_diagnostic.CA1830.severity = warning
+
+# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1831.severity = warning
+
+# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1832.severity = warning
+
+# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1833.severity = warning
+
+# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
+dotnet_diagnostic.CA1834.severity = warning
+
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = warning
+
+# CA1836: Prefer IsEmpty over Count
+dotnet_diagnostic.CA1836.severity = warning
+
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = warning
+
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = warning
+
+# CA1839: Use 'Environment.ProcessPath'
+dotnet_diagnostic.CA1839.severity = warning
+
+# CA1840: Use 'Environment.CurrentManagedThreadId'
+dotnet_diagnostic.CA1840.severity = warning
+
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = warning
+
+# CA1842: Do not use 'WhenAll' with a single task
+dotnet_diagnostic.CA1842.severity = warning
+
+# CA1843: Do not use 'WaitAll' with a single task
+dotnet_diagnostic.CA1843.severity = warning
+
+# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
+dotnet_diagnostic.CA1844.severity = warning
+
+# CA1845: Use span-based 'string.Concat'
+dotnet_diagnostic.CA1845.severity = warning
+
+# CA1846: Prefer AsSpan over Substring
+dotnet_diagnostic.CA1846.severity = warning
+
+# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
+dotnet_diagnostic.CA1847.severity = warning
+
+# CA1852: Seal internal types
+dotnet_diagnostic.CA1852.severity = warning
+
+# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
+dotnet_diagnostic.CA1854.severity = warning
+
+# CA1855: Prefer 'Clear' over 'Fill'
+dotnet_diagnostic.CA1855.severity = warning
+
+# CA1856: Incorrect usage of ConstantExpected attribute
+dotnet_diagnostic.CA1856.severity = error
+
+# CA1857: A constant is expected for the parameter
+dotnet_diagnostic.CA1857.severity = warning
+
+# CA1858: Use 'StartsWith' instead of 'IndexOf'
+dotnet_diagnostic.CA1858.severity = warning
+
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = warning
+
+# CA2008: Do not create tasks without passing a TaskScheduler
+dotnet_diagnostic.CA2008.severity = warning
+
+# CA2009: Do not call ToImmutableCollection on an ImmutableCollection value
+dotnet_diagnostic.CA2009.severity = warning
+
+# CA2011: Avoid infinite recursion
+dotnet_diagnostic.CA2011.severity = warning
+
+# CA2012: Use ValueTask correctly
+dotnet_diagnostic.CA2012.severity = warning
+
+# CA2013: Do not use ReferenceEquals with value types
+dotnet_diagnostic.CA2013.severity = warning
+
+# CA2014: Do not use stackalloc in loops.
+dotnet_diagnostic.CA2014.severity = warning
+
+# CA2016: Forward the 'CancellationToken' parameter to methods that take one
+dotnet_diagnostic.CA2016.severity = warning
+
+# CA2200: Rethrow to preserve stack details
+dotnet_diagnostic.CA2200.severity = warning
+
+# CA2201: Do not raise reserved exception types
+dotnet_diagnostic.CA2201.severity = warning
+
+# CA2208: Instantiate argument exceptions correctly
+dotnet_diagnostic.CA2208.severity = warning
+
+# CA2245: Do not assign a property to itself
+dotnet_diagnostic.CA2245.severity = warning
+
+# CA2246: Assigning symbol and its member in the same statement
+dotnet_diagnostic.CA2246.severity = warning
+
+# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
+dotnet_diagnostic.CA2249.severity = warning
+
+# IDE0005: Remove unnecessary usings
+dotnet_diagnostic.IDE0005.severity = warning
+
+# IDE0011: Curly braces to surround blocks of code
+dotnet_diagnostic.IDE0011.severity = warning
+
+# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
+dotnet_diagnostic.IDE0020.severity = warning
+
+# IDE0029: Use coalesce expression (non-nullable types)
+dotnet_diagnostic.IDE0029.severity = warning
+
+# IDE0030: Use coalesce expression (nullable types)
+dotnet_diagnostic.IDE0030.severity = warning
+
+# IDE0031: Use null propagation
+dotnet_diagnostic.IDE0031.severity = warning
+
+# IDE0035: Remove unreachable code
+dotnet_diagnostic.IDE0035.severity = warning
+
+# IDE0036: Order modifiers
+csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+dotnet_diagnostic.IDE0036.severity = warning
+
+# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
+dotnet_diagnostic.IDE0038.severity = warning
+
+# IDE0043: Format string contains invalid placeholder
+dotnet_diagnostic.IDE0043.severity = warning
+
+# IDE0044: Make field readonly
+dotnet_diagnostic.IDE0044.severity = warning
+
+# IDE0051: Remove unused private members
+dotnet_diagnostic.IDE0051.severity = warning
+
+# IDE0055: All formatting rules
+dotnet_diagnostic.IDE0055.severity = suggestion
+
+# IDE0059: Unnecessary assignment to a value
+dotnet_diagnostic.IDE0059.severity = warning
+
+# IDE0060: Remove unused parameter
+dotnet_code_quality_unused_parameters = non_public:suggestion
+dotnet_diagnostic.IDE0060.severity = warning
+
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = warning
+
+# IDE0073: File header
+dotnet_diagnostic.IDE0073.severity = warning
+file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.
+
+# IDE1006: Required naming style
+dotnet_diagnostic.IDE1006.severity = suggestion
+
+# IDE0161: Convert to file-scoped namespace
+dotnet_diagnostic.IDE0161.severity = warning
+
+# IDE0200: Lambda expression can be removed
+dotnet_diagnostic.IDE0200.severity = warning
+
+# IDE2000: Disallow multiple blank lines
+dotnet_style_allow_multiple_blank_lines_experimental = false:silent
+dotnet_diagnostic.IDE2000.severity = warning
+
+[{eng/tools/**.cs,**/{test,testassets,samples,Samples,perf,benchmarkapps,scripts,stress}/**.cs,src/Hosting/Server.IntegrationTesting/**.cs,src/Servers/IIS/IntegrationTesting.IIS/**.cs,src/Shared/Http2cat/**.cs,src/Testing/**.cs}]
+# CA1018: Mark attributes with AttributeUsageAttribute
+dotnet_diagnostic.CA1018.severity = suggestion
+# CA1507: Use nameof to express symbol names
+dotnet_diagnostic.CA1507.severity = suggestion
+# CA1510: Use ArgumentNullException throw helper
+dotnet_diagnostic.CA1510.severity = suggestion
+# CA1511: Use ArgumentException throw helper
+dotnet_diagnostic.CA1511.severity = suggestion
+# CA1512: Use ArgumentOutOfRangeException throw helper
+dotnet_diagnostic.CA1512.severity = suggestion
+# CA1513: Use ObjectDisposedException throw helper
+dotnet_diagnostic.CA1513.severity = suggestion
+# CA1802: Use literals where appropriate
+dotnet_diagnostic.CA1802.severity = suggestion
+# CA1805: Do not initialize unnecessarily
+dotnet_diagnostic.CA1805.severity = suggestion
+# CA1810: Do not initialize unnecessarily
+dotnet_diagnostic.CA1810.severity = suggestion
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = suggestion
+# CA1823: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = suggestion
+# CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly
+dotnet_diagnostic.CA1826.severity = suggestion
+# CA1827: Do not use Count() or LongCount() when Any() can be used
+dotnet_diagnostic.CA1827.severity = suggestion
+# CA1829: Use Length/Count property instead of Count() when available
+dotnet_diagnostic.CA1829.severity = suggestion
+# CA1831: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1831.severity = suggestion
+# CA1832: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1832.severity = suggestion
+# CA1833: Use AsSpan or AsMemory instead of Range-based indexers when appropriate
+dotnet_diagnostic.CA1833.severity = suggestion
+# CA1834: Consider using 'StringBuilder.Append(char)' when applicable
+dotnet_diagnostic.CA1834.severity = suggestion
+# CA1835: Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+dotnet_diagnostic.CA1835.severity = suggestion
+# CA1837: Use 'Environment.ProcessId'
+dotnet_diagnostic.CA1837.severity = suggestion
+# CA1838: Avoid 'StringBuilder' parameters for P/Invokes
+dotnet_diagnostic.CA1838.severity = suggestion
+# CA1841: Prefer Dictionary.Contains methods
+dotnet_diagnostic.CA1841.severity = suggestion
+# CA1844: Provide memory-based overrides of async methods when subclassing 'Stream'
+dotnet_diagnostic.CA1844.severity = suggestion
+# CA1845: Use span-based 'string.Concat'
+dotnet_diagnostic.CA1845.severity = suggestion
+# CA1846: Prefer AsSpan over Substring
+dotnet_diagnostic.CA1846.severity = suggestion
+# CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
+dotnet_diagnostic.CA1847.severity = suggestion
+# CA1852: Seal internal types
+dotnet_diagnostic.CA1852.severity = suggestion
+# CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
+dotnet_diagnostic.CA1854.severity = suggestion
+# CA1855: Prefer 'Clear' over 'Fill'
+dotnet_diagnostic.CA1855.severity = suggestion
+# CA1856: Incorrect usage of ConstantExpected attribute
+dotnet_diagnostic.CA1856.severity = suggestion
+# CA1857: A constant is expected for the parameter
+dotnet_diagnostic.CA1857.severity = suggestion
+# CA1858: Use 'StartsWith' instead of 'IndexOf'
+dotnet_diagnostic.CA1858.severity = suggestion
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = suggestion
+# CA2008: Do not create tasks without passing a TaskScheduler
+dotnet_diagnostic.CA2008.severity = suggestion
+# CA2012: Use ValueTask correctly
+dotnet_diagnostic.CA2012.severity = suggestion
+# CA2201: Do not raise reserved exception types
+dotnet_diagnostic.CA2201.severity = suggestion
+# CA2249: Use string.Contains instead of string.IndexOf to improve readability.
+dotnet_diagnostic.CA2249.severity = suggestion
+# IDE0005: Remove unnecessary usings
+dotnet_diagnostic.IDE0005.severity = suggestion
+# IDE0020: Use pattern matching to avoid is check followed by a cast (with variable)
+dotnet_diagnostic.IDE0020.severity = suggestion
+# IDE0029: Use coalesce expression (non-nullable types)
+dotnet_diagnostic.IDE0029.severity = suggestion
+# IDE0030: Use coalesce expression (nullable types)
+dotnet_diagnostic.IDE0030.severity = suggestion
+# IDE0031: Use null propagation
+dotnet_diagnostic.IDE0031.severity = suggestion
+# IDE0038: Use pattern matching to avoid is check followed by a cast (without variable)
+dotnet_diagnostic.IDE0038.severity = suggestion
+# IDE0044: Make field readonly
+dotnet_diagnostic.IDE0044.severity = suggestion
+# IDE0051: Remove unused private members
+dotnet_diagnostic.IDE0051.severity = suggestion
+# IDE0059: Unnecessary assignment to a value
+dotnet_diagnostic.IDE0059.severity = suggestion
+# IDE0060: Remove unused parameters
+dotnet_diagnostic.IDE0060.severity = suggestion
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = suggestion
+# IDE0200: Lambda expression can be removed
+dotnet_diagnostic.IDE0200.severity = suggestion
+
+# CA2016: Forward the 'CancellationToken' parameter to methods that take one
+dotnet_diagnostic.CA2016.severity = suggestion
+
+# Defaults for content in the shared src/ and shared runtime dir
+
+[{**/Shared/runtime/**.{cs,vb},src/Shared/test/Shared.Tests/runtime/**.{cs,vb},**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
+# CA1822: Make member static
+dotnet_diagnostic.CA1822.severity = silent
+# IDE0011: Use braces
+dotnet_diagnostic.IDE0011.severity = silent
+# IDE0055: Fix formatting
+dotnet_diagnostic.IDE0055.severity = silent
+# IDE0060: Remove unused parameters
+dotnet_diagnostic.IDE0060.severity = silent
+# IDE0062: Make local function static
+dotnet_diagnostic.IDE0062.severity = silent
+# IDE0161: Convert to file-scoped namespace
+dotnet_diagnostic.IDE0161.severity = silent
+
+[{**/Shared/**.cs,**/microsoft.extensions.hostfactoryresolver.sources/**.{cs,vb}}]
+# IDE0005: Remove unused usings. Ignore for shared src files since imports for those depend on the projects in which they are included.
+dotnet_diagnostic.IDE0005.severity = silent
+
+[{*.razor.cs,src/Aspire.Dashboard/Components/**.cs}]
+# CA2007: Consider calling ConfigureAwait on the awaited task
+dotnet_diagnostic.CA2007.severity = silent
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:warning
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+
+dotnet_style_readonly_field = true:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+
+
diff --git a/.gitattributes b/.gitattributes
index 1ff0c42..671f86b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,63 +1,60 @@
-###############################################################################
# Set default behavior to automatically normalize line endings.
-###############################################################################
* text=auto
-###############################################################################
-# Set default behavior for command prompt diff.
-#
-# This is need for earlier builds of msysgit that does not have it on by
-# default for csharp files.
-# Note: This is only used by command line
-###############################################################################
-#*.cs diff=csharp
+# Collapse these files in PRs by default
+*.xlf linguist-generated=true
+*.lcl linguist-generated=true
-###############################################################################
-# Set the merge driver for project and solution files
-#
-# 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
-# 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
-###############################################################################
-#*.sln merge=binary
-#*.csproj merge=binary
-#*.vbproj merge=binary
-#*.vcxproj merge=binary
-#*.vcproj merge=binary
-#*.dbproj merge=binary
-#*.fsproj merge=binary
-#*.lsproj merge=binary
-#*.wixproj merge=binary
-#*.modelproj merge=binary
-#*.sqlproj merge=binary
-#*.wwaproj merge=binary
+*.jpg binary
+*.png binary
+*.gif binary
-###############################################################################
-# behavior for image files
-#
-# image files are treated as binary by default.
-###############################################################################
-#*.jpg binary
-#*.png binary
-#*.gif binary
+# Force bash scripts to always use lf line endings so that if a repo is accessed
+# in Unix via a file share from Windows, the scripts will work.
+*.in text eol=lf
+*.sh text eol=lf
-###############################################################################
-# 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
-# entries below.
-###############################################################################
-#*.doc diff=astextplain
-#*.DOC diff=astextplain
-#*.docx diff=astextplain
-#*.DOCX diff=astextplain
-#*.dot diff=astextplain
-#*.DOT diff=astextplain
-#*.pdf diff=astextplain
-#*.PDF diff=astextplain
-#*.rtf diff=astextplain
-#*.RTF diff=astextplain
+# Likewise, force cmd and batch scripts to always use crlf
+*.cmd text eol=crlf
+*.bat text eol=crlf
+
+*.cs text=auto diff=csharp
+*.vb text=auto
+*.resx text=auto
+*.c text=auto
+*.cpp text=auto
+*.cxx text=auto
+*.h text=auto
+*.hxx text=auto
+*.py text=auto
+*.rb text=auto
+*.java text=auto
+*.html text=auto
+*.htm text=auto
+*.css text=auto
+*.scss text=auto
+*.sass text=auto
+*.less text=auto
+*.js text=auto
+*.lisp text=auto
+*.clj text=auto
+*.sql text=auto
+*.php text=auto
+*.lua text=auto
+*.m text=auto
+*.asm text=auto
+*.erl text=auto
+*.fs text=auto
+*.fsx text=auto
+*.hs text=auto
+
+*.csproj text=auto
+*.vbproj text=auto
+*.fsproj text=auto
+*.dbproj text=auto
+*.sln text=auto eol=crlf
+
+# Set linguist language for .h files explicitly based on
+# https://github.com/github/linguist/issues/1626#issuecomment-401442069
+# this only affects the repo's language statistics
+*.h linguist-language=C
diff --git a/.gitignore b/.gitignore
index 9491a2f..b53c09b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,363 +1,146 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+syntax: glob
+
+### VisualStudio ###
+
+# Tools directory
+.dotnet/
+.packages/
+.tools/
# User-specific files
-*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
# Build results
+
+artifacts/
+artifacts_stage_1/
[Dd]ebug/
-[Dd]ebugPublic/
[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
+x64/ !eng/common/cross/x64/
+x86/ !eng/common/cross/x86/
[Bb]in/
[Oo]bj/
-[Oo]ut/
-[Ll]og/
-[Ll]ogs/
+msbuild.log
+msbuild.err
+msbuild.wrn
+*.binlog
-# Visual Studio 2015/2017 cache/options directory
+# Visual Studio 2015
.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-# Visual Studio 2017 auto generated files
-Generated\ Files/
+# Visual Studio 2015 Pre-CTP6
+*.sln.ide
+*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
-# NUnit
+#NUNIT
*.VisualState.xml
TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
-# TeamCity is a build add-in
-_TeamCity*
-
# DotCover is a Code Coverage Tool
*.dotCover
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
+*.nupkg
+**/packages/*
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
+### Windows ###
-# Visual Studio 6 build log
-*.plg
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
-# Visual Studio 6 workspace options file
-*.opt
+# Folder config file
+Desktop.ini
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
+# Windows shortcuts
+*.lnk
-# FAKE - F# Make
-.fake/
+### Linux ###
-# CodeRush personal settings
-.cr/personal
+*~
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
+# KDE directory preferences
+.directory
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
+### OSX ###
-# Tabs Studio
-*.tss
+.DS_Store
+.AppleDouble
+.LSOverride
-# Telerik's JustMock configuration file
-*.jmconfig
+# Icon must end with two \r
+Icon
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
+# Thumbnails
+._*
-# OpenCover UI analysis results
-OpenCover/
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
-# Azure Stream Analytics local run output
-ASALocalRun/
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
-# MSBuild Binary and Structured Log
-*.binlog
+# vim temporary files
+[._]*.s[a-w][a-z]
+[._]s[a-w][a-z]
+*.un~
+Session.vim
+.netrwhist
+*~
+
+# Visual Studio Code
+.vscode/
+
+# Private test configuration and binaries.
+config.ps1
+**/IISApplications
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
+# Node.js modules
+node_modules/
+
+# Python Compile Outputs
-# Local History for Visual Studio
-.localhistory/
+*.pyc
-# BeatPulse healthcheck temp database
-healthchecksdb
+# IntelliJ
+.idea/
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
+# vscode python env files
+.env
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
+# Storage emulator storage files
+**/.azurite/*
-# Fody - auto-generated XML schema
-FodyWeavers.xsd
\ No newline at end of file
+# Azure Developer CLI files
+/playground/**/.gitignore
+/playground/**/azure.yaml
+/playground/**/next-steps.md
diff --git a/AspireDemo.code-workspace b/AspireDemo.code-workspace
deleted file mode 100644
index 876a149..0000000
--- a/AspireDemo.code-workspace
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "folders": [
- {
- "path": "."
- }
- ],
- "settings": {}
-}
\ No newline at end of file
diff --git a/GagoAspireApp.AppInit/GagoAspireApp.AppInit.csproj b/GagoAspireApp.AppInit/GagoAspireApp.AppInit.csproj
deleted file mode 100644
index 9d008d8..0000000
--- a/GagoAspireApp.AppInit/GagoAspireApp.AppInit.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
diff --git a/GagoAspireApp.Architecture/Messaging/AMQPRemoteException.cs b/GagoAspireApp.Architecture/Messaging/AMQPRemoteException.cs
deleted file mode 100644
index 902a5c1..0000000
--- a/GagoAspireApp.Architecture/Messaging/AMQPRemoteException.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace GagoAspireApp.Architecture.Messaging;
-
-
-[Serializable]
-public class AMQPRemoteException : Exception
-{
- private readonly string remoteStackTrace;
-
- public AMQPRemoteException() : this(message: null, remoteStackTrace: null, inner: null) { }
- public AMQPRemoteException(string message) : base(message) { }
- public AMQPRemoteException(string message, Exception inner) : base(message, inner) { }
- public AMQPRemoteException(string message, string remoteStackTrace, Exception inner) : base(message, inner) { this.remoteStackTrace = remoteStackTrace; }
-
-
- public override string StackTrace => this.remoteStackTrace;
-
-
- protected AMQPRemoteException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/AckResult.cs b/GagoAspireApp.Architecture/Messaging/Consumer/Actions/AckResult.cs
deleted file mode 100644
index e73ac7b..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/AckResult.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using Dawn;
-using RabbitMQ.Client.Events;
-using RabbitMQ.Client;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-
-public class AckResult : IAMQPResult
-{
- public void Execute(IModel model, BasicDeliverEventArgs delivery)
- {
- Guard.Argument(model).NotNull();
- Guard.Argument(delivery).NotNull();
-
- model.BasicAck(delivery.DeliveryTag, false);
- }
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/IAMQPResult.cs b/GagoAspireApp.Architecture/Messaging/Consumer/Actions/IAMQPResult.cs
deleted file mode 100644
index 86e266f..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/IAMQPResult.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using RabbitMQ.Client;
-using RabbitMQ.Client.Events;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-
-
-public interface IAMQPResult
-{
- void Execute(IModel model, BasicDeliverEventArgs delivery);
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/NackResult.cs b/GagoAspireApp.Architecture/Messaging/Consumer/Actions/NackResult.cs
deleted file mode 100644
index f407820..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/NackResult.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Dawn;
-using RabbitMQ.Client.Events;
-using RabbitMQ.Client;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-
-public class NackResult : IAMQPResult
-{
- public bool Requeue { get; }
-
- public NackResult(bool requeue)
- {
- this.Requeue = requeue;
- }
-
- public void Execute(IModel model, BasicDeliverEventArgs delivery)
- {
- Guard.Argument(model).NotNull();
- Guard.Argument(delivery).NotNull();
-
- model.BasicNack(delivery.DeliveryTag, false, this.Requeue);
- }
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/RejectResult.cs b/GagoAspireApp.Architecture/Messaging/Consumer/Actions/RejectResult.cs
deleted file mode 100644
index 64336e4..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/Actions/RejectResult.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Dawn;
-using RabbitMQ.Client.Events;
-using RabbitMQ.Client;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-
-public class RejectResult : IAMQPResult
-{
- public bool Requeue { get; }
-
- public RejectResult(bool requeue)
- {
- this.Requeue = requeue;
- }
-
- public void Execute(IModel model, BasicDeliverEventArgs delivery)
- {
- Guard.Argument(model).NotNull();
- Guard.Argument(delivery).NotNull();
-
- model.BasicReject(delivery.DeliveryTag, this.Requeue);
- }
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumer.cs b/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumer.cs
deleted file mode 100644
index 970b90c..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumer.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-using Dawn;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using RabbitMQ.Client;
-using RabbitMQ.Client.Events;
-using System.Diagnostics;
-using OpenTelemetry.Context.Propagation;
-using OpenTelemetry;
-using System.Text;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-
-public class AsyncQueueConsumer : ConsumerBase
- where TResponse : Task
- where TRequest : class
-{
- private AsyncQueueConsumerParameters parameters;
-
- protected static readonly ActivitySource activitySource = new(MessagingTelemetryNames.GetName(nameof(AsyncQueueConsumer)));
- private static readonly TextMapPropagator propagator = Propagators.DefaultTextMapPropagator;
-
- #region Constructors
-
- public AsyncQueueConsumer(ILogger logger, AsyncQueueConsumerParameters parameters, IServiceProvider serviceProvider)
- : base(logger, parameters, serviceProvider)
- {
- this.parameters = Guard.Argument(parameters).NotNull().Value;
- this.parameters.Validate();
- }
-
- #endregion
-
-
- protected override IBasicConsumer BuildConsumer()
- {
- Guard.Argument(this.Model).NotNull();
-
- var consumer = new AsyncEventingBasicConsumer(this.Model);
-
- consumer.Received += this.Receive;
-
- return consumer;
- }
-
- public async Task Receive(object sender, BasicDeliverEventArgs delivery)
- {
- Guard.Argument(delivery).NotNull();
- Guard.Argument(delivery.BasicProperties).NotNull();
-
-
- var parentContext = propagator.Extract(default, delivery.BasicProperties, this.ExtractTraceContextFromBasicProperties);
- Baggage.Current = parentContext.Baggage;
-
- using Activity receiveActivity = activitySource.StartActivity("AsyncQueueConsumer.Receive", ActivityKind.Consumer, parentContext.ActivityContext) ?? new Activity("?AsyncQueueConsumer.Receive");
-
- receiveActivity.AddTag("Queue", this.parameters.QueueName);
- receiveActivity.AddTag("MessageId", delivery.BasicProperties.MessageId);
- receiveActivity.AddTag("CorrelationId", delivery.BasicProperties.CorrelationId);
-
- receiveActivity.SetTag("messaging.system", "rabbitmq");
- receiveActivity.SetTag("messaging.destination_kind", "queue");
- receiveActivity.SetTag("messaging.destination", delivery.Exchange);
- receiveActivity.SetTag("messaging.rabbitmq.routing_key", delivery.RoutingKey);
-
- IAMQPResult result = this.TryDeserialize(receiveActivity, delivery, out TRequest request)
- ? await this.Dispatch(receiveActivity, delivery, request)
- : new RejectResult(false);
-
- result.Execute(this.Model, delivery);
-
- //receiveActivity?.SetEndTime(DateTime.UtcNow);
- }
-
- private IEnumerable ExtractTraceContextFromBasicProperties(IBasicProperties props, string key)
- {
- try
- {
- if (props.Headers.TryGetValue(key, out var value))
- {
- var bytes = value as byte[];
- return new[] { Encoding.UTF8.GetString(bytes) };
- }
- }
- catch (Exception ex)
- {
- this.logger.LogError(ex, "Failed to extract trace context.");
- }
-
- return Enumerable.Empty();
- }
-
- private bool TryDeserialize(Activity receiveActivity, BasicDeliverEventArgs receivedItem, out TRequest request)
- {
- Guard.Argument(receivedItem).NotNull();
-
- bool returnValue = true;
-
- request = default;
- try
- {
- request = this.parameters.Serializer.Deserialize(eventArgs: receivedItem);
- }
- catch (Exception exception)
- {
- returnValue = false;
-
- receiveActivity.SetStatus(ActivityStatusCode.Error, exception.ToString());
-
- this.logger.LogWarning("Message rejected during deserialization {exception}", exception);
- }
-
- return returnValue;
- }
-
- protected virtual async Task Dispatch(Activity receiveActivity, BasicDeliverEventArgs receivedItem, TRequest request)
- {
- Guard.Argument(receiveActivity).NotNull();
- Guard.Argument(receivedItem).NotNull();
-
- if (request == null) return new RejectResult(false);
-
- IAMQPResult returnValue;
-
- using Activity? dispatchActivity = activitySource.StartActivity(this.parameters.AdapterExpressionText, ActivityKind.Internal, receiveActivity.Context);
-
- //using (var logContext = new EnterpriseApplicationLogContext())
- //{
- try
- {
- TService service = this.parameters.ServiceProvider.GetRequiredService();
-
- if (this.parameters.DispatchScope == DispatchScope.RootScope)
- {
- await this.parameters.AdapterFunc(service, request);
- }
- else if (this.parameters.DispatchScope == DispatchScope.ChildScope)
- {
- using (var scope = this.parameters.ServiceProvider.CreateScope())
- {
- await this.parameters.AdapterFunc(service, request);
- }
- }
- returnValue = new AckResult();
- }
- catch (Exception exception)
- {
-
- this.logger.LogWarning("Exception on processing message {queueName} {exception}", this.parameters.QueueName, exception);
- returnValue = new NackResult(this.parameters.RequeueOnCrash);
-
- dispatchActivity?.SetStatus(ActivityStatusCode.Error, exception.ToString());
- }
- //}
-
-
-
- return returnValue;
- }
-}
\ No newline at end of file
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumerParameters.cs b/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumerParameters.cs
deleted file mode 100644
index 7ff1977..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncQueueConsumerParameters.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using GagoAspireApp.Architecture.Messaging.Serialization;
-using Dawn;
-using System.Diagnostics;
-using System.Linq.Expressions;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-public class AsyncQueueConsumerParameters : ConsumerBaseParameters
- where TResponse : Task
- where TRequest : class
-{
- public IServiceProvider ServiceProvider { get; private set; }
- public AsyncQueueConsumerParameters WithServiceProvider(IServiceProvider serviceProvider)
- {
- this.ServiceProvider = serviceProvider;
- return this;
- }
-
- public IAMQPSerializer Serializer { get; private set; }
- public AsyncQueueConsumerParameters WithSerializer(IAMQPSerializer serializer)
- {
- this.Serializer = serializer;
- return this;
- }
-
- public Expression>? AdapterExpression { get; private set; }
- public string? AdapterExpressionText { get; private set; }
- public Func AdapterFunc { get; private set; }
- public AsyncQueueConsumerParameters WithAdapter(Expression> adapterExpression)
- {
- this.AdapterExpression = adapterExpression;
- this.AdapterFunc = adapterExpression.Compile();
- this.AdapterExpressionText = adapterExpression.ToString();
- return this;
- }
-
- /*public AsyncQueueConsumerParameters WithEnterpriseApplicationLog(Func adapterFunc)
- {
- Guard.Argument(this.AdapterFunc).NotNull();
-
- Func oldAdapterFunc = this.AdapterFunc;
-
- this.AdapterFunc = async (svc, msg) =>
- {
- using (var logContext = new EnterpriseApplicationLogContext())
- {
- //logContext.SetIdentity(nameof(DiscordSyncService.SyncAsync));
- logContext.AddArgument("msg", msg);
- return await logContext.ExecuteWithLogAsync(() => oldAdapterFunc(svc, msg));
- }
- };
- return this;
- }*/
-
- public DispatchScope DispatchScope { get; private set; }
- public AsyncQueueConsumerParameters WithDispatchScope(DispatchScope dispatchScope)
- {
- this.DispatchScope = dispatchScope;
- return this;
- }
-
- public bool RequeueOnCrash { get; private set; }
- public AsyncQueueConsumerParameters WithRequeueOnCrash(bool requeueOnCrash = true)
- {
- this.RequeueOnCrash = requeueOnCrash;
- return this;
- }
-
-
- public AsyncQueueConsumerParameters WithDispatchInRootScope()
- => this.WithDispatchScope(DispatchScope.RootScope);
-
- public AsyncQueueConsumerParameters WithDispatchInChildScope()
- => this.WithDispatchScope(DispatchScope.ChildScope);
-
-
- public override void Validate()
- {
- base.Validate();
-
- Guard.Argument(this.ServiceProvider).NotNull();
- Guard.Argument(this.Serializer).NotNull();
- Guard.Argument(this.AdapterFunc).NotNull();
- Guard.Argument(this.DispatchScope).NotIn(DispatchScope.None);
- }
-
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncRpcConsumer.cs b/GagoAspireApp.Architecture/Messaging/Consumer/AsyncRpcConsumer.cs
deleted file mode 100644
index 5f8fadc..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/AsyncRpcConsumer.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using GagoAspireApp.Architecture.Messaging.Consumer.Actions;
-using Dawn;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using RabbitMQ.Client;
-using RabbitMQ.Client.Events;
-using System.Diagnostics;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-
-public class AsyncRpcConsumer : AsyncQueueConsumer>
- where TResponse : class
- where TRequest : class
-{
- private AsyncQueueConsumerParameters> parameters;
-
- public AsyncRpcConsumer(ILogger logger, AsyncQueueConsumerParameters> parameters, IServiceProvider serviceProvider)
- : base(logger, parameters, serviceProvider)
- {
- this.parameters = Guard.Argument(parameters).NotNull().Value;
- this.parameters.Validate();
- }
-
- protected override async Task Dispatch(Activity receiveActivity, BasicDeliverEventArgs receivedItem, TRequest request)
- {
- Guard.Argument(receivedItem).NotNull();
- Guard.Argument(receiveActivity).NotNull();
- Guard.Argument(request).NotNull();
-
- if (receivedItem.BasicProperties.ReplyTo == null)
- {
- this.logger.LogWarning("Message cannot be processed in RPC Flow because original message didn't have a ReplyTo.");
-
- return new RejectResult(false);
- }
-
- TResponse responsePayload = default;
-
- using (Activity? dispatchActivity = activitySource.StartActivity(this.parameters.AdapterExpressionText, ActivityKind.Internal, receiveActivity.Context))
- {
- try
- {
- TService service = this.parameters.ServiceProvider.GetRequiredService();
-
- if (this.parameters.DispatchScope == DispatchScope.RootScope)
- {
- responsePayload = await this.parameters.AdapterFunc(service, request);
- }
- else if (this.parameters.DispatchScope == DispatchScope.ChildScope)
- {
- using (var scope = this.parameters.ServiceProvider.CreateScope())
- {
- responsePayload = await this.parameters.AdapterFunc(service, request);
- }
- }
- }
- catch (Exception exception)
- {
- dispatchActivity?.SetStatus(ActivityStatusCode.Error, exception.ToString());
-
- this.SendReply(dispatchActivity, receivedItem, null, exception);
-
- return new NackResult(this.parameters.RequeueOnCrash);
- }
- }
-
- using (Activity? replyActivity = activitySource.StartActivity(this.parameters.AdapterExpressionText, ActivityKind.Internal, receiveActivity.Context))
- {
- this.SendReply(replyActivity, receivedItem, responsePayload);
- }
- return new AckResult();
- }
-
- private void SendReply(Activity activity, BasicDeliverEventArgs receivedItem, TResponse responsePayload = null, Exception exception = null)
- {
- Guard.Argument(receivedItem).NotNull();
- Guard.Argument(responsePayload).NotNull();
-
-
- IBasicProperties responseProperties = this.Model.CreateBasicProperties()
- .SetMessageId()
- .IfFunction(it => exception != null, it => it.SetException(exception))
- .SetTelemetry(activity)
- .SetCorrelationId(receivedItem.BasicProperties);
-
- activity?.AddTag("Queue", receivedItem.BasicProperties.ReplyTo);
- activity?.AddTag("MessageId", responseProperties.MessageId);
- activity?.AddTag("CorrelationId", responseProperties.CorrelationId);
-
- this.Model.BasicPublish(string.Empty,
- receivedItem.BasicProperties.ReplyTo,
- responseProperties,
- exception != null
- ? Array.Empty()
- : this.parameters.Serializer.Serialize(basicProperties: responseProperties, objectToSerialize: responsePayload)
- );
-
- //replyActivity?.SetEndTime(DateTime.UtcNow);
- }
-
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBase.cs b/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBase.cs
deleted file mode 100644
index 75169d2..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBase.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using Dawn;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Polly;
-using RabbitMQ.Client;
-using RabbitMQ.Client.Exceptions;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-public abstract class ConsumerBase : BackgroundService
-{
-
- protected readonly ILogger logger;
- private readonly IServiceProvider serviceProvider;
- protected IConnection connection;
- protected IBasicConsumer consumer;
- private string consumerTag;
- private ConsumerBaseParameters parameters;
-
- protected IModel Model { get; private set; }
-
-
- #region Constructors
-
- protected ConsumerBase(ILogger logger, ConsumerBaseParameters parameters, IServiceProvider serviceProvider)
- {
- this.logger = Guard.Argument(logger).NotNull().Value;
- this.parameters = Guard.Argument(parameters).NotNull().Value;
- this.parameters.Validate();
- this.serviceProvider = serviceProvider;
- }
-
-
- #endregion
-
- protected override async Task ExecuteAsync(CancellationToken stoppingToken)
- {
- this.connection = this.parameters.ConnectionFactoryFunc(this.serviceProvider);
-
- if (this.parameters.Configurer != null)
- {
- using var tmpModel = this.connection.CreateModel();
- this.parameters.Configurer(this.serviceProvider, tmpModel);
- }
-
- await this.WaitQueueCreationAsync();
-
- this.Model = this.connection.CreateModel();
-
- this.Model.BasicQos(0, this.parameters.PrefetchCount, false);
-
- this.consumer = this.BuildConsumer();
-
- DateTimeOffset startTime = DateTimeOffset.UtcNow;
-
- this.logger.LogInformation($"Consuming Queue {this.parameters.QueueName} since: {startTime}");
-
- this.consumerTag = this.Model.BasicConsume(
- queue: this.parameters.QueueName,
- autoAck: false,
- consumer: this.consumer);
-
- int timeToDisplay = (int)this.parameters.DisplayLoopInConsoleEvery.TotalSeconds;
-
-
- long loopCount = 0;
- while (!stoppingToken.IsCancellationRequested)
- {
- loopCount++;
- string logMessage = $"Consuming Queue {this.parameters.QueueName} since: {startTime} uptime: {DateTimeOffset.Now - startTime}";
-
- if (loopCount % timeToDisplay == 0)
- this.logger.LogInformation(logMessage);
- else
- this.logger.LogTrace(logMessage);
-
- await Task.Delay(1000, stoppingToken);
- }
- }
-
- protected virtual async Task WaitQueueCreationAsync()
- {
- await Policy
- .Handle()
- .WaitAndRetryAsync(this.parameters.TestQueueRetryCount, retryAttempt =>
- {
- var timeToWait = TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));
- this.logger.LogWarning("Queue {queueName} not found... We will try in {tempo}.", this.parameters.QueueName, timeToWait);
- return timeToWait;
- })
- .ExecuteAsync(() =>
- {
- using IModel testModel = this.connection.CreateModel();
- testModel.QueueDeclarePassive(this.parameters.QueueName);
- return Task.CompletedTask;
- });
- }
-
- protected abstract IBasicConsumer BuildConsumer();
-
- public override void Dispose()
- {
- if (this.Model != null && !string.IsNullOrWhiteSpace(this.consumerTag))
- this.Model.BasicCancelNoWait(this.consumerTag);
- if (this.Model != null)
- {
- this.Model.Dispose();
- this.Model = null;
- }
-
- base.Dispose();
- }
-
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBaseParameters.cs b/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBaseParameters.cs
deleted file mode 100644
index 716beec..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/ConsumerBaseParameters.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Dawn;
-using RabbitMQ.Client;
-
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-public class ConsumerBaseParameters
-{
-
- public string QueueName { get; private set; }
- public ConsumerBaseParameters WithQueueName(string queueName)
- {
- this.QueueName = queueName;
- return this;
- }
-
- public Action Configurer { get; private set; }
- public ConsumerBaseParameters WithTopology(Action configurer)
- {
- this.Configurer = configurer;
- return this;
- }
-
- public ushort PrefetchCount { get; private set; }
- public ConsumerBaseParameters WithPrefetchCount(ushort prefetchCount)
- {
- this.PrefetchCount = prefetchCount;
- return this;
- }
-
- public Func ConnectionFactoryFunc { get; private set; }
- public ConsumerBaseParameters WithConnectionFactoryFunc(Func connectionFactoryFunc)
- {
- this.ConnectionFactoryFunc = connectionFactoryFunc;
- return this;
- }
-
- public int TestQueueRetryCount { get; private set; }
- public ConsumerBaseParameters WithTestQueueRetryCount(int testQueueRetryCount)
- {
- this.TestQueueRetryCount = testQueueRetryCount;
- return this;
- }
-
- public TimeSpan DisplayLoopInConsoleEvery { get; private set; }
- public ConsumerBaseParameters WithDisplayLoopInConsoleEvery(TimeSpan timeToDisplay)
- {
- this.DisplayLoopInConsoleEvery = timeToDisplay;
- return this;
- }
-
- public virtual void Validate()
- {
- Guard.Argument(this.QueueName).NotNull().NotEmpty().NotWhiteSpace();
- Guard.Argument(this.PrefetchCount).NotZero().NotNegative();
- Guard.Argument(this.TestQueueRetryCount).NotNegative();
- Guard.Argument(this.ConnectionFactoryFunc).NotNull();
- }
-
-
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Consumer/DispatchScope.cs b/GagoAspireApp.Architecture/Messaging/Consumer/DispatchScope.cs
deleted file mode 100644
index 9eadd49..0000000
--- a/GagoAspireApp.Architecture/Messaging/Consumer/DispatchScope.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace GagoAspireApp.Architecture.Messaging.Consumer;
-
-public enum DispatchScope
-{
- None,
- RootScope,
- ChildScope
-}
diff --git a/GagoAspireApp.Architecture/Messaging/Extensions.RabbitMQ.cs b/GagoAspireApp.Architecture/Messaging/Extensions.RabbitMQ.cs
deleted file mode 100644
index bac9530..0000000
--- a/GagoAspireApp.Architecture/Messaging/Extensions.RabbitMQ.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using Dawn;
-using RabbitMQ.Client;
-using System.Text;
-
-namespace GagoAspireApp.Architecture.Messaging;
-
-public static partial class RabbitMQExtensions
-{
- public static IBasicProperties SetMessageId(this IBasicProperties basicProperties, string messageId = null)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
- basicProperties.MessageId = messageId ?? Guid.NewGuid().ToString("D");
- return basicProperties;
- }
-
- public static IBasicProperties SetCorrelationId(this IBasicProperties basicProperties, IBasicProperties originalBasicProperties)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
- ArgumentNullException.ThrowIfNull(originalBasicProperties);
-
- return basicProperties.SetCorrelationId(originalBasicProperties.MessageId);
- }
-
- public static IBasicProperties SetCorrelationId(this IBasicProperties basicProperties, string correlationId)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
- if (string.IsNullOrEmpty(correlationId)) throw new ArgumentException($"'{nameof(correlationId)}' cannot be null or empty.", nameof(correlationId));
-
- basicProperties.CorrelationId = correlationId;
- return basicProperties;
- }
-
- public static IBasicProperties SetDurable(this IBasicProperties basicProperties, bool durable = true)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
- basicProperties.Persistent = durable;
- return basicProperties;
- }
-
- public static IBasicProperties SetReplyTo(this IBasicProperties basicProperties, string replyTo = null)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
-
- if (!string.IsNullOrEmpty(replyTo))
- basicProperties.ReplyTo = replyTo;
-
- return basicProperties;
- }
-
- public static IBasicProperties SetAppId(this IBasicProperties basicProperties, string appId = null)
- {
- ArgumentNullException.ThrowIfNull(basicProperties);
-
- if (!string.IsNullOrEmpty(appId))
- basicProperties.AppId = appId;
-
- return basicProperties;
- }
-
- private static string AsString(this object objectToConvert)
- {
- return objectToConvert != null ? Encoding.UTF8.GetString((byte[])objectToConvert) : null;
- }
-
- public static string AsString(this IDictionary dic, string key)
- {
- object content = dic?[key];
- return content != null ? Encoding.UTF8.GetString((byte[])content) : null;
- }
-
- public static List AsStringList(this object objectToConvert)
- {
- ArgumentNullException.ThrowIfNull(objectToConvert);
- var routingKeyList = (List