From 41e84769e3d69becd22f926947977191bc483602 Mon Sep 17 00:00:00 2001
From: zhenlei520 <wangzhenlei520@gmail.com>
Date: Wed, 22 Jun 2022 09:56:11 +0800
Subject: [PATCH 1/2] docs: Add Benchmark

---
 .../Masa.Contrib.Dispatcher.Events/README.md  | 17 +++++
 .../README.zh-CN.md                           | 17 +++++
 .../Benchmarks.cs                             | 29 ++++----
 .../AddShoppingCartEventHandler.cs            | 14 ++++
 .../Extensions/EventHandlers/NoticeHandler.cs | 66 -------------------
 ...sswordEvent.cs => AddShoppingCartEvent.cs} |  8 +--
 ...atcher.Events.BenchmarkDotnet.Tests.csproj |  1 +
 .../_Imports.cs                               |  2 +-
 8 files changed, 68 insertions(+), 86 deletions(-)
 create mode 100644 test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/AddShoppingCartEventHandler.cs
 delete mode 100644 test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/NoticeHandler.cs
 rename test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/{ForgetPasswordEvent.cs => AddShoppingCartEvent.cs} (50%)

diff --git a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
index 9291a3ca4..35967d033 100644
--- a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
+++ b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
@@ -173,6 +173,23 @@ builder.Services.AddEventBus(eventBusBuilder => eventBusBuilder.UseMiddleware(ty
 
 > Used in conjunction with Contracts.EF and UnitOfWork, when Event implements ITransaction, the transaction will be automatically opened after the first CUD is executed, and the transaction will be submitted after all Handlers are executed. When an exception occurs in the transaction, the transaction will be automatically rolled back.
 
+### Performance Testing
+
+BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1023 (21H1/May2021Update)
+11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores
+.NET SDK=7.0.100-preview.4.22252.9
+  [Host]     : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT DEBUG
+  Job-MHJZJL : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT
+
+Runtime=.NET 6.0  IterationCount=100  RunStrategy=ColdStart
+
+|                         Method |      Mean |     Error |      StdDev |   Median |      Min |         Max |
+|------------------------------- |----------:|----------:|------------:|---------:|---------:|------------:|
+|             SendCouponByDirect |  18.10 us |  47.19 us |   139.13 us | 3.600 us | 3.000 us |  1,395.4 us |
+|           SendCouponByEventBus | 126.16 us | 374.20 us | 1,103.33 us | 9.950 us | 8.100 us | 11,043.7 us |
+| AddShoppingCartByEventBusAsync | 124.80 us | 346.93 us | 1,022.94 us | 8.650 us | 6.500 us | 10,202.4 us |
+|  AddShoppingCartByMediatRAsync | 110.57 us | 306.47 us |   903.64 us | 7.500 us | 5.300 us |  9,000.1 us |
+
 ##### Summarize
 
 IEventBus is the core of the event bus. It can be used with Cqrs, Uow, Masa.Contrib.Ddd.Domain.Repository.EF to automatically execute SaveChange (enable UoW) and Commit (enable UoW without closing transaction) operations after sending Command, And support to roll back the transaction after an exception occurs
diff --git a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
index 8613be4d8..8f5a0c286 100644
--- a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
+++ b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
@@ -172,6 +172,23 @@ builder.Services.AddEventBus(eventBusBuilder => eventBusBuilder.UseMiddleware(ty
 
 > 配合MASA.Contrib.Ddd.Domain.Repository.EF.Repository、UnitOfWork使用,当Event实现了ITransaction,会在执行Add、Update、Delete方法时自动开启事务,且在Handler全部执行后提交事务,当事务出现异常后,会自动回滚事务
 
+### 性能测试
+
+BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1023 (21H1/May2021Update)
+11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores
+.NET SDK=7.0.100-preview.4.22252.9
+  [Host]     : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT DEBUG
+  Job-MHJZJL : .NET 6.0.6 (6.0.622.26707), X64 RyuJIT
+
+Runtime=.NET 6.0  IterationCount=100  RunStrategy=ColdStart
+
+|                         Method |      Mean |     Error |      StdDev |   Median |      Min |         Max |
+|------------------------------- |----------:|----------:|------------:|---------:|---------:|------------:|
+|             SendCouponByDirect |  18.10 us |  47.19 us |   139.13 us | 3.600 us | 3.000 us |  1,395.4 us |
+|           SendCouponByEventBus | 126.16 us | 374.20 us | 1,103.33 us | 9.950 us | 8.100 us | 11,043.7 us |
+| AddShoppingCartByEventBusAsync | 124.80 us | 346.93 us | 1,022.94 us | 8.650 us | 6.500 us | 10,202.4 us |
+|  AddShoppingCartByMediatRAsync | 110.57 us | 306.47 us |   903.64 us | 7.500 us | 5.300 us |  9,000.1 us |
+
 ##### 总结
 
 IEventBus是事件总线的核心,配合Cqrs、Uow、Masa.Contrib.Ddd.Domain.Repository.EF使用,可实现自动执行SaveChange(启用UoW)与Commit(启用UoW且无关闭事务)操作,并支持出现异常后,回滚事务
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Benchmarks.cs b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Benchmarks.cs
index 7d23ed9f9..0789cfdbc 100644
--- a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Benchmarks.cs
+++ b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Benchmarks.cs
@@ -8,57 +8,56 @@ namespace Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests;
 public class Benchmarks
 {
     private RegisterUserEvent _userEvent;
-    private ForgetPasswordEvent _forgetPasswordEvent;
+    private AddShoppingCartEvent _shoppingCartEvent;
     private IServiceProvider _serviceProvider;
     private IEventBus _eventBus;
+    private IMediator _mediator;
 
     [GlobalSetup]
     public void GlobalSetup()
     {
         IServiceCollection services = new ServiceCollection();
         services.AddLogging(loggingBuilder => loggingBuilder.ClearProviders());
+        services.AddMediatR(typeof(Benchmarks));
         services.AddEventBus();
         _serviceProvider = services.BuildServiceProvider();
         _eventBus = _serviceProvider.GetRequiredService<IEventBus>();
+        _mediator = _serviceProvider.GetRequiredService<IMediator>();
         _userEvent = new RegisterUserEvent()
         {
             Name = "tom",
             PhoneNumber = "18888888888"
         };
-        _forgetPasswordEvent = new ForgetPasswordEvent()
+        _shoppingCartEvent = new AddShoppingCartEvent()
         {
-            Name = "lisa",
-            PhoneNumber = "19999999999"
+            Count = 1,
+            GoodsId = "Microsoft"
         };
     }
 
     [Benchmark]
-    public async Task Direct()
+    public async Task SendCouponByDirect()
     {
         var _couponHandler = new CouponHandler(_serviceProvider);
         await _couponHandler.SendCoupon(_userEvent);
+        await _couponHandler.SendNotice(_userEvent);
     }
 
     [Benchmark]
-    public async Task LambdaTree()
+    public async Task SendCouponByEventBus()
     {
         await _eventBus.PublishAsync(_userEvent);
     }
 
     [Benchmark]
-    public async Task SendForgetPasseordByDirect()
+    public async Task AddShoppingCartByEventBusAsync()
     {
-        var emailNoticeHandler = new NoticeEmailHandler(_serviceProvider);
-        var smsNoticeHandler = new NoticeSmsHandler(_serviceProvider);
-        var sendCouponHandler = new SendCouponHandler(_serviceProvider);
-        await emailNoticeHandler.HandleAsync(_forgetPasswordEvent);
-        await smsNoticeHandler.HandleAsync(_forgetPasswordEvent);
-        await sendCouponHandler.HandleAsync(_forgetPasswordEvent);
+        await _eventBus.PublishAsync(_shoppingCartEvent);
     }
 
     [Benchmark]
-    public async Task SendForgetPasseordByInterfaces()
+    public async Task AddShoppingCartByMediatRAsync()
     {
-        await _eventBus.PublishAsync(_forgetPasswordEvent);
+        await _mediator.Send(_shoppingCartEvent);
     }
 }
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/AddShoppingCartEventHandler.cs b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/AddShoppingCartEventHandler.cs
new file mode 100644
index 000000000..8405f5277
--- /dev/null
+++ b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/AddShoppingCartEventHandler.cs
@@ -0,0 +1,14 @@
+// Copyright (c) MASA Stack All rights reserved.
+// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
+
+namespace Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.EventHandlers;
+
+public class AddShoppingCartEventHandler : IRequestHandler<AddShoppingCartEvent>
+{
+    [EventHandler]
+    public Task AddShoppingCartAsync(AddShoppingCartEvent @event)
+        => Task.CompletedTask;
+
+    public Task<Unit> Handle(AddShoppingCartEvent request, CancellationToken cancellationToken)
+        => Unit.Task;
+}
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/NoticeHandler.cs b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/NoticeHandler.cs
deleted file mode 100644
index 55de045a3..000000000
--- a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/EventHandlers/NoticeHandler.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.Events;
-
-// Copyright (c) MASA Stack All rights reserved.
-// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
-
-namespace Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.EventHandlers;
-
-public class SendCouponHandler : ISagaEventHandler<ForgetPasswordEvent>
-{
-    private readonly ILogger<SendCouponHandler>? _logger;
-
-    public SendCouponHandler(IServiceProvider serviceProvider) => _logger = serviceProvider.GetService<ILogger<SendCouponHandler>>();
-
-    [EventHandler(Order = 10)]
-    public Task HandleAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Send Coupon------");
-        return Task.CompletedTask;
-    }
-
-    public Task CancelAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Cancel Coupon------");
-        return Task.CompletedTask;
-    }
-}
-
-public class NoticeSmsHandler : ISagaEventHandler<ForgetPasswordEvent>
-{
-    private readonly ILogger<NoticeSmsHandler>? _logger;
-
-    public NoticeSmsHandler(IServiceProvider serviceProvider) => _logger = serviceProvider.GetService<ILogger<NoticeSmsHandler>>();
-
-    [EventHandler(Order = 20)]
-    public Task HandleAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Send Sms Notice------");
-        return Task.CompletedTask;
-    }
-
-    public Task CancelAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Cancel Sms Notice------");
-        return Task.CompletedTask;
-    }
-}
-
-public class NoticeEmailHandler : ISagaEventHandler<ForgetPasswordEvent>
-{
-    private readonly ILogger<NoticeEmailHandler>? _logger;
-
-    public NoticeEmailHandler(IServiceProvider serviceProvider) => _logger = serviceProvider.GetService<ILogger<NoticeEmailHandler>>();
-
-    [EventHandler(Order = 30)]
-    public Task HandleAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Send Email Notice------");
-        return Task.CompletedTask;
-    }
-
-    public Task CancelAsync(ForgetPasswordEvent @event)
-    {
-        _logger?.LogInformation("------Cancel Email Notice------");
-        return Task.CompletedTask;
-    }
-}
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/ForgetPasswordEvent.cs b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/AddShoppingCartEvent.cs
similarity index 50%
rename from test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/ForgetPasswordEvent.cs
rename to test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/AddShoppingCartEvent.cs
index 474826f16..223a79654 100644
--- a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/ForgetPasswordEvent.cs
+++ b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Extensions/Events/AddShoppingCartEvent.cs
@@ -1,11 +1,11 @@
-// Copyright (c) MASA Stack All rights reserved.
+// Copyright (c) MASA Stack All rights reserved.
 // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
 
 namespace Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.Events;
 
