Co-authored-by: Andrii Labyntsev <lab.andrii@gmail.com>master
@@ -34,6 +34,16 @@ namespace DotNetCore.CAP | |||||
/// </summary> | /// </summary> | ||||
public string DefaultGroup { get; set; } | public string DefaultGroup { get; set; } | ||||
/// <summary> | |||||
/// Subscriber group prefix. | |||||
/// </summary> | |||||
public string GroupNamePrefix { get; set; } | |||||
/// <summary> | |||||
/// Topic prefix. | |||||
/// </summary> | |||||
public string TopicNamePrefix { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// The default version of the message, configured to isolate data in the same instance. The length must not exceed 20 | /// The default version of the message, configured to isolate data in the same instance. The length must not exceed 20 | ||||
/// </summary> | /// </summary> | ||||
@@ -24,6 +24,8 @@ namespace DotNetCore.CAP.Internal | |||||
public IList<ParameterDescriptor> Parameters { get; set; } | public IList<ParameterDescriptor> Parameters { get; set; } | ||||
public string TopicNamePrefix { get; set; } | |||||
private string _topicName; | private string _topicName; | ||||
/// <summary> | /// <summary> | ||||
/// Topic name based on both <see cref="Attribute"/> and <see cref="ClassAttribute"/>. | /// Topic name based on both <see cref="Attribute"/> and <see cref="ClassAttribute"/>. | ||||
@@ -43,6 +45,11 @@ namespace DotNetCore.CAP.Internal | |||||
{ | { | ||||
_topicName = Attribute.Name; | _topicName = Attribute.Name; | ||||
} | } | ||||
if (!string.IsNullOrEmpty(TopicNamePrefix) && !string.IsNullOrEmpty(_topicName)) | |||||
{ | |||||
_topicName = $"{TopicNamePrefix}.{_topicName}"; | |||||
} | |||||
} | } | ||||
return _topicName; | return _topicName; | ||||
} | } | ||||
@@ -11,6 +11,7 @@ using DotNetCore.CAP.Messages; | |||||
using DotNetCore.CAP.Persistence; | using DotNetCore.CAP.Persistence; | ||||
using DotNetCore.CAP.Transport; | using DotNetCore.CAP.Transport; | ||||
using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
using Microsoft.Extensions.Options; | |||||
namespace DotNetCore.CAP.Internal | namespace DotNetCore.CAP.Internal | ||||
{ | { | ||||
@@ -18,6 +19,7 @@ namespace DotNetCore.CAP.Internal | |||||
{ | { | ||||
private readonly IDispatcher _dispatcher; | private readonly IDispatcher _dispatcher; | ||||
private readonly IDataStorage _storage; | private readonly IDataStorage _storage; | ||||
private readonly CapOptions _capOptions; | |||||
// ReSharper disable once InconsistentNaming | // ReSharper disable once InconsistentNaming | ||||
protected static readonly DiagnosticListener s_diagnosticListener = | protected static readonly DiagnosticListener s_diagnosticListener = | ||||
@@ -28,6 +30,7 @@ namespace DotNetCore.CAP.Internal | |||||
ServiceProvider = service; | ServiceProvider = service; | ||||
_dispatcher = service.GetRequiredService<IDispatcher>(); | _dispatcher = service.GetRequiredService<IDispatcher>(); | ||||
_storage = service.GetRequiredService<IDataStorage>(); | _storage = service.GetRequiredService<IDataStorage>(); | ||||
_capOptions = service.GetService<IOptions<CapOptions>>().Value; | |||||
Transaction = new AsyncLocal<ICapTransaction>(); | Transaction = new AsyncLocal<ICapTransaction>(); | ||||
} | } | ||||
@@ -63,6 +66,11 @@ namespace DotNetCore.CAP.Internal | |||||
throw new ArgumentNullException(nameof(name)); | throw new ArgumentNullException(nameof(name)); | ||||
} | } | ||||
if (!string.IsNullOrEmpty(_capOptions.TopicNamePrefix)) | |||||
{ | |||||
name = $"{_capOptions.TopicNamePrefix}.{name}"; | |||||
} | |||||
headers ??= new Dictionary<string, string>(); | headers ??= new Dictionary<string, string>(); | ||||
if (!headers.ContainsKey(Headers.MessageId)) | if (!headers.ContainsKey(Headers.MessageId)) | ||||
@@ -59,6 +59,11 @@ namespace DotNetCore.CAP.Internal | |||||
return null; | return null; | ||||
} | } | ||||
if (!string.IsNullOrEmpty(_capOptions.TopicNamePrefix)) | |||||
{ | |||||
key = $"{_capOptions.TopicNamePrefix}.{key}"; | |||||
} | |||||
var result = MatchUsingName(key, executeDescriptor); | var result = MatchUsingName(key, executeDescriptor); | ||||
if (result != null) | if (result != null) | ||||
{ | { | ||||
@@ -165,10 +170,13 @@ namespace DotNetCore.CAP.Internal | |||||
protected virtual void SetSubscribeAttribute(TopicAttribute attribute) | protected virtual void SetSubscribeAttribute(TopicAttribute attribute) | ||||
{ | { | ||||
attribute.Group = (attribute.Group ?? _capOptions.DefaultGroup) + "." + _capOptions.Version; | |||||
var prefix = !string.IsNullOrEmpty(_capOptions.GroupNamePrefix) | |||||
? $"{_capOptions.GroupNamePrefix}." | |||||
: string.Empty; | |||||
attribute.Group = $"{prefix}{attribute.Group ?? _capOptions.DefaultGroup}.{_capOptions.Version}"; | |||||
} | } | ||||
private static ConsumerExecutorDescriptor InitDescriptor( | |||||
private ConsumerExecutorDescriptor InitDescriptor( | |||||
TopicAttribute attr, | TopicAttribute attr, | ||||
MethodInfo methodInfo, | MethodInfo methodInfo, | ||||
TypeInfo implType, | TypeInfo implType, | ||||
@@ -183,7 +191,8 @@ namespace DotNetCore.CAP.Internal | |||||
MethodInfo = methodInfo, | MethodInfo = methodInfo, | ||||
ImplTypeInfo = implType, | ImplTypeInfo = implType, | ||||
ServiceTypeInfo = serviceTypeInfo, | ServiceTypeInfo = serviceTypeInfo, | ||||
Parameters = parameters | |||||
Parameters = parameters, | |||||
TopicNamePrefix = _capOptions.TopicNamePrefix | |||||
}; | }; | ||||
return descriptor; | return descriptor; | ||||
@@ -12,6 +12,9 @@ namespace DotNetCore.CAP.Test | |||||
{ | { | ||||
public class CustomConsumerSubscribeTest | public class CustomConsumerSubscribeTest | ||||
{ | { | ||||
private const string TopicNamePrefix = "topic"; | |||||
private const string GroupNamePrefix = "group"; | |||||
private readonly IServiceProvider _provider; | private readonly IServiceProvider _provider; | ||||
public CustomConsumerSubscribeTest() | public CustomConsumerSubscribeTest() | ||||
@@ -20,7 +23,11 @@ namespace DotNetCore.CAP.Test | |||||
services.AddSingleton<IConsumerServiceSelector, MyConsumerServiceSelector>(); | services.AddSingleton<IConsumerServiceSelector, MyConsumerServiceSelector>(); | ||||
services.AddTransient<IMySubscribe, CustomInterfaceTypesClass>(); | services.AddTransient<IMySubscribe, CustomInterfaceTypesClass>(); | ||||
services.AddLogging(); | services.AddLogging(); | ||||
services.AddCap(x => { }); | |||||
services.AddCap(x => | |||||
{ | |||||
x.TopicNamePrefix = TopicNamePrefix; | |||||
x.GroupNamePrefix = GroupNamePrefix; | |||||
}); | |||||
_provider = services.BuildServiceProvider(); | _provider = services.BuildServiceProvider(); | ||||
} | } | ||||
@@ -42,6 +49,8 @@ namespace DotNetCore.CAP.Test | |||||
Assert.NotNull(bestCandidates); | Assert.NotNull(bestCandidates); | ||||
Assert.NotNull(bestCandidates.MethodInfo); | Assert.NotNull(bestCandidates.MethodInfo); | ||||
Assert.StartsWith(GroupNamePrefix, bestCandidates.Attribute.Group); | |||||
Assert.StartsWith(TopicNamePrefix, bestCandidates.TopicName); | |||||
Assert.Equal(typeof(Task), bestCandidates.MethodInfo.ReturnType); | Assert.Equal(typeof(Task), bestCandidates.MethodInfo.ReturnType); | ||||
} | } | ||||
} | } | ||||
@@ -102,6 +111,11 @@ namespace DotNetCore.CAP.Test | |||||
attr.Group = attr.Group + "." + _capOptions.Version; | attr.Group = attr.Group + "." + _capOptions.Version; | ||||
} | } | ||||
if (!string.IsNullOrEmpty(_capOptions.GroupNamePrefix)) | |||||
{ | |||||
attr.Group = $"{_capOptions.GroupNamePrefix}.{attr.Group}"; | |||||
} | |||||
yield return new ConsumerExecutorDescriptor | yield return new ConsumerExecutorDescriptor | ||||
{ | { | ||||
Attribute = new CapSubscribeAttribute(attr.Name) | Attribute = new CapSubscribeAttribute(attr.Name) | ||||
@@ -109,7 +123,8 @@ namespace DotNetCore.CAP.Test | |||||
Group = attr.Group | Group = attr.Group | ||||
}, | }, | ||||
MethodInfo = method, | MethodInfo = method, | ||||
ImplTypeInfo = typeInfo | |||||
ImplTypeInfo = typeInfo, | |||||
TopicNamePrefix = _capOptions.TopicNamePrefix | |||||
}; | }; | ||||
} | } | ||||
} | } | ||||