From 8bb2c7aa1eb5ed3298669712fd3764f16f21c4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 23 Aug 2023 10:29:58 +0300 Subject: [PATCH 1/2] Use DatabaseName instead of config name --- .../DistributedEvents/EfCoreInboxConfigExtensions.cs | 2 ++ .../DistributedEvents/EfCoreOutboxConfigExtensions.cs | 4 +++- .../Volo/Abp/EventBus/Distributed/InboxConfig.cs | 7 +++++++ .../Volo/Abp/EventBus/Distributed/OutboxConfig.cs | 7 +++++++ .../Volo/Abp/EventBus/Distributed/InboxProcessor.cs | 3 ++- .../Volo/Abp/EventBus/Distributed/OutboxSender.cs | 3 ++- .../DistributedEvents/MongoDbInboxConfigExtensions.cs | 2 ++ .../DistributedEvents/MongoDbOutboxConfigExtensions.cs | 4 +++- 8 files changed, 28 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs index 9f0ff3f35b..4092de5b3b 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreInboxConfigExtensions.cs @@ -1,3 +1,4 @@ +using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents; @@ -8,5 +9,6 @@ public static class EfCoreInboxConfigExtensions where TDbContext : IHasEventInbox { outboxConfig.ImplementationType = typeof(IDbContextEventInbox); + outboxConfig.DatabaseName = ConnectionStringNameAttribute.GetConnStringName(); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs index 2071a832e8..5da25e2d14 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DistributedEvents/EfCoreOutboxConfigExtensions.cs @@ -1,4 +1,5 @@ -using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Data; +using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.EntityFrameworkCore.DistributedEvents; @@ -8,5 +9,6 @@ public static class EfCoreOutboxConfigExtensions where TDbContext : IHasEventOutbox { outboxConfig.ImplementationType = typeof(IDbContextEventOutbox); + outboxConfig.DatabaseName = ConnectionStringNameAttribute.GetConnStringName(); } } diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxConfig.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxConfig.cs index b2d90e707e..94e0e55be9 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxConfig.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/InboxConfig.cs @@ -8,6 +8,13 @@ public class InboxConfig [NotNull] public string Name { get; } + [NotNull] + public string DatabaseName { + get => _databaseName; + set => _databaseName = Check.NotNullOrWhiteSpace(value, nameof(DatabaseName)); + } + [NotNull] private string _databaseName; + public Type ImplementationType { get; set; } public Func EventSelector { get; set; } diff --git a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutboxConfig.cs b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutboxConfig.cs index d526195ba3..0b327c0e3b 100644 --- a/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutboxConfig.cs +++ b/framework/src/Volo.Abp.EventBus.Abstractions/Volo/Abp/EventBus/Distributed/OutboxConfig.cs @@ -7,6 +7,13 @@ public class OutboxConfig { [NotNull] public string Name { get; } + + [NotNull] + public string DatabaseName { + get => _databaseName; + set => _databaseName = Check.NotNullOrWhiteSpace(value, nameof(DatabaseName)); + } + [NotNull] private string _databaseName; public Type ImplementationType { get; set; } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs index 1b4f0e4deb..14e80bd9c6 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs @@ -27,7 +27,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency protected DateTime? LastCleanTime { get; set; } - protected string DistributedLockName => "AbpInbox_" + InboxConfig.Name; + protected string DistributedLockName { get; private set; } public ILogger Logger { get; set; } protected CancellationTokenSource StoppingTokenSource { get; } protected CancellationToken StoppingToken { get; } @@ -64,6 +64,7 @@ public class InboxProcessor : IInboxProcessor, ITransientDependency { InboxConfig = inboxConfig; Inbox = (IEventInbox)ServiceProvider.GetRequiredService(inboxConfig.ImplementationType); + DistributedLockName = $"AbpInbox_{InboxConfig.DatabaseName}"; Timer.Start(cancellationToken); return Task.CompletedTask; } diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs index 3f7e2dfd73..5f34761b17 100644 --- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs +++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/OutboxSender.cs @@ -22,7 +22,7 @@ public class OutboxSender : IOutboxSender, ITransientDependency protected IEventOutbox Outbox { get; private set; } protected OutboxConfig OutboxConfig { get; private set; } protected AbpEventBusBoxesOptions EventBusBoxesOptions { get; } - protected string DistributedLockName => "AbpOutbox_" + OutboxConfig.Name; + protected string DistributedLockName { get; private set; } public ILogger Logger { get; set; } protected CancellationTokenSource StoppingTokenSource { get; } @@ -51,6 +51,7 @@ public class OutboxSender : IOutboxSender, ITransientDependency { OutboxConfig = outboxConfig; Outbox = (IEventOutbox)ServiceProvider.GetRequiredService(outboxConfig.ImplementationType); + DistributedLockName = $"AbpOutbox_{OutboxConfig.DatabaseName}"; Timer.Start(cancellationToken); return Task.CompletedTask; } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs index 8b3f17c58b..9d16d9b730 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbInboxConfigExtensions.cs @@ -1,3 +1,4 @@ +using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.MongoDB.DistributedEvents; @@ -8,5 +9,6 @@ public static class MongoDbInboxConfigExtensions where TMongoDbContext : IHasEventInbox { outboxConfig.ImplementationType = typeof(IMongoDbContextEventInbox); + outboxConfig.DatabaseName = ConnectionStringNameAttribute.GetConnStringName(); } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs index 6b91fec861..3914c1380d 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbOutboxConfigExtensions.cs @@ -1,4 +1,5 @@ -using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Data; +using Volo.Abp.EventBus.Distributed; namespace Volo.Abp.MongoDB.DistributedEvents; @@ -8,5 +9,6 @@ public static class MongoDbOutboxConfigExtensions where TMongoDbContext : IHasEventOutbox { outboxConfig.ImplementationType = typeof(IMongoDbContextEventOutbox); + outboxConfig.DatabaseName = ConnectionStringNameAttribute.GetConnStringName(); } } From afd6a44c4bec487c7fc604806c701fd43771e60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 23 Aug 2023 10:56:51 +0300 Subject: [PATCH 2/2] Document the databasename property --- docs/en/Distributed-Event-Bus.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/en/Distributed-Event-Bus.md b/docs/en/Distributed-Event-Bus.md index 550ea6d9f8..2fff974f50 100644 --- a/docs/en/Distributed-Event-Bus.md +++ b/docs/en/Distributed-Event-Bus.md @@ -469,6 +469,8 @@ Configure(options => }); ```` +> **IMPORTANT**: Outbox sending service uses distributed locks to ensure only a single instance of your application consumes the outbox queue concurrently. Distributed locking key should be unique per database. The `config` object (in the preceding code example) has a `DatabaseName` property, which is used in the distributed lock key to ensure the uniqueness. `DatabaseName` is automatically set by the `UseDbContext` method, getting the database name from the `ConnectionStringName` attribute of the `YourDbContext` class. So, if you have multiple databases in your system, ensure that you use the same connection string name for the same database, but different connection string names for different databases. If you can't ensure that, you can manually set `config.DatabaseName` (after the `UseDbContext` line) to ensure that uniqueness. + ### Enabling event inbox Open your `DbContext` class (EF Core or MongoDB), implement the `IHasEventInbox` interface. You should end up by adding a `DbSet` property into your `DbContext` class: @@ -502,6 +504,8 @@ Configure(options => }); ```` +**IMPORTANT**: Inbox processing service uses distributed locks to ensure only a single instance of your application consumes the inbox queue concurrently. Distributed locking key should be unique per database. The `config` object (in the preceding code example) has a `DatabaseName` property, which is used in the distributed lock key to ensure the uniqueness. `DatabaseName` is automatically set by the `UseDbContext` method, getting the database name from the `ConnectionStringName` attribute of the `YourDbContext` class. So, if you have multiple databases in your system, ensure that you use the same connection string name for the same database, but different connection string names for different databases. If you can't ensure that, you can manually set `config.DatabaseName` (after the `UseDbContext` line) to ensure that uniqueness. + ### Additional Configuration > The default configuration will be enough for most cases. However, there are some options you may want to set for outbox and inbox. @@ -525,6 +529,7 @@ Here, the following properties are available on the `config` object: * `IsSendingEnabled` (default: `true`): You can set to `false` to disable sending outbox events to the actual event bus. If you disable this, events can still be added to outbox, but not sent. This can be helpful if you have multiple applications (or application instances) writing to outbox, but use one of them to send the events. * `Selector`: A predicate to filter the event (ETO) types to be used for this configuration. Should return `true` to select the event. It selects all the events by default. This is especially useful if you want to ignore some ETO types from the outbox, or want to define named outbox configurations and group events within these configurations. See the *Named Configurations* section. * `ImplementationType`: Type of the class that implements the database operations for the outbox. This is normally set when you call `UseDbContext` as shown before. See *Implementing a Custom Outbox/Inbox Database Provider* section for advanced usages. +* `DatabaseName`: Unique database name for the database that is used for this outbox configuration. See the **IMPORTANT** paragraph at the end of the *Enabling event outbox* section. #### Inbox configuration @@ -546,6 +551,7 @@ Here, the following properties are available on the `config` object: * `EventSelector`: A predicate to filter the event (ETO) types to be used for this configuration. This is especially useful if you want to ignore some ETO types from the inbox, or want to define named inbox configurations and group events within these configurations. See the *Named Configurations* section. * `HandlerSelector`: A predicate to filter the event handled types (classes implementing the `IDistributedEventHandler` interface) to be used for this configuration. This is especially useful if you want to ignore some event handler types from inbox processing, or want to define named inbox configurations and group event handlers within these configurations. See the *Named Configurations* section. * `ImplementationType`: Type of the class that implements the database operations for the inbox. This is normally set when you call `UseDbContext` as shown before. See *Implementing a Custom Outbox/Inbox Database Provider* section for advanced usages. +* `DatabaseName`: Unique database name for the database that is used for this outbox configuration. See the **IMPORTANT** paragraph at the end of the *Enabling event inbox* section. #### AbpEventBusBoxesOptions