From 02e61322ece51469b94a6fcc2cd0e87e8d09bf17 Mon Sep 17 00:00:00 2001 From: damon Date: Mon, 3 Jun 2024 18:35:49 +0800 Subject: [PATCH 1/5] Use `Parallel.ForEachAsync` instead of `Task.WhenAll` . --- Source/Euonia.Bus/Core/HandlerContext.cs | 34 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/Source/Euonia.Bus/Core/HandlerContext.cs b/Source/Euonia.Bus/Core/HandlerContext.cs index 0ce0d41..da48197 100644 --- a/Source/Euonia.Bus/Core/HandlerContext.cs +++ b/Source/Euonia.Bus/Core/HandlerContext.cs @@ -91,7 +91,6 @@ public virtual async Task HandleAsync(string channel, object message, MessageCon return; } - var tasks = new List(); using var scope = _provider.GetRequiredService().CreateScope(); if (!_handlerContainer.TryGetValue(channel, out var handling)) @@ -101,22 +100,35 @@ public virtual async Task HandleAsync(string channel, object message, MessageCon // Get handler instance from service provider using Expression Tree - foreach (var factory in handling) + if (handling.Count == 0) { - var handler = factory(scope.ServiceProvider); - tasks.Add(handler(message, context, cancellationToken)); + throw new InvalidOperationException("No handler registered for message"); } - if (tasks.Count == 0) + _logger?.LogInformation("Message {Id} is being handled", context.MessageId); + + if (handling.Count == 1) { - return; + var handler = handling.First()(scope.ServiceProvider); + await handler(message, context, cancellationToken); } - - await Task.WhenAll(tasks).ContinueWith(task => + else { - task.WaitAndUnwrapException(cancellationToken); - _logger?.LogInformation("Message {Id} was completed handled", context.MessageId); - }, cancellationToken); + await Parallel.ForEachAsync(handling, cancellationToken, async (factory, token) => + { + try + { + var handler = factory(scope.ServiceProvider); + await handler(message, context, token); + } + catch (Exception ex) + { + _logger?.LogError(ex, "Error occurred while handling message {Id}", context.MessageId); + } + }); + } + + _logger?.LogInformation("Message {Id} was completed handled", context.MessageId); } #endregion From 4f817c92ecda4204980c9c59a8eec4a09dde0192 Mon Sep 17 00:00:00 2001 From: damon Date: Thu, 4 Jul 2024 23:27:25 +0800 Subject: [PATCH 2/5] Update dependence package versions. --- Directory.Packages.props | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3b823a7..799d383 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -17,14 +17,14 @@ - + - + @@ -37,11 +37,11 @@ - + - - - + + + @@ -112,7 +112,7 @@ - + From 7a8a9dc0ce3103604936b79a77710f83c57f3f07 Mon Sep 17 00:00:00 2001 From: damon Date: Thu, 4 Jul 2024 23:28:39 +0800 Subject: [PATCH 3/5] Add LikeOperator to Compares two strings --- Source/Euonia.Core/System/LikeOperator.cs | 203 ++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 Source/Euonia.Core/System/LikeOperator.cs diff --git a/Source/Euonia.Core/System/LikeOperator.cs b/Source/Euonia.Core/System/LikeOperator.cs new file mode 100644 index 0000000..05747b6 --- /dev/null +++ b/Source/Euonia.Core/System/LikeOperator.cs @@ -0,0 +1,203 @@ +#nullable enable +namespace System; + +/// +/// The LikeOperator class is used to compare two strings using the * and ? wildcards. +/// +public class LikeOperator +{ + /// + /// Compares two strings using the * and ? wildcards. + /// + public static bool LikeString(string? content, string? pattern, bool ignoreCase = true, bool useInvariantCulture = true) + { + if (content == null && pattern == null) + return true; + if (content == null || pattern == null) + return false; + + var patternSpan = pattern.AsSpan(); + var contentSpan = content.AsSpan(); + + return LikeString(contentSpan, patternSpan, ignoreCase, useInvariantCulture); + } + + /// + /// Compares two spans using the * and ? wildcards. + /// + public static bool LikeString(ReadOnlySpan contentSpan, ReadOnlySpan patternSpan, bool ignoreCase = true, bool useInvariantCulture = true) + { + var zeroOrMoreChars = '*'; + var oneChar = '?'; + + if (patternSpan.Length == 1) + { + ref readonly char patternItem = ref patternSpan[0]; + if (patternItem == zeroOrMoreChars) + { + return true; + } + } + + if (contentSpan.Length == 1) + { + ref readonly var patternItem = ref patternSpan[0]; + if (patternItem == oneChar) + { + return true; + } + } + + var zeroOrMorePatternCount = 0; + var onePatternCount = 0; + foreach (var @char in patternSpan) + { + ref readonly char patternItem = ref @char; + if (patternItem == zeroOrMoreChars) + { + zeroOrMorePatternCount++; + } + else if (patternItem == oneChar) + { + onePatternCount++; + } + } + + if (zeroOrMorePatternCount + onePatternCount == patternSpan.Length) + { + if (zeroOrMorePatternCount > 0) + { + return true; + } + + if (patternSpan.Length == contentSpan.Length) + { + return true; + } + } + + EqualsCharDelegate equalsChar; + if (ignoreCase) + { + if (useInvariantCulture) + { + equalsChar = EqualsCharInvariantCultureIgnoreCase; + } + else + { + equalsChar = EqualsCharCurrentCultureIgnoreCase; + } + } + else + { + equalsChar = EqualsChar; + } + + return LikeStringCore(contentSpan, patternSpan, in zeroOrMoreChars, in oneChar, equalsChar); + } + + private static bool LikeStringCore(ReadOnlySpan contentSpan, ReadOnlySpan patternSpan, in char zeroOrMoreChars, in char oneChar, EqualsCharDelegate equalsChar) + { + var contentIndex = 0; + var patternIndex = 0; + while (contentIndex < contentSpan.Length && patternIndex < patternSpan.Length) + { + ref readonly var patternItem = ref patternSpan[patternIndex]; + if (patternItem == zeroOrMoreChars) + { + while (true) + { + if (patternIndex < patternSpan.Length) + { + ref readonly char nextPatternItem = ref patternSpan[patternIndex]; + if (nextPatternItem == zeroOrMoreChars) + { + patternIndex++; + continue; + } + } + + break; + } + + if (patternIndex == patternSpan.Length) + { + return true; + } + + while (contentIndex < contentSpan.Length) + { + if (LikeStringCore(contentSpan[contentIndex..], patternSpan[patternIndex..], in zeroOrMoreChars, in oneChar, equalsChar)) + { + return true; + } + + contentIndex++; + } + + return false; + } + + if (patternItem == oneChar) + { + contentIndex++; + patternIndex++; + } + else + { + if (contentIndex >= contentSpan.Length) + { + return false; + } + + ref readonly var contentItem = ref contentSpan[contentIndex]; + if (!equalsChar(in contentItem, in patternItem)) + { + return false; + } + + contentIndex++; + patternIndex++; + } + } + + if (contentIndex == contentSpan.Length) + { + while (true) + { + if (patternIndex < patternSpan.Length) + { + ref readonly char nextPatternItem = ref patternSpan[patternIndex]; + if (nextPatternItem == zeroOrMoreChars) + { + patternIndex++; + continue; + } + } + + break; + } + + return patternIndex == patternSpan.Length; + } + + return false; + } + + private static bool EqualsChar(in char contentItem, in char patternItem) + { + return contentItem == patternItem; + } + + private static bool EqualsCharCurrentCultureIgnoreCase(in char contentItem, in char patternItem) + { + return char.ToUpper(contentItem) == char.ToUpper(patternItem); + } + + private static bool EqualsCharInvariantCultureIgnoreCase(in char contentItem, in char patternItem) + { + return char.ToUpperInvariant(contentItem) == char.ToUpperInvariant(patternItem); + } + + private delegate bool EqualsCharDelegate(in char contentItem, in char patternItem); +} \ No newline at end of file From e890ad9250bc738ad2f04f35d5b49a533c895904 Mon Sep 17 00:00:00 2001 From: damon Date: Wed, 17 Jul 2024 23:26:33 +0800 Subject: [PATCH 4/5] Add summary. --- Euonia.sln | 1 + Source/Euonia.Bus.Abstract/DefaultIdentityProvider.cs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Euonia.sln b/Euonia.sln index b2f7e45..14dc06d 100644 --- a/Euonia.sln +++ b/Euonia.sln @@ -16,6 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution", "Solution", "{CC NuGet.config = NuGet.config project.props = project.props README.md = README.md + .editorconfig = .editorconfig EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{E57A56F3-7BAB-4DB5-9CE8-EC91985A6586}" diff --git a/Source/Euonia.Bus.Abstract/DefaultIdentityProvider.cs b/Source/Euonia.Bus.Abstract/DefaultIdentityProvider.cs index b1501b7..ce9d771 100644 --- a/Source/Euonia.Bus.Abstract/DefaultIdentityProvider.cs +++ b/Source/Euonia.Bus.Abstract/DefaultIdentityProvider.cs @@ -2,6 +2,9 @@ namespace Nerosoft.Euonia.Bus; +/// +/// The default message identity provider. +/// internal class DefaultIdentityProvider : IIdentityProvider { private readonly IdentityAccessor _accessor; From 9b50b25ea38c2e72daaea9c6f9cf2fa17c1f89b8 Mon Sep 17 00:00:00 2001 From: damon Date: Mon, 12 Aug 2024 21:28:56 +0800 Subject: [PATCH 5/5] Bump nuget package version. --- Directory.Packages.props | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 799d383..eb6201d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,11 +2,11 @@ true true - 6.0.31 + 6.0.32 7.0.20 - 8.0.6 - 2.63.0 - 3.9.0 + 8.0.7 + 2.65.0 + 3.13.0 @@ -14,7 +14,7 @@ - + @@ -24,9 +24,9 @@ - + - + @@ -35,14 +35,14 @@ - - - + + + - + @@ -51,7 +51,7 @@ - + @@ -112,7 +112,7 @@ - +