diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 1eff521897..4b5b456a93 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -2,7 +2,8 @@
"permissions": {
"allow": [
"Bash(yarn nx g:*)",
- "Bash(npx vitest:*)"
+ "Bash(npx vitest:*)",
+ "Bash(git show:*)"
]
}
}
diff --git a/test/DistEvents/.gitignore b/test/DistEvents/.gitignore
new file mode 100644
index 0000000000..8dd4607a4b
--- /dev/null
+++ b/test/DistEvents/.gitignore
@@ -0,0 +1,398 @@
+## 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/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# 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
+*.tlog
+*.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
+
+# 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/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
\ No newline at end of file
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoApp.AspNetCoreDapr.csproj b/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoApp.AspNetCoreDapr.csproj
new file mode 100644
index 0000000000..8801131096
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoApp.AspNetCoreDapr.csproj
@@ -0,0 +1,39 @@
+
+
+
+ net10.0
+ enable
+ enable
+ DistDemoApp
+ MongoDb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);DISTDEMO_USE_MONGODB
+
+
+
+ $(DefineConstants);DISTDEMO_USE_EFCORE
+
+
+
+
+ Always
+
+
+
+
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoAppAspNetCoreDaprModule.cs b/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoAppAspNetCoreDaprModule.cs
new file mode 100644
index 0000000000..843a4af81b
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/DistDemoAppAspNetCoreDaprModule.cs
@@ -0,0 +1,67 @@
+using Dapr;
+using Volo.Abp;
+using Volo.Abp.AspNetCore.Mvc.Dapr.EventBus;
+using Volo.Abp.Autofac;
+using Volo.Abp.Dapr;
+using Volo.Abp.EventBus.Dapr;
+using Volo.Abp.Modularity;
+
+namespace DistDemoApp;
+
+#if DISTDEMO_USE_MONGODB
+[DependsOn(
+ typeof(DistDemoAppMongoDbInfrastructureModule),
+ typeof(AbpAspNetCoreMvcDaprEventBusModule),
+ typeof(DistDemoAppSharedModule),
+ typeof(AbpAutofacModule)
+)]
+#else
+[DependsOn(
+ typeof(DistDemoAppEntityFrameworkCoreInfrastructureModule),
+ typeof(AbpAspNetCoreMvcDaprEventBusModule),
+ typeof(DistDemoAppSharedModule),
+ typeof(AbpAutofacModule)
+)]
+#endif
+public class DistDemoAppAspNetCoreDaprModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+#if DISTDEMO_USE_MONGODB
+ context.ConfigureDistDemoMongoInfrastructure();
+#else
+ context.ConfigureDistDemoEntityFrameworkInfrastructure();
+#endif
+
+ Configure(options =>
+ {
+ options.HttpEndpoint = "http://localhost:3500";
+ });
+
+ Configure(options =>
+ {
+ options.PubSubName = "pubsub";
+ });
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ var app = context.GetApplicationBuilder();
+ var env = context.GetEnvironment();
+
+ if (env.IsDevelopment())
+ {
+ app.UseExceptionHandler("/Error");
+ }
+
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+ app.UseRouting();
+ app.UseCloudEvents();
+ app.UseConfiguredEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapSubscribeHandler();
+ });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/Program.cs b/test/DistEvents/DistDemoApp.AspNetCoreDapr/Program.cs
new file mode 100644
index 0000000000..f5d3f8c8ef
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/Program.cs
@@ -0,0 +1,12 @@
+using DistDemoApp;
+using Dapr;
+using Volo.Abp;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Host.UseAutofac();
+
+await builder.AddApplicationAsync();
+
+var app = builder.Build();
+await app.InitializeApplicationAsync();
+await app.RunAsync("http://localhost:8090");
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioController.cs b/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioController.cs
new file mode 100644
index 0000000000..ff6de4f5b6
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioController.cs
@@ -0,0 +1,23 @@
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.Mvc;
+
+namespace DistDemoApp;
+
+[ApiController]
+[Route("api/dist-demo/dapr")]
+public class ProviderScenarioController : AbpController
+{
+ private readonly IDistEventScenarioRunner _scenarioRunner;
+
+ public ProviderScenarioController(IDistEventScenarioRunner scenarioRunner)
+ {
+ _scenarioRunner = scenarioRunner;
+ }
+
+ [HttpGet]
+ public async Task RunAsync()
+ {
+ await _scenarioRunner.RunAsync(DistEventScenarioProfile.DaprWeb());
+ return Ok(new { Status = "ScenarioCompleted", Profile = "dapr-web" });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioEventHandler.cs b/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioEventHandler.cs
new file mode 100644
index 0000000000..b26844d7c5
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/ProviderScenarioEventHandler.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EventBus.Distributed;
+
+namespace DistDemoApp;
+
+public class ProviderScenarioEventHandler :
+ IDistributedEventHandler,
+ ITransientDependency
+{
+ public Task HandleEventAsync(ProviderScenarioEvent eventData)
+ {
+ Console.WriteLine($"Dapr ASP.NET Core handler received ProviderScenarioEvent: {eventData.Value}");
+ return Task.CompletedTask;
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AspNetCoreDapr/appsettings.json b/test/DistEvents/DistDemoApp.AspNetCoreDapr/appsettings.json
new file mode 100644
index 0000000000..711c4a34f7
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AspNetCoreDapr/appsettings.json
@@ -0,0 +1,14 @@
+{
+ "ConnectionStrings": {
+ "Default": "mongodb://localhost:27017/DistEventsDemo?retryWrites=false"
+ },
+ "Dapr": {
+ "HttpEndpoint": "http://localhost:3500"
+ },
+ "DaprEventBus": {
+ "PubSubName": "pubsub"
+ },
+ "Redis": {
+ "Configuration": "127.0.0.1"
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoApp.AzureEmulator.csproj b/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoApp.AzureEmulator.csproj
new file mode 100644
index 0000000000..d96ef9fda5
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoApp.AzureEmulator.csproj
@@ -0,0 +1,37 @@
+
+
+
+ Exe
+ net10.0
+ DistDemoApp
+ MongoDb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);DISTDEMO_USE_MONGODB
+
+
+
+ $(DefineConstants);DISTDEMO_USE_EFCORE
+
+
+
+
+ Always
+
+
+
+
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoAppAzureEmulatorModule.cs b/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoAppAzureEmulatorModule.cs
new file mode 100644
index 0000000000..2dd0c59c36
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/DistDemoAppAzureEmulatorModule.cs
@@ -0,0 +1,51 @@
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.EventBus.Azure;
+using Volo.Abp.Modularity;
+using Volo.Abp.AzureServiceBus;
+
+namespace DistDemoApp;
+
+#if DISTDEMO_USE_MONGODB
+[DependsOn(
+ typeof(DistDemoAppMongoDbInfrastructureModule),
+ typeof(AbpEventBusAzureModule),
+ typeof(DistDemoAppSharedModule)
+)]
+#else
+[DependsOn(
+ typeof(DistDemoAppEntityFrameworkCoreInfrastructureModule),
+ typeof(AbpEventBusAzureModule),
+ typeof(DistDemoAppSharedModule)
+)]
+#endif
+public class DistDemoAppAzureEmulatorModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddSingleton();
+ context.Services.AddSingleton();
+#if DISTDEMO_USE_MONGODB
+ context.ConfigureDistDemoMongoInfrastructure();
+#else
+ context.ConfigureDistDemoEntityFrameworkInfrastructure();
+#endif
+
+ Configure(options =>
+ {
+ options.Connections.Default.ConnectionString =
+ "Endpoint=sb://localhost:5673;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;";
+ options.Connections.Default.Processor = new ServiceBusProcessorOptions
+ {
+ AutoCompleteMessages = false
+ };
+ });
+
+ Configure(options =>
+ {
+ options.ConnectionName = "Default";
+ options.SubscriberName = "DistDemoAzureSubscriber";
+ options.TopicName = "DistDemoAzureTopic";
+ });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorProcessorPool.cs b/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorProcessorPool.cs
new file mode 100644
index 0000000000..84891ae804
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorProcessorPool.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using Volo.Abp.AzureServiceBus;
+using Volo.Abp.DependencyInjection;
+
+namespace DistDemoApp;
+
+public class EmulatorProcessorPool : IProcessorPool, ISingletonDependency
+{
+ public ILogger Logger { get; set; }
+
+ private bool _isDisposed;
+ private readonly AbpAzureServiceBusOptions _options;
+ private readonly IConnectionPool _connectionPool;
+ private readonly ConcurrentDictionary> _processors;
+
+ public EmulatorProcessorPool(
+ IOptions options,
+ IConnectionPool connectionPool)
+ {
+ _options = options.Value;
+ _connectionPool = connectionPool;
+ _processors = new ConcurrentDictionary>();
+ Logger = NullLogger.Instance;
+ }
+
+ public Task GetAsync(string subscriptionName, string topicName, string connectionName)
+ {
+ var processor = _processors.GetOrAdd(
+ $"{topicName}-{subscriptionName}",
+ new Lazy(() =>
+ {
+ var config = _options.Connections.GetOrDefault(connectionName);
+ var client = _connectionPool.GetClient(connectionName);
+ return client.CreateProcessor(topicName, subscriptionName, config.Processor);
+ })
+ ).Value;
+
+ return Task.FromResult(processor);
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ if (_isDisposed)
+ {
+ return;
+ }
+
+ _isDisposed = true;
+ if (!_processors.Any())
+ {
+ return;
+ }
+
+ foreach (var item in _processors.Values)
+ {
+ var processor = item.Value;
+ if (processor.IsProcessing)
+ {
+ await processor.StopProcessingAsync();
+ }
+
+ if (!processor.IsClosed)
+ {
+ await processor.CloseAsync();
+ }
+
+ await processor.DisposeAsync();
+ }
+
+ _processors.Clear();
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorPublisherPool.cs b/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorPublisherPool.cs
new file mode 100644
index 0000000000..f3c9c0a854
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/EmulatorPublisherPool.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Threading.Tasks;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Volo.Abp.AzureServiceBus;
+using Volo.Abp.DependencyInjection;
+
+#nullable enable
+namespace DistDemoApp;
+
+public class EmulatorPublisherPool : IPublisherPool, ISingletonDependency
+{
+ public ILogger Logger { get; set; }
+
+ private bool _isDisposed;
+ private readonly IConnectionPool _connectionPool;
+ private readonly ConcurrentDictionary> _publishers;
+
+ public EmulatorPublisherPool(IConnectionPool connectionPool)
+ {
+ _connectionPool = connectionPool;
+ _publishers = new ConcurrentDictionary>();
+ Logger = NullLogger.Instance;
+ }
+
+ public Task GetAsync(string topicName, string? connectionName)
+ {
+ var sender = _publishers.GetOrAdd(
+ topicName,
+ new Lazy(() =>
+ {
+ var client = _connectionPool.GetClient(connectionName);
+ return client.CreateSender(topicName);
+ })
+ ).Value;
+
+ return Task.FromResult(sender);
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ if (_isDisposed)
+ {
+ return;
+ }
+
+ _isDisposed = true;
+ if (!_publishers.Any())
+ {
+ return;
+ }
+
+ foreach (var publisher in _publishers.Values)
+ {
+ await publisher.Value.CloseAsync();
+ await publisher.Value.DisposeAsync();
+ }
+
+ _publishers.Clear();
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/Program.cs b/test/DistEvents/DistDemoApp.AzureEmulator/Program.cs
new file mode 100644
index 0000000000..a5375dad49
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/Program.cs
@@ -0,0 +1,32 @@
+using Microsoft.Extensions.DependencyInjection;
+using Serilog;
+using Volo.Abp;
+using Volo.Abp.Threading;
+
+namespace DistDemoApp;
+
+public class Program
+{
+ public static void Main(string[] args)
+ {
+ using var application = AbpApplicationFactory.Create(options =>
+ {
+ options.UseAutofac();
+ options.Services.AddSerilog((serviceProvider, configuration) =>
+ {
+ });
+ options.Services.AddLogging(c => c.AddSerilog());
+ });
+
+ Log.Information("Starting DistDemoApp.AzureEmulator.");
+
+ application.Initialize();
+
+ AsyncHelper.RunSync(() => application
+ .ServiceProvider
+ .GetRequiredService()
+ .RunAsync(DistEventScenarioProfile.AzureEmulator()));
+
+ application.Shutdown();
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.AzureEmulator/appsettings.json b/test/DistEvents/DistDemoApp.AzureEmulator/appsettings.json
new file mode 100644
index 0000000000..4502f1e483
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.AzureEmulator/appsettings.json
@@ -0,0 +1,22 @@
+{
+ "ConnectionStrings": {
+ "Default": "mongodb://localhost:27017/DistEventsDemo?retryWrites=false"
+ },
+ "Azure": {
+ "ServiceBus": {
+ "Connections": {
+ "Default": {
+ "ConnectionString": "Endpoint=sb://localhost:5673;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"
+ }
+ }
+ },
+ "EventBus": {
+ "ConnectionName": "Default",
+ "SubscriberName": "DistDemoAzureSubscriber",
+ "TopicName": "DistDemoAzureTopic"
+ }
+ },
+ "Redis": {
+ "Configuration": "127.0.0.1"
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj
index c3b8719b3f..156de09a79 100644
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoApp.EfCoreRabbitMq.csproj
@@ -4,14 +4,30 @@
Exe
net10.0
DistDemoApp
+ EntityFrameworkCore
-
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);DISTDEMO_USE_MONGODB
+
+
+
+ $(DefineConstants);DISTDEMO_USE_EFCORE
+
+
runtime; build; native; contentfiles; analyzers
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs
index da2e7a1445..363373441d 100644
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/DistDemoAppEfCoreRabbitMqModule.cs
@@ -1,44 +1,59 @@
using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.EntityFrameworkCore;
-using Volo.Abp.EntityFrameworkCore.DistributedEvents;
-using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Modularity;
+using Volo.Abp.RabbitMQ;
namespace DistDemoApp
{
+#if DISTDEMO_USE_MONGODB
[DependsOn(
- typeof(AbpEntityFrameworkCoreSqlServerModule),
+ typeof(DistDemoAppMongoDbInfrastructureModule),
typeof(AbpEventBusRabbitMqModule),
typeof(DistDemoAppSharedModule)
)]
+#else
+ [DependsOn(
+ typeof(DistDemoAppEntityFrameworkCoreInfrastructureModule),
+ typeof(AbpEventBusRabbitMqModule),
+ typeof(DistDemoAppSharedModule)
+ )]
+#endif
public class DistDemoAppEfCoreRabbitMqModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.AddAbpDbContext(options =>
+#if DISTDEMO_USE_MONGODB
+ context.ConfigureDistDemoMongoInfrastructure();
+#else
+ context.ConfigureDistDemoEntityFrameworkInfrastructure();
+#endif
+
+ Configure(options =>
{
- options.AddDefaultRepositories();
+ // options.Outboxes.Configure(config =>
+ // {
+ // config.UseDbContext();
+ // });
+ //
+ // options.Inboxes.Configure(config =>
+ // {
+ // config.UseDbContext();
+ // });
});
- Configure(options =>
+ Configure(options =>
{
- options.UseSqlServer();
+ options.Connections.Default.HostName = "localhost";
});
-
- Configure(options =>
+
+ Configure(options =>
{
- options.Outboxes.Configure(config =>
- {
- config.UseDbContext();
- });
-
- options.Inboxes.Configure(config =>
- {
- config.UseDbContext();
- });
+ options.ConnectionName = "Default";
+ options.ClientName = "DistDemoApp";
+ options.ExchangeName = "DistDemo";
});
+
}
}
}
\ No newline at end of file
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.Designer.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.Designer.cs
new file mode 100644
index 0000000000..718cebec33
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.Designer.cs
@@ -0,0 +1,182 @@
+//
+using System;
+using DistDemoApp;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.Abp.EntityFrameworkCore;
+
+#nullable disable
+
+namespace DistDemoApp.Migrations
+{
+ [DbContext(typeof(TodoDbContext))]
+ [Migration("20260304073807_Update-10.2")]
+ partial class Update102
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
+ .HasAnnotation("ProductVersion", "10.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("DistDemoApp.TodoItem", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Text")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.HasKey("Id");
+
+ b.ToTable("TodoItems");
+ });
+
+ modelBuilder.Entity("DistDemoApp.TodoSummary", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("Day")
+ .HasColumnType("tinyint");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Month")
+ .HasColumnType("tinyint");
+
+ b.Property("TotalCount")
+ .HasColumnType("int");
+
+ b.Property("Year")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("TodoSummaries");
+ });
+
+ modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.IncomingEventRecord", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("EventData")
+ .IsRequired()
+ .HasColumnType("varbinary(max)");
+
+ b.Property("EventName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("HandledTime")
+ .HasColumnType("datetime2");
+
+ b.Property("MessageId")
+ .IsRequired()
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("NextRetryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("RetryCount")
+ .HasColumnType("int");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MessageId");
+
+ b.HasIndex("Status", "CreationTime");
+
+ b.ToTable("AbpEventInbox", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("EventData")
+ .IsRequired()
+ .HasColumnType("varbinary(max)");
+
+ b.Property("EventName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreationTime");
+
+ b.ToTable("AbpEventOutbox", (string)null);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.cs
new file mode 100644
index 0000000000..a3bcf90174
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/20260304073807_Update-10.2.cs
@@ -0,0 +1,233 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace DistDemoApp.Migrations
+{
+ ///
+ public partial class Update102 : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "IX_AbpEventInbox_Processed_CreationTime",
+ table: "AbpEventInbox");
+
+ migrationBuilder.DropColumn(
+ name: "Processed",
+ table: "AbpEventInbox");
+
+ migrationBuilder.RenameColumn(
+ name: "ProcessedTime",
+ table: "AbpEventInbox",
+ newName: "NextRetryTime");
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "TodoSummaries",
+ type: "nvarchar(max)",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "ConcurrencyStamp",
+ table: "TodoSummaries",
+ type: "nvarchar(40)",
+ maxLength: 40,
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(40)",
+ oldMaxLength: 40,
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "TodoItems",
+ type: "nvarchar(max)",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "ConcurrencyStamp",
+ table: "TodoItems",
+ type: "nvarchar(40)",
+ maxLength: 40,
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(40)",
+ oldMaxLength: 40,
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "AbpEventOutbox",
+ type: "nvarchar(max)",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "MessageId",
+ table: "AbpEventInbox",
+ type: "nvarchar(450)",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(450)",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "AbpEventInbox",
+ type: "nvarchar(max)",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)",
+ oldNullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "HandledTime",
+ table: "AbpEventInbox",
+ type: "datetime2",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "RetryCount",
+ table: "AbpEventInbox",
+ type: "int",
+ nullable: false,
+ defaultValue: 0);
+
+ migrationBuilder.AddColumn(
+ name: "Status",
+ table: "AbpEventInbox",
+ type: "int",
+ nullable: false,
+ defaultValue: 0);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpEventOutbox_CreationTime",
+ table: "AbpEventOutbox",
+ column: "CreationTime");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpEventInbox_Status_CreationTime",
+ table: "AbpEventInbox",
+ columns: new[] { "Status", "CreationTime" });
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropIndex(
+ name: "IX_AbpEventOutbox_CreationTime",
+ table: "AbpEventOutbox");
+
+ migrationBuilder.DropIndex(
+ name: "IX_AbpEventInbox_Status_CreationTime",
+ table: "AbpEventInbox");
+
+ migrationBuilder.DropColumn(
+ name: "HandledTime",
+ table: "AbpEventInbox");
+
+ migrationBuilder.DropColumn(
+ name: "RetryCount",
+ table: "AbpEventInbox");
+
+ migrationBuilder.DropColumn(
+ name: "Status",
+ table: "AbpEventInbox");
+
+ migrationBuilder.RenameColumn(
+ name: "NextRetryTime",
+ table: "AbpEventInbox",
+ newName: "ProcessedTime");
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "TodoSummaries",
+ type: "nvarchar(max)",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)");
+
+ migrationBuilder.AlterColumn(
+ name: "ConcurrencyStamp",
+ table: "TodoSummaries",
+ type: "nvarchar(40)",
+ maxLength: 40,
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(40)",
+ oldMaxLength: 40);
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "TodoItems",
+ type: "nvarchar(max)",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)");
+
+ migrationBuilder.AlterColumn(
+ name: "ConcurrencyStamp",
+ table: "TodoItems",
+ type: "nvarchar(40)",
+ maxLength: 40,
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(40)",
+ oldMaxLength: 40);
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "AbpEventOutbox",
+ type: "nvarchar(max)",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)");
+
+ migrationBuilder.AlterColumn(
+ name: "MessageId",
+ table: "AbpEventInbox",
+ type: "nvarchar(450)",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(450)");
+
+ migrationBuilder.AlterColumn(
+ name: "ExtraProperties",
+ table: "AbpEventInbox",
+ type: "nvarchar(max)",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "nvarchar(max)");
+
+ migrationBuilder.AddColumn(
+ name: "Processed",
+ table: "AbpEventInbox",
+ type: "bit",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_AbpEventInbox_Processed_CreationTime",
+ table: "AbpEventInbox",
+ columns: new[] { "Processed", "CreationTime" });
+ }
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs
index 57e8c14442..1f12a89a1c 100644
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Migrations/TodoDbContextModelSnapshot.cs
@@ -7,6 +7,8 @@ using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
+#nullable disable
+
namespace DistDemoApp.Migrations
{
[DbContext(typeof(TodoDbContext))]
@@ -17,9 +19,10 @@ namespace DistDemoApp.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
- .HasAnnotation("Relational:MaxIdentifierLength", 128)
- .HasAnnotation("ProductVersion", "5.0.9")
- .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+ .HasAnnotation("ProductVersion", "10.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DistDemoApp.TodoItem", b =>
{
@@ -28,6 +31,7 @@ namespace DistDemoApp.Migrations
b.Property("ConcurrencyStamp")
.IsConcurrencyToken()
+ .IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@@ -41,6 +45,7 @@ namespace DistDemoApp.Migrations
.HasColumnName("CreatorId");
b.Property("ExtraProperties")
+ .IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@@ -58,11 +63,13 @@ namespace DistDemoApp.Migrations
{
b.Property("Id")
.ValueGeneratedOnAdd()
- .HasColumnType("int")
- .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
b.Property("ConcurrencyStamp")
.IsConcurrencyToken()
+ .IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@@ -71,6 +78,7 @@ namespace DistDemoApp.Migrations
.HasColumnType("tinyint");
b.Property("ExtraProperties")
+ .IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@@ -107,25 +115,33 @@ namespace DistDemoApp.Migrations
.HasColumnType("nvarchar(256)");
b.Property("ExtraProperties")
+ .IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
+ b.Property("HandledTime")
+ .HasColumnType("datetime2");
+
b.Property("MessageId")
+ .IsRequired()
.HasColumnType("nvarchar(450)");
- b.Property("Processed")
- .HasColumnType("bit");
-
- b.Property("ProcessedTime")
+ b.Property("NextRetryTime")
.HasColumnType("datetime2");
+ b.Property("RetryCount")
+ .HasColumnType("int");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
b.HasKey("Id");
b.HasIndex("MessageId");
- b.HasIndex("Processed", "CreationTime");
+ b.HasIndex("Status", "CreationTime");
- b.ToTable("AbpEventInbox");
+ b.ToTable("AbpEventInbox", (string)null);
});
modelBuilder.Entity("Volo.Abp.EntityFrameworkCore.DistributedEvents.OutgoingEventRecord", b =>
@@ -147,12 +163,15 @@ namespace DistDemoApp.Migrations
.HasColumnType("nvarchar(256)");
b.Property("ExtraProperties")
+ .IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.HasKey("Id");
- b.ToTable("AbpEventOutbox");
+ b.HasIndex("CreationTime");
+
+ b.ToTable("AbpEventOutbox", (string)null);
});
#pragma warning restore 612, 618
}
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs
index 597b29ae22..3cee486e96 100644
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/Program.cs
@@ -1,57 +1,34 @@
-using System;
-using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Serilog;
-using Serilog.Events;
+using Volo.Abp;
+using Volo.Abp.Threading;
namespace DistDemoApp
{
public class Program
{
- public static async Task Main(string[] args)
+ public static void Main(string[] args)
{
- Log.Logger = new LoggerConfiguration()
-#if DEBUG
- .MinimumLevel.Debug()
-#else
- .MinimumLevel.Information()
-#endif
- .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
- .Enrich.FromLogContext()
- .WriteTo.Async(c => c.File("Logs/logs.txt"))
- .WriteTo.Async(c => c.Console())
- .CreateLogger();
-
- try
- {
- Log.Information("Starting console host.");
- await CreateHostBuilder(args).RunConsoleAsync();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly!");
- return 1;
- }
- finally
+ using (var application = AbpApplicationFactory.Create(options =>
+ {
+ options.UseAutofac();
+ options.Services.AddSerilog((_, _) =>
+ {
+ });
+ options.Services.AddLogging(c => c.AddSerilog());
+ }))
{
- Log.CloseAndFlush();
- }
+ Log.Information("Starting DistDemoApp.EfCoreRabbitMq.");
+ application.Initialize();
- }
+ AsyncHelper.RunSync(
+ () => application
+ .ServiceProvider
+ .GetRequiredService().CreateTodoItemAsync()
+ );
- internal static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseAutofac()
- .UseSerilog()
- .ConfigureAppConfiguration((context, config) =>
- {
- //setup your additional configuration sources
- })
- .ConfigureServices((hostContext, services) =>
- {
- services.AddApplication();
- });
+ application.Shutdown();
+ }
+ }
}
}
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContext.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContext.cs
deleted file mode 100644
index 5a1ddd2c3f..0000000000
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContext.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using Volo.Abp.Domain.Entities;
-using Volo.Abp.EntityFrameworkCore;
-using Volo.Abp.EntityFrameworkCore.DistributedEvents;
-
-namespace DistDemoApp
-{
- public class TodoDbContext : AbpDbContext, IHasEventOutbox, IHasEventInbox
- {
- public DbSet TodoItems { get; set; }
- public DbSet TodoSummaries { get; set; }
- public DbSet OutgoingEvents { get; set; }
- public DbSet IncomingEvents { get; set; }
-
- public TodoDbContext(DbContextOptions options)
- : base(options)
- {
-
- }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
-
- modelBuilder.ConfigureEventOutbox();
- modelBuilder.ConfigureEventInbox();
-
- modelBuilder.Entity(b =>
- {
- b.Property(x => x.Text).IsRequired().HasMaxLength(128);
- });
- }
- }
-}
\ No newline at end of file
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContextFactory.cs b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContextFactory.cs
deleted file mode 100644
index 97be637acc..0000000000
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/TodoDbContextFactory.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.IO;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Design;
-using Microsoft.Extensions.Configuration;
-
-namespace DistDemoApp
-{
- public class TodoDbContextFactory : IDesignTimeDbContextFactory
- {
- public TodoDbContext CreateDbContext(string[] args)
- {
- var configuration = BuildConfiguration();
-
- var builder = new DbContextOptionsBuilder()
- .UseSqlServer(configuration.GetConnectionString("Default"));
-
- return new TodoDbContext(builder.Options);
- }
-
- private static IConfigurationRoot BuildConfiguration()
- {
- var builder = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json", optional: false);
-
- return builder.Build();
- }
- }
-}
\ No newline at end of file
diff --git a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json
index 393be04a6c..91cc668167 100644
--- a/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json
+++ b/test/DistEvents/DistDemoApp.EfCoreRabbitMq/appsettings.json
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
- "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=DistEventsDemo;Trusted_Connection=True;TrustServerCertificate=True"
+ "Default": "Server=localhost,1433;Database=DistEventsDemo;User Id=sa;Password=AbpDemo_123456;TrustServerCertificate=True"
},
"RabbitMQ": {
"Connections": {
diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj
index abeb206500..ad384a51dd 100644
--- a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj
+++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoApp.MongoDbKafka.csproj
@@ -4,14 +4,30 @@
Exe
net10.0
DistDemoApp
+ MongoDb
-
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);DISTDEMO_USE_MONGODB
+
+
+
+ $(DefineConstants);DISTDEMO_USE_EFCORE
+
+
Always
diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs
index b2e41b6ca7..b9439da27b 100644
--- a/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs
+++ b/test/DistEvents/DistDemoApp.MongoDbKafka/DistDemoAppMongoDbKafkaModule.cs
@@ -1,37 +1,42 @@
-using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Kafka;
+using Volo.Abp.Kafka;
using Volo.Abp.Modularity;
-using Volo.Abp.MongoDB;
-using Volo.Abp.MongoDB.DistributedEvents;
namespace DistDemoApp
{
+#if DISTDEMO_USE_MONGODB
[DependsOn(
- typeof(AbpMongoDbModule),
+ typeof(DistDemoAppMongoDbInfrastructureModule),
typeof(AbpEventBusKafkaModule),
typeof(DistDemoAppSharedModule)
)]
+#else
+ [DependsOn(
+ typeof(DistDemoAppEntityFrameworkCoreInfrastructureModule),
+ typeof(AbpEventBusKafkaModule),
+ typeof(DistDemoAppSharedModule)
+ )]
+#endif
public class DistDemoAppMongoDbKafkaModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.AddMongoDbContext(options =>
+#if DISTDEMO_USE_MONGODB
+ context.ConfigureDistDemoMongoInfrastructure();
+#else
+ context.ConfigureDistDemoEntityFrameworkInfrastructure();
+#endif
+
+ Configure(options =>
{
- options.AddDefaultRepositories();
+ options.Connections.Default.BootstrapServers = "localhost:9092";
});
- Configure(options =>
+ Configure(options =>
{
- options.Outboxes.Configure(config =>
- {
- config.UseMongoDbContext();
- });
-
- options.Inboxes.Configure(config =>
- {
- config.UseMongoDbContext();
- });
+ options.ConnectionName = "Default";
+ options.TopicName = "DistDemoTopic";
+ options.GroupId = "DistDemoApp";
});
}
}
diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs
index b048c17389..4d324bce0a 100644
--- a/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs
+++ b/test/DistEvents/DistDemoApp.MongoDbKafka/Program.cs
@@ -1,57 +1,36 @@
-using System;
-using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Serilog;
-using Serilog.Events;
+using Volo.Abp;
+using Volo.Abp.Threading;
namespace DistDemoApp
{
public class Program
{
- public static async Task Main(string[] args)
+ public static void Main(string[] args)
{
- Log.Logger = new LoggerConfiguration()
-#if DEBUG
- .MinimumLevel.Debug()
-#else
- .MinimumLevel.Information()
-#endif
- .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
- .Enrich.FromLogContext()
- .WriteTo.Async(c => c.File("Logs/logs.txt"))
- .WriteTo.Async(c => c.Console())
- .CreateLogger();
-
- try
- {
- Log.Information("Starting console host.");
- await CreateHostBuilder(args).RunConsoleAsync();
- return 0;
- }
- catch (Exception ex)
- {
- Log.Fatal(ex, "Host terminated unexpectedly!");
- return 1;
- }
- finally
+ using (var application = AbpApplicationFactory.Create(options =>
+ {
+ options.UseAutofac();
+ options.Services.AddSerilog((_, _) =>
+ {
+ });
+ options.Services.AddLogging(c => c.AddSerilog());
+ }))
{
- Log.CloseAndFlush();
+ Log.Information("Starting DistDemoApp.MongoDbKafka.");
+
+ application.Initialize();
+
+ AsyncHelper.RunSync(
+ () => application
+ .ServiceProvider
+ .GetRequiredService().CreateTodoItemAsync()
+ );
+
+ application.Shutdown();
}
}
-
- internal static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseAutofac()
- .UseSerilog()
- .ConfigureAppConfiguration((context, config) =>
- {
- //setup your additional configuration sources
- })
- .ConfigureServices((hostContext, services) =>
- {
- services.AddApplication();
- });
}
}
diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs b/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs
deleted file mode 100644
index a7f1b78f86..0000000000
--- a/test/DistEvents/DistDemoApp.MongoDbKafka/TodoMongoDbContext.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using MongoDB.Driver;
-using Volo.Abp.Data;
-using Volo.Abp.MongoDB;
-using Volo.Abp.MongoDB.DistributedEvents;
-
-namespace DistDemoApp
-{
- [ConnectionStringName("Default")]
- public class TodoMongoDbContext : AbpMongoDbContext, IHasEventOutbox, IHasEventInbox
- {
- public IMongoCollection TodoItems => Collection();
- public IMongoCollection TodoSummaries => Collection();
-
- public IMongoCollection OutgoingEvents
- {
- get => Collection();
- set {}
- }
- public IMongoCollection IncomingEvents
- {
- get => Collection();
- set {}
- }
- }
-
-}
diff --git a/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json b/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json
index f9ee345d5a..d6d1351b25 100644
--- a/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json
+++ b/test/DistEvents/DistDemoApp.MongoDbKafka/appsettings.json
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
- "Default": "mongodb://localhost:27018,localhost:27019,localhost:27020/DistEventsDemo"
+ "Default": "mongodb://localhost:27017/DistEventsDemo?retryWrites=false"
},
"Kafka": {
"Connections": {
diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj
index 0b04220e3e..49b6d118d2 100644
--- a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj
+++ b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoApp.MongoDbRebus.csproj
@@ -4,14 +4,30 @@
Exe
net10.0
DistDemoApp
+ MongoDb
-
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);DISTDEMO_USE_MONGODB
+
+
+
+ $(DefineConstants);DISTDEMO_USE_EFCORE
+
+
Always
diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs
index 21dab7b9b5..702ffc3f62 100644
--- a/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs
+++ b/test/DistEvents/DistDemoApp.MongoDbRebus/DistDemoAppMongoDbRebusModule.cs
@@ -1,19 +1,22 @@
-using Microsoft.Extensions.DependencyInjection;
-using Rebus.Persistence.InMem;
using Rebus.Transport.InMem;
-using Volo.Abp.EventBus.Distributed;
using Volo.Abp.EventBus.Rebus;
using Volo.Abp.Modularity;
-using Volo.Abp.MongoDB;
-using Volo.Abp.MongoDB.DistributedEvents;
namespace DistDemoApp
{
+#if DISTDEMO_USE_MONGODB
[DependsOn(
- typeof(AbpMongoDbModule),
+ typeof(DistDemoAppMongoDbInfrastructureModule),
typeof(AbpEventBusRebusModule),
typeof(DistDemoAppSharedModule)
)]
+#else
+ [DependsOn(
+ typeof(DistDemoAppEntityFrameworkCoreInfrastructureModule),
+ typeof(AbpEventBusRebusModule),
+ typeof(DistDemoAppSharedModule)
+ )]
+#endif
public class DistDemoAppMongoDbRebusModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
@@ -24,30 +27,17 @@ namespace DistDemoApp
options.Configurer = rebusConfigurer =>
{
rebusConfigurer.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "eventbus"));
- rebusConfigurer.Subscriptions(s => s.StoreInMemory());
};
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.AddMongoDbContext(options =>
- {
- options.AddDefaultRepositories();
- });
-
- Configure(options =>
- {
- options.Outboxes.Configure(config =>
- {
- config.UseMongoDbContext();
- });
-
- options.Inboxes.Configure(config =>
- {
- config.UseMongoDbContext();
- });
- });
+#if DISTDEMO_USE_MONGODB
+ context.ConfigureDistDemoMongoInfrastructure();
+#else
+ context.ConfigureDistDemoEntityFrameworkInfrastructure();
+#endif
}
}
}
diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs
index 9f8c1e6c56..17a11b5f17 100644
--- a/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs
+++ b/test/DistEvents/DistDemoApp.MongoDbRebus/Program.cs
@@ -1,9 +1,5 @@
-using System;
-using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
using Serilog;
-using Serilog.Events;
using Volo.Abp;
using Volo.Abp.Threading;
@@ -13,48 +9,16 @@ namespace DistDemoApp
{
public static void Main(string[] args)
{
-// Log.Logger = new LoggerConfiguration()
-// #if DEBUG
-// .MinimumLevel.Debug()
-// #else
-// .MinimumLevel.Information()
-// #endif
-// .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
-// .Enrich.FromLogContext()
-// .WriteTo.Async(c => c.File("Logs/logs.txt"))
-// .WriteTo.Async(c => c.Console())
-// .CreateLogger();
-//
-// try
-// {
-// Log.Information("Starting console host.");
-// await CreateHostBuilder(args).RunConsoleAsync();
-// return 0;
-// }
-// catch (Exception ex)
-// {
-// Log.Fatal(ex, "Host terminated unexpectedly!");
-// return 1;
-// }
-// finally
-// {
-// Log.CloseAndFlush();
-// }
-
using (var application = AbpApplicationFactory.Create(options =>
{
options.UseAutofac();
- options.Services.AddSerilog((serviceProvider, c) =>
+ options.Services.AddSerilog((_, _) =>
{
- // c.Enrich.FromLogContext()
- // .WriteTo.Async(c => c.File("Logs/logs.txt"))
- // .WriteTo.Async(c => c.Console())
- // .WriteTo.AbpStudio(serviceProvider);
});
options.Services.AddLogging(c => c.AddSerilog());
}))
{
- Log.Information("Starting Volo.AbpIo.DbMigrator.");
+ Log.Information("Starting DistDemoApp.MongoDbRebus.");
application.Initialize();
@@ -68,18 +32,5 @@ namespace DistDemoApp
}
}
-
- internal static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .UseAutofac()
- .UseSerilog()
- .ConfigureAppConfiguration((context, config) =>
- {
- //setup your additional configuration sources
- })
- .ConfigureServices((hostContext, services) =>
- {
- services.AddApplication();
- });
}
}
diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs b/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs
deleted file mode 100644
index 95370bb4d2..0000000000
--- a/test/DistEvents/DistDemoApp.MongoDbRebus/TodoMongoDbContext.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using MongoDB.Driver;
-using Volo.Abp.Data;
-using Volo.Abp.MongoDB;
-using Volo.Abp.MongoDB.DistributedEvents;
-
-namespace DistDemoApp
-{
- [ConnectionStringName("Default")]
- public class TodoMongoDbContext : AbpMongoDbContext, IHasEventOutbox, IHasEventInbox
- {
- public IMongoCollection TodoItems => Collection();
- public IMongoCollection TodoSummaries => Collection();
-
- public IMongoCollection OutgoingEvents => Collection();
-
- public IMongoCollection IncomingEvents => Collection();
- }
-
-}
diff --git a/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json b/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json
index f9ee345d5a..d6d1351b25 100644
--- a/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json
+++ b/test/DistEvents/DistDemoApp.MongoDbRebus/appsettings.json
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
- "Default": "mongodb://localhost:27018,localhost:27019,localhost:27020/DistEventsDemo"
+ "Default": "mongodb://localhost:27017/DistEventsDemo?retryWrites=false"
},
"Kafka": {
"Connections": {
diff --git a/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoApp.Persistence.EntityFrameworkCore.csproj b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoApp.Persistence.EntityFrameworkCore.csproj
new file mode 100644
index 0000000000..2adc9e976e
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoApp.Persistence.EntityFrameworkCore.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net10.0
+ DistDemoApp
+ EntityFrameworkCore
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoAppEntityFrameworkCoreInfrastructureModule.cs b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoAppEntityFrameworkCoreInfrastructureModule.cs
new file mode 100644
index 0000000000..1c7c094953
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoAppEntityFrameworkCoreInfrastructureModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.EntityFrameworkCore.SqlServer;
+using Volo.Abp.Modularity;
+
+namespace DistDemoApp;
+
+[DependsOn(
+ typeof(AbpEntityFrameworkCoreSqlServerModule),
+ typeof(DistDemoAppSharedModule)
+)]
+public class DistDemoAppEntityFrameworkCoreInfrastructureModule : AbpModule
+{
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoEntityFrameworkServiceCollectionExtensions.cs b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoEntityFrameworkServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..f2aa5f874e
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/DistDemoEntityFrameworkServiceCollectionExtensions.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+
+namespace DistDemoApp;
+
+public static class DistDemoEntityFrameworkServiceCollectionExtensions
+{
+ public static void ConfigureDistDemoEntityFrameworkInfrastructure(this ServiceConfigurationContext context)
+ {
+ context.Services.AddAbpDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+ });
+
+ context.Services.Configure(options =>
+ {
+ options.UseSqlServer();
+ });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContext.cs b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContext.cs
new file mode 100644
index 0000000000..a352e4a5b0
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContext.cs
@@ -0,0 +1,34 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.DistributedEvents;
+
+namespace DistDemoApp;
+
+public class TodoDbContext : AbpDbContext, IHasEventOutbox, IHasEventInbox
+{
+ public DbSet TodoItems { get; set; } = null!;
+
+ public DbSet TodoSummaries { get; set; } = null!;
+
+ public DbSet OutgoingEvents { get; set; } = null!;
+
+ public DbSet IncomingEvents { get; set; } = null!;
+
+ public TodoDbContext(DbContextOptions options)
+ : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.ConfigureEventOutbox();
+ modelBuilder.ConfigureEventInbox();
+
+ modelBuilder.Entity(b =>
+ {
+ b.Property(x => x.Text).IsRequired().HasMaxLength(128);
+ });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContextFactory.cs b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContextFactory.cs
new file mode 100644
index 0000000000..082c85bb29
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.EntityFrameworkCore/TodoDbContextFactory.cs
@@ -0,0 +1,28 @@
+using System.IO;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+
+namespace DistDemoApp;
+
+public class TodoDbContextFactory : IDesignTimeDbContextFactory
+{
+ public TodoDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+
+ var builder = new DbContextOptionsBuilder()
+ .UseSqlServer(configuration.GetConnectionString("Default"));
+
+ return new TodoDbContext(builder.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoApp.Persistence.MongoDb.csproj b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoApp.Persistence.MongoDb.csproj
new file mode 100644
index 0000000000..8c9e3e14c5
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoApp.Persistence.MongoDb.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net10.0
+ DistDemoApp
+ MongoDb
+
+
+
+
+
+
+
+
diff --git a/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoAppMongoDbInfrastructureModule.cs b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoAppMongoDbInfrastructureModule.cs
new file mode 100644
index 0000000000..390badca6f
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoAppMongoDbInfrastructureModule.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Modularity;
+using Volo.Abp.MongoDB;
+
+namespace DistDemoApp;
+
+[DependsOn(
+ typeof(AbpMongoDbModule),
+ typeof(DistDemoAppSharedModule)
+)]
+public class DistDemoAppMongoDbInfrastructureModule : AbpModule
+{
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoDbContext.cs b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoDbContext.cs
new file mode 100644
index 0000000000..4c63400dc3
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoDbContext.cs
@@ -0,0 +1,26 @@
+using MongoDB.Driver;
+using Volo.Abp.Data;
+using Volo.Abp.MongoDB;
+using Volo.Abp.MongoDB.DistributedEvents;
+
+namespace DistDemoApp;
+
+[ConnectionStringName("Default")]
+public class DistDemoMongoDbContext : AbpMongoDbContext, IHasEventOutbox, IHasEventInbox
+{
+ public IMongoCollection TodoItems => Collection();
+
+ public IMongoCollection TodoSummaries => Collection();
+
+ public IMongoCollection OutgoingEvents
+ {
+ get => Collection();
+ set { }
+ }
+
+ public IMongoCollection IncomingEvents
+ {
+ get => Collection();
+ set { }
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoServiceCollectionExtensions.cs b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..48a8285b54
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Persistence.MongoDb/DistDemoMongoServiceCollectionExtensions.cs
@@ -0,0 +1,42 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Data;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.Modularity;
+using Volo.Abp.MongoDB;
+using Volo.Abp.MongoDB.DistributedEvents;
+
+namespace DistDemoApp;
+
+public static class DistDemoMongoServiceCollectionExtensions
+{
+ private const string DefaultMongoConnectionString = "mongodb://localhost:27017/DistEventsDemo?retryWrites=false";
+
+ public static void ConfigureDistDemoMongoInfrastructure(this ServiceConfigurationContext context)
+ {
+ context.Services.AddMongoDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+ });
+
+ context.Services.Configure(options =>
+ {
+ if (string.IsNullOrWhiteSpace(options.ConnectionStrings.Default))
+ {
+ options.ConnectionStrings.Default = DefaultMongoConnectionString;
+ }
+ });
+
+ context.Services.Configure(options =>
+ {
+ options.Outboxes.Configure(config =>
+ {
+ config.UseMongoDbContext();
+ });
+
+ options.Inboxes.Configure(config =>
+ {
+ config.UseMongoDbContext();
+ });
+ });
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Shared/DemoService.cs b/test/DistEvents/DistDemoApp.Shared/DemoService.cs
index c970485252..cc6d6f64c6 100644
--- a/test/DistEvents/DistDemoApp.Shared/DemoService.cs
+++ b/test/DistEvents/DistDemoApp.Shared/DemoService.cs
@@ -1,29 +1,21 @@
-using System;
+using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
-using Volo.Abp.Domain.Repositories;
namespace DistDemoApp
{
public class DemoService : ITransientDependency
{
- private readonly IRepository _todoItemRepository;
+ private readonly IDistEventScenarioRunner _scenarioRunner;
- public DemoService(IRepository todoItemRepository)
+ public DemoService(IDistEventScenarioRunner scenarioRunner)
{
- _todoItemRepository = todoItemRepository;
+ _scenarioRunner = scenarioRunner;
}
-
- public async Task CreateTodoItemAsync()
+
+ public virtual async Task CreateTodoItemAsync()
{
- var todoItem = await _todoItemRepository.InsertAsync(
- new TodoItem
- {
- Text = "todo item " + DateTime.Now.Ticks
- }
- );
-
- Console.WriteLine("Created a new todo item: " + todoItem);
+ await _scenarioRunner.RunAsync(DistEventScenarioProfile.Default());
}
}
}
\ No newline at end of file
diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs b/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs
index ba72d6902a..90f27cb638 100644
--- a/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs
+++ b/test/DistEvents/DistDemoApp.Shared/DistDemoAppHostedService.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
@@ -11,21 +11,22 @@ namespace DistDemoApp
private readonly IAbpApplicationWithExternalServiceProvider _application;
private readonly IServiceProvider _serviceProvider;
private readonly DemoService _demoService;
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
public DistDemoAppHostedService(
IAbpApplicationWithExternalServiceProvider application,
IServiceProvider serviceProvider,
- DemoService demoService)
+ DemoService demoService,
+ IHostApplicationLifetime hostApplicationLifetime)
{
_application = application;
_serviceProvider = serviceProvider;
_demoService = demoService;
+ _hostApplicationLifetime = hostApplicationLifetime;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
- _application.Initialize(_serviceProvider);
-
await _demoService.CreateTodoItemAsync();
}
diff --git a/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs
index 936264e828..09c458bf85 100644
--- a/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs
+++ b/test/DistEvents/DistDemoApp.Shared/DistDemoAppSharedModule.cs
@@ -1,4 +1,4 @@
-using Medallion.Threading;
+using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
@@ -21,7 +21,7 @@ namespace DistDemoApp
{
var configuration = context.Services.GetConfiguration();
- context.Services.AddHostedService();
+ // context.Services.AddHostedService();
Configure(options =>
{
diff --git a/test/DistEvents/DistDemoApp.Shared/DistEventScenarioProfile.cs b/test/DistEvents/DistDemoApp.Shared/DistEventScenarioProfile.cs
new file mode 100644
index 0000000000..5dc360cfe9
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Shared/DistEventScenarioProfile.cs
@@ -0,0 +1,60 @@
+namespace DistDemoApp;
+
+public class DistEventScenarioProfile
+{
+ public string Name { get; set; } = "default";
+
+ public string AnonymousOnlyEventName { get; set; } = "dist-demo.anonymous-only";
+
+ public string AnonymousOnlyMessage { get; set; } = "hello-anonymous";
+
+ public int TypedFromTypedValue { get; set; } = 7;
+
+ public int TypedFromAnonymousValue { get; set; } = 11;
+
+ public bool EnableTypedFromTypedScenario { get; set; } = true;
+
+ public bool EnableTypedFromAnonymousScenario { get; set; } = true;
+
+ public bool EnableAnonymousOnlyScenario { get; set; } = true;
+
+ public bool OnUnitOfWorkComplete { get; set; } = true;
+
+ public bool UseOutbox { get; set; } = true;
+
+ public bool UseUnitOfWork { get; set; } = true;
+
+ public int WarmupDelayMs { get; set; } = 1500;
+
+ public int TimeoutSeconds { get; set; } = 60;
+
+ public static DistEventScenarioProfile Default()
+ {
+ return new DistEventScenarioProfile();
+ }
+
+ public static DistEventScenarioProfile DaprWeb()
+ {
+ return new DistEventScenarioProfile
+ {
+ Name = "dapr-web",
+ AnonymousOnlyEventName = "dist-demo.dapr.anonymous-only",
+ AnonymousOnlyMessage = "hello-dapr-web",
+ EnableTypedFromTypedScenario = false,
+ EnableTypedFromAnonymousScenario = false,
+ EnableAnonymousOnlyScenario = false
+ };
+ }
+
+ public static DistEventScenarioProfile AzureEmulator()
+ {
+ return new DistEventScenarioProfile
+ {
+ Name = "azure-emulator",
+ AnonymousOnlyEventName = "DistDemoApp.Azure.AnonymousOnly",
+ AnonymousOnlyMessage = "hello-azure-emulator",
+ TypedFromTypedValue = 21,
+ TypedFromAnonymousValue = 34
+ };
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Shared/DistEventScenarioRunner.cs b/test/DistEvents/DistDemoApp.Shared/DistEventScenarioRunner.cs
new file mode 100644
index 0000000000..a9601335f8
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Shared/DistEventScenarioRunner.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EventBus;
+using Volo.Abp.EventBus.Distributed;
+using Volo.Abp.Uow;
+
+namespace DistDemoApp;
+
+public class DistEventScenarioRunner : IDistEventScenarioRunner, ITransientDependency
+{
+ private readonly IDistributedEventBus _distributedEventBus;
+ private readonly IUnitOfWorkManager _unitOfWorkManager;
+
+ public DistEventScenarioRunner(
+ IDistributedEventBus distributedEventBus,
+ IUnitOfWorkManager unitOfWorkManager)
+ {
+ _distributedEventBus = distributedEventBus;
+ _unitOfWorkManager = unitOfWorkManager;
+ }
+
+ public async Task RunAsync(DistEventScenarioProfile profile)
+ {
+ var typedEventName = EventNameAttribute.GetNameOrDefault();
+
+ var typedFromTypedPublish = profile.EnableTypedFromTypedScenario
+ ? new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously)
+ : null;
+ var typedFromAnonymousPublish = profile.EnableTypedFromAnonymousScenario
+ ? new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously)
+ : null;
+ var anonymousOnlyPublish = profile.EnableAnonymousOnlyScenario
+ ? new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously)
+ : null;
+
+ using var typedSubscription = _distributedEventBus.Subscribe(eventData =>
+ {
+ if (typedFromTypedPublish != null && eventData.Value == profile.TypedFromTypedValue)
+ {
+ typedFromTypedPublish.TrySetResult(eventData.Value);
+ }
+
+ if (typedFromAnonymousPublish != null && eventData.Value == profile.TypedFromAnonymousValue)
+ {
+ typedFromAnonymousPublish.TrySetResult(eventData.Value);
+ }
+
+ return Task.CompletedTask;
+ });
+
+ IDisposable? anonymousOnlySubscription = null;
+ if (profile.EnableAnonymousOnlyScenario)
+ {
+ anonymousOnlySubscription = _distributedEventBus.Subscribe(
+ profile.AnonymousOnlyEventName,
+ new SingleInstanceHandlerFactory(
+ new ActionEventHandler(eventData =>
+ {
+ var converted = eventData.ConvertToTypedObject();
+ if (converted is Dictionary payload &&
+ payload.TryGetValue("Message", out var message) &&
+ message?.ToString() == profile.AnonymousOnlyMessage)
+ {
+ anonymousOnlyPublish!.TrySetResult(true);
+ }
+
+ return Task.CompletedTask;
+ })));
+ }
+
+ await Task.Delay(profile.WarmupDelayMs);
+
+ if (profile.UseUnitOfWork)
+ {
+ using var uow = _unitOfWorkManager.Begin();
+ await PublishScenarioEventsAsync(profile, typedEventName);
+ await uow.CompleteAsync();
+ }
+ else
+ {
+ await PublishScenarioEventsAsync(profile, typedEventName);
+ }
+
+ if (typedFromTypedPublish != null)
+ {
+ await typedFromTypedPublish.Task.WaitAsync(TimeSpan.FromSeconds(profile.TimeoutSeconds));
+ }
+
+ if (typedFromAnonymousPublish != null)
+ {
+ await typedFromAnonymousPublish.Task.WaitAsync(TimeSpan.FromSeconds(profile.TimeoutSeconds));
+ }
+
+ if (anonymousOnlyPublish != null)
+ {
+ await anonymousOnlyPublish.Task.WaitAsync(TimeSpan.FromSeconds(profile.TimeoutSeconds));
+ }
+
+ anonymousOnlySubscription?.Dispose();
+
+ Console.WriteLine($"All distributed event scenarios passed ({profile.Name}).");
+ }
+
+ private async Task PublishScenarioEventsAsync(DistEventScenarioProfile profile, string typedEventName)
+ {
+ if (profile.EnableTypedFromTypedScenario)
+ {
+ await _distributedEventBus.PublishAsync(
+ new ProviderScenarioEvent { Value = profile.TypedFromTypedValue },
+ onUnitOfWorkComplete: profile.OnUnitOfWorkComplete,
+ useOutbox: profile.UseOutbox);
+ }
+
+ if (profile.EnableTypedFromAnonymousScenario)
+ {
+ await _distributedEventBus.PublishAsync(
+ typedEventName,
+ new { Value = profile.TypedFromAnonymousValue },
+ onUnitOfWorkComplete: profile.OnUnitOfWorkComplete,
+ useOutbox: profile.UseOutbox);
+ }
+
+ if (profile.EnableAnonymousOnlyScenario)
+ {
+ await _distributedEventBus.PublishAsync(
+ profile.AnonymousOnlyEventName,
+ new { Message = profile.AnonymousOnlyMessage },
+ onUnitOfWorkComplete: profile.OnUnitOfWorkComplete,
+ useOutbox: profile.UseOutbox);
+ }
+ }
+}
diff --git a/test/DistEvents/DistDemoApp.Shared/IDistEventScenarioRunner.cs b/test/DistEvents/DistDemoApp.Shared/IDistEventScenarioRunner.cs
new file mode 100644
index 0000000000..6961ecdbaf
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Shared/IDistEventScenarioRunner.cs
@@ -0,0 +1,8 @@
+using System.Threading.Tasks;
+
+namespace DistDemoApp;
+
+public interface IDistEventScenarioRunner
+{
+ Task RunAsync(DistEventScenarioProfile profile);
+}
diff --git a/test/DistEvents/DistDemoApp.Shared/ProviderScenarioEvent.cs b/test/DistEvents/DistDemoApp.Shared/ProviderScenarioEvent.cs
new file mode 100644
index 0000000000..08dd2102c2
--- /dev/null
+++ b/test/DistEvents/DistDemoApp.Shared/ProviderScenarioEvent.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.EventBus;
+
+namespace DistDemoApp;
+
+[EventName("DistDemoApp.ProviderScenarioEvent")]
+public class ProviderScenarioEvent
+{
+ public int Value { get; set; }
+}
diff --git a/test/DistEvents/DistEventsDemo.slnx b/test/DistEvents/DistEventsDemo.slnx
index 595e2e5d3e..d31f2b3262 100644
--- a/test/DistEvents/DistEventsDemo.slnx
+++ b/test/DistEvents/DistEventsDemo.slnx
@@ -1,5 +1,9 @@
+
+
+
+
diff --git a/test/DistEvents/dapr/components/pubsub.yaml b/test/DistEvents/dapr/components/pubsub.yaml
new file mode 100644
index 0000000000..669a6149b5
--- /dev/null
+++ b/test/DistEvents/dapr/components/pubsub.yaml
@@ -0,0 +1,12 @@
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+ name: pubsub
+spec:
+ type: pubsub.redis
+ version: v1
+ metadata:
+ - name: redisHost
+ value: redis:6379
+ - name: redisPassword
+ value: ""
diff --git a/test/DistEvents/docker-compose.yml b/test/DistEvents/docker-compose.yml
new file mode 100644
index 0000000000..916b6542f7
--- /dev/null
+++ b/test/DistEvents/docker-compose.yml
@@ -0,0 +1,131 @@
+services:
+ rabbitmq:
+ image: rabbitmq:3.13-management
+ container_name: distevents-rabbitmq
+ ports:
+ - "5672:5672"
+ - "15672:15672"
+ environment:
+ RABBITMQ_DEFAULT_USER: guest
+ RABBITMQ_DEFAULT_PASS: guest
+
+ zookeeper:
+ image: confluentinc/cp-zookeeper:7.6.0
+ container_name: distevents-zookeeper
+ ports:
+ - "2181:2181"
+ environment:
+ ZOOKEEPER_CLIENT_PORT: "2181"
+ ZOOKEEPER_TICK_TIME: "2000"
+
+ kafka:
+ image: confluentinc/cp-kafka:7.6.0
+ container_name: distevents-kafka
+ depends_on:
+ - zookeeper
+ ports:
+ - "9092:9092"
+ environment:
+ KAFKA_BROKER_ID: "1"
+ KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
+ KAFKA_LISTENERS: "PLAINTEXT://0.0.0.0:9092"
+ KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://localhost:9092"
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "PLAINTEXT:PLAINTEXT"
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
+ KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
+
+ mongodb:
+ image: mongo:7
+ container_name: distevents-mongodb
+ command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
+ ports:
+ - "27017:27017"
+ healthcheck:
+ test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
+ interval: 5s
+ timeout: 3s
+ retries: 20
+
+ mongodb-rs-init:
+ image: mongo:7
+ container_name: distevents-mongodb-rs-init
+ depends_on:
+ mongodb:
+ condition: service_healthy
+ restart: "no"
+ command:
+ [
+ "mongosh",
+ "--host", "mongodb:27017",
+ "--quiet",
+ "--eval",
+ "try { rs.status() } catch (e) { rs.initiate({_id:'rs0',members:[{_id:0,host:'mongodb:27017'}]}) }"
+ ]
+
+ redis:
+ image: redis:7-alpine
+ container_name: distevents-redis
+ ports:
+ - "6379:6379"
+
+ dapr-placement:
+ image: daprio/dapr:1.14.4
+ container_name: distevents-dapr-placement
+ command: ["./placement", "-port", "50006"]
+ ports:
+ - "50006:50006"
+
+ daprd:
+ image: daprio/dapr:1.14.4
+ container_name: distevents-daprd
+ depends_on:
+ - redis
+ - dapr-placement
+ command:
+ [
+ "./daprd",
+ "--app-id", "dist-demo-dapr",
+ "--app-port", "8090",
+ "--app-channel-address", "host.docker.internal",
+ "--app-protocol", "http",
+ "--resources-path", "/components",
+ "--placement-host-address", "dapr-placement:50006",
+ "--dapr-http-port", "3500",
+ "--dapr-grpc-port", "50001"
+ ]
+ volumes:
+ - ./dapr/components:/components
+ ports:
+ - "3500:3500"
+ - "50001:50001"
+
+ servicebus-sql:
+ image: mcr.microsoft.com/azure-sql-edge:latest
+ container_name: distevents-servicebus-sql
+ environment:
+ ACCEPT_EULA: "Y"
+ MSSQL_SA_PASSWORD: "AbpDemo_123456"
+
+ servicebus-emulator:
+ image: mcr.microsoft.com/azure-messaging/servicebus-emulator:latest
+ container_name: distevents-servicebus-emulator
+ depends_on:
+ - servicebus-sql
+ environment:
+ SQL_SERVER: servicebus-sql
+ MSSQL_SA_PASSWORD: "AbpDemo_123456"
+ ACCEPT_EULA: "Y"
+ volumes:
+ - ./servicebus-emulator/Config.json:/ServiceBus_Emulator/ConfigFiles/Config.json
+ ports:
+ - "5673:5672"
+ - "5300:5300"
+
+ sqlserver:
+ image: mcr.microsoft.com/mssql/server:2022-latest
+ container_name: distevents-sqlserver
+ ports:
+ - "1433:1433"
+ environment:
+ ACCEPT_EULA: "Y"
+ MSSQL_SA_PASSWORD: "AbpDemo_123456"
diff --git a/test/DistEvents/servicebus-emulator/Config.json b/test/DistEvents/servicebus-emulator/Config.json
new file mode 100644
index 0000000000..39908ff27d
--- /dev/null
+++ b/test/DistEvents/servicebus-emulator/Config.json
@@ -0,0 +1,22 @@
+{
+ "UserConfig": {
+ "Namespaces": [
+ {
+ "Name": "sbemulatorns",
+ "Topics": [
+ {
+ "Name": "DistDemoAzureTopic",
+ "Subscriptions": [
+ {
+ "Name": "DistDemoAzureSubscriber"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "Logging": {
+ "Type": "File"
+ }
+ }
+}