-public record ForgetPasswordEvent : Event
+public record AddShoppingCartEvent : Event, IRequest
 {
-    public string Name { get; set; }
+    public string GoodsId { get; set; }
 
-    public string PhoneNumber { get; set; }
+    public int Count { get; set; }
 }
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.csproj b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.csproj
index 9cdd8e415..075382f3f 100644
--- a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.csproj
+++ b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.csproj
@@ -12,6 +12,7 @@
 
   <ItemGroup>
     <PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetPackageVersion)" />
+    <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
     <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftPackageVersion)" />
   </ItemGroup>
 
diff --git a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/_Imports.cs b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/_Imports.cs
index 595b29fce..44ae67ddd 100644
--- a/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/_Imports.cs
+++ b/test/Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests/_Imports.cs
@@ -11,8 +11,8 @@
 global using Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.EventHandlers;
 global using Masa.Contrib.Dispatcher.Events.BenchmarkDotnet.Tests.Extensions.Events;
 global using Masa.Contrib.Dispatcher.Events.Enums;
+global using MediatR;
 global using Microsoft.Extensions.DependencyInjection;
 global using Microsoft.Extensions.Logging;
 global using System;
 global using System.Threading.Tasks;
-

From f0747fde1de89151fe71bf346aaff90afa19bd88 Mon Sep 17 00:00:00 2001
From: zhenlei520 <wangzhenlei520@gmail.com>
Date: Wed, 22 Jun 2022 10:13:38 +0800
Subject: [PATCH 2/2] chore: Modify markdown format

---
 src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md       | 2 +-
 src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
index 35967d033..84c43d710 100644
--- a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
+++ b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.md
@@ -173,7 +173,7 @@ builder.Services.AddEventBus(eventBusBuilder => eventBusBuilder.UseMiddleware(ty
 
 > Used in conjunction with Contracts.EF and UnitOfWork, when Event implements ITransaction, the transaction will be automatically opened after the first CUD is executed, and the transaction will be submitted after all Handlers are executed. When an exception occurs in the transaction, the transaction will be automatically rolled back.
 
-### Performance Testing
+##### Performance Testing
 
 BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1023 (21H1/May2021Update)
 11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores
diff --git a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
index 8f5a0c286..29f7738c3 100644
--- a/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
+++ b/src/Dispatcher/Masa.Contrib.Dispatcher.Events/README.zh-CN.md
@@ -172,7 +172,7 @@ builder.Services.AddEventBus(eventBusBuilder => eventBusBuilder.UseMiddleware(ty
 
 > 配合MASA.Contrib.Ddd.Domain.Repository.EF.Repository、UnitOfWork使用,当Event实现了ITransaction,会在执行Add、Update、Delete方法时自动开启事务,且在Handler全部执行后提交事务,当事务出现异常后,会自动回滚事务
 
-### 性能测试
+##### 性能测试
 
 BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1023 (21H1/May2021Update)
 11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores