diff --git a/Directory.Build.props b/Directory.Build.props
index ca05097a..4daf54ad 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -5,7 +5,7 @@
true
true
- $(NoWarn),1573,1591,1712
+ $(NoWarn),1573,1591,1712,NU1903
..\..\_stylecop\codeanalysis.ruleset
diff --git a/src/Nacos.Microsoft.Extensions.Configuration/ConfigListener.cs b/src/Nacos.Microsoft.Extensions.Configuration/ConfigListener.cs
index 1aa687a0..05c305a0 100644
--- a/src/Nacos.Microsoft.Extensions.Configuration/ConfigListener.cs
+++ b/src/Nacos.Microsoft.Extensions.Configuration/ConfigListener.cs
@@ -16,5 +16,10 @@ public class ConfigListener
/// Configuration group
///
public string Group { get; set; }
+
+ ///
+ /// Configuration namespace
+ ///
+ public string Namespace { get; set; }
}
}
diff --git a/src/Nacos.Microsoft.Extensions.Configuration/NacosV2ConfigurationProvider.cs b/src/Nacos.Microsoft.Extensions.Configuration/NacosV2ConfigurationProvider.cs
index c686c909..e016ce4f 100644
--- a/src/Nacos.Microsoft.Extensions.Configuration/NacosV2ConfigurationProvider.cs
+++ b/src/Nacos.Microsoft.Extensions.Configuration/NacosV2ConfigurationProvider.cs
@@ -3,6 +3,7 @@
using global::Microsoft.Extensions.Configuration;
using global::Microsoft.Extensions.Logging;
using Nacos.V2;
+ using Nacos.V2.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -39,11 +40,13 @@ public NacosV2ConfigurationProvider(NacosV2ConfigurationSource configurationSour
foreach (var item in configurationSource.Listeners)
{
- var listener = new MsConfigListener(item.DataId, item.Group, item.Optional, this, _logger);
+ var listener = new MsConfigListener(item, this, _logger);
- tasks.Add(_client.AddListener(item.DataId, item.Group, listener));
+ tasks.Add(item.Namespace.IsNullOrWhiteSpace()
+ ? _client.AddListener(item.DataId, item.Group, listener)
+ : _client.AddListener(item.DataId, item.Group, item.Namespace, listener));
- _listenerDict.Add($"{item.DataId}#{item.Group}", listener);
+ _listenerDict.Add($"{item.DataId}#{item.Group}#{item.Namespace}", listener);
}
Task.WaitAll(tasks.ToArray());
@@ -66,8 +69,11 @@ public void Dispose()
var arr = item.Key.Split('#');
var dataId = arr[0];
var group = arr[1];
+ var tenant = arr[2];
- tasks.Add(_client.RemoveListener(dataId, group, item.Value));
+ tasks.Add(tenant.IsNullOrWhiteSpace()
+ ? _client.RemoveListener(dataId, group, item.Value)
+ : _client.RemoveListener(dataId, group, tenant, item.Value));
}
Task.WaitAll(tasks.ToArray());
@@ -87,10 +93,12 @@ public override void Load()
{
try
{
- var config = _client.GetConfig(listener.DataId, listener.Group, 3000)
+ var config = (listener.Namespace.IsNullOrWhiteSpace()
+ ? _client.GetConfig(listener.DataId, listener.Group, 3000)
+ : _client.GetConfig(listener.DataId, listener.Group, listener.Namespace, 3000))
.ConfigureAwait(false).GetAwaiter().GetResult();
- _configDict.AddOrUpdate($"{_configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}", config, (x, y) => config);
+ _configDict.AddOrUpdate(GetCacheKey(listener), config, (x, y) => config);
var data = _parser.Parse(config);
@@ -123,6 +131,9 @@ public override void Load()
}
}
+ private string GetCacheKey(ConfigListener listener)
+ => $"{(listener.Namespace.IsNullOrWhiteSpace() ? _configurationSource.GetNamespace() : listener.Namespace)}#{listener.Group}#{listener.DataId}";
+
// for test
internal void SetListener(string key, MsConfigListener listener)
{
@@ -131,21 +142,17 @@ internal void SetListener(string key, MsConfigListener listener)
internal class MsConfigListener : IListener
{
- private string _dataId;
- private string _group;
private bool _optional;
private NacosV2ConfigurationProvider _provider;
private string _key;
private ILogger _logger;
- internal MsConfigListener(string dataId, string group, bool optional, NacosV2ConfigurationProvider provider, ILogger logger)
+ internal MsConfigListener(ConfigListener listener, NacosV2ConfigurationProvider provider, ILogger logger)
{
- this._dataId = dataId;
- this._group = group;
- this._optional = optional;
+ this._optional = listener.Optional;
this._provider = provider;
this._logger = logger;
- _key = $"{provider._configurationSource.GetNamespace()}#{_group}#{_dataId}";
+ _key = provider.GetCacheKey(listener);
}
@@ -160,7 +167,7 @@ public void ReceiveConfigInfo(string configInfo)
foreach (var listener in _provider._configurationSource.Listeners)
{
- var key = $"{_provider._configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}";
+ var key = _provider.GetCacheKey(listener);
if (!_provider._configDict.TryGetValue(key, out var config))
{
diff --git a/src/Nacos/V2/Config/Impl/ClientWorker.cs b/src/Nacos/V2/Config/Impl/ClientWorker.cs
index 4e1d4412..a6d2d126 100644
--- a/src/Nacos/V2/Config/Impl/ClientWorker.cs
+++ b/src/Nacos/V2/Config/Impl/ClientWorker.cs
@@ -33,10 +33,12 @@ public ClientWorker(ILogger logger, ConfigFilterChainManager configFilterChainMa
: new ConfigHttpTransportClient(logger, options, serverListManager, _cacheMap);
}
- public async Task AddTenantListeners(string dataId, string group, List listeners)
+ public Task AddTenantListeners(string dataId, string group, List listeners)
+ => AddTenantListeners(dataId, group, _agent.GetTenant(), listeners);
+
+ public async Task AddTenantListeners(string dataId, string group, string tenant, List listeners)
{
group = ParamUtils.Null2DefaultGroup(group);
- string tenant = _agent.GetTenant();
CacheData cache = AddCacheDataIfAbsent(dataId, group, tenant);
foreach (var listener in listeners)
@@ -68,10 +70,12 @@ internal async Task AddTenantListenersWithContent(string dataId, string group, s
}
}
- public async Task RemoveTenantListener(string dataId, string group, IListener listener)
+ public Task RemoveTenantListener(string dataId, string group, IListener listener)
+ => RemoveTenantListener(dataId, group, _agent.GetTenant(), listener);
+
+ public async Task RemoveTenantListener(string dataId, string group, string tenant, IListener listener)
{
group = ParamUtils.Null2DefaultGroup(group);
- string tenant = _agent.GetTenant();
CacheData cache = GetCache(dataId, group, tenant);
if (cache != null)
diff --git a/src/Nacos/V2/Config/NacosConfigService.cs b/src/Nacos/V2/Config/NacosConfigService.cs
index 43ac86d0..abf3925b 100644
--- a/src/Nacos/V2/Config/NacosConfigService.cs
+++ b/src/Nacos/V2/Config/NacosConfigService.cs
@@ -6,6 +6,7 @@
using Nacos.V2.Config.Impl;
using Nacos.V2.Config.Utils;
using Nacos.V2.Exceptions;
+ using Nacos.V2.Utils;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -28,9 +29,17 @@ public NacosConfigService(ILoggerFactory loggerFactory, IOptions _worker.AddTenantListeners(dataId, group, new List { listener });
+ public Task AddListener(string dataId, string group, string tenant, IListener listener)
+ => tenant.IsNullOrWhiteSpace()
+ ? _worker.AddTenantListeners(dataId, group, new List { listener })
+ : _worker.AddTenantListeners(dataId, group, tenant, new List { listener });
+
public async Task GetConfig(string dataId, string group, long timeoutMs)
=> await GetConfigInner(_namespace, dataId, group, timeoutMs).ConfigureAwait(false);
+ public Task GetConfig(string dataId, string group, string tenant, long timeoutMs)
+ => GetConfigInner(tenant.IsNullOrWhiteSpace() ? _namespace : tenant, dataId, group, timeoutMs);
+
public async Task GetConfigAndSignListener(string dataId, string group, long timeoutMs, IListener listener)
{
string content = await GetConfig(dataId, group, timeoutMs).ConfigureAwait(false);
@@ -59,6 +68,11 @@ public async Task RemoveConfig(string dataId, string group)
public Task RemoveListener(string dataId, string group, IListener listener)
=> _worker.RemoveTenantListener(dataId, group, listener);
+ public Task RemoveListener(string dataId, string group, string tenant, IListener listener)
+ => tenant.IsNullOrWhiteSpace()
+ ? _worker.RemoveTenantListener(dataId, group, listener)
+ : _worker.RemoveTenantListener(dataId, group, tenant, listener);
+
public Task ShutDown() => Task.CompletedTask;
private async Task GetConfigInner(string tenant, string dataId, string group, long timeoutMs)
diff --git a/src/Nacos/V2/INacosConfigService.cs b/src/Nacos/V2/INacosConfigService.cs
index 2cfea59b..dd6c6959 100644
--- a/src/Nacos/V2/INacosConfigService.cs
+++ b/src/Nacos/V2/INacosConfigService.cs
@@ -13,6 +13,16 @@ public interface INacosConfigService
/// config value
Task GetConfig(string dataId, string group, long timeoutMs);
+ ///
+ /// Get config.
+ ///
+ /// dataId
+ /// group
+ /// namespace
+ /// read timeout
+ /// config value
+ Task GetConfig(string dataId, string group, string tenant, long timeoutMs);
+
///
/// Get config and register Listener.
/// If you want to pull it yourself when the program starts to get the configuration for the first time, and the
@@ -38,6 +48,18 @@ public interface INacosConfigService
/// Listener
Task AddListener(string dataId, string group, IListener listener);
+ ///
+ /// Add a listener to the configuration, after the server modified the configuration, the client will use the
+ /// incoming listener callback. Recommended asynchronous processing, the application can implement the getExecutor
+ /// method in the ManagerListener, provide a thread pool of execution. If provided, use the main thread callback, May
+ /// block other configurations or be blocked by other configurations.
+ ///
+ /// dataId
+ /// group
+ /// namespace
+ /// Listener
+ Task AddListener(string dataId, string group, string tenant, IListener listener);
+
///
/// Publish config.
///
@@ -94,6 +116,15 @@ public interface INacosConfigService
/// listener
Task RemoveListener(string dataId, string group, IListener listener);
+ ///
+ /// Remove listener.
+ ///
+ /// dataId
+ /// group
+ /// tenant
+ /// listener
+ Task RemoveListener(string dataId, string group, string tenant, IListener listener);
+
///
/// Get server status.
///
@@ -105,4 +136,4 @@ public interface INacosConfigService
///
Task ShutDown();
}
-}
\ No newline at end of file
+}
diff --git a/tests/Nacos.Microsoft.Extensions.Configuration.Tests/NacosV2ConfigurationProviderTest.cs b/tests/Nacos.Microsoft.Extensions.Configuration.Tests/NacosV2ConfigurationProviderTest.cs
index 32f5a146..12929307 100644
--- a/tests/Nacos.Microsoft.Extensions.Configuration.Tests/NacosV2ConfigurationProviderTest.cs
+++ b/tests/Nacos.Microsoft.Extensions.Configuration.Tests/NacosV2ConfigurationProviderTest.cs
@@ -34,13 +34,38 @@ public void Init_Should_ThrowException_When_Listeners_Is_Empty()
});
}
+ [Fact]
+ public void Init_Should_Call_AddListener()
+ {
+ _mockSvc.Setup(x => x.AddListener("d1", "g", It.IsAny())).Returns(Task.CompletedTask);
+ _mockSvc.Setup(x => x.AddListener("d2", "g", "ns", It.IsAny())).Returns(Task.CompletedTask);
+
+ var cs = new NacosV2ConfigurationSource(null, null)
+ {
+ Namespace = "cs",
+ Listeners = new System.Collections.Generic.List
+ {
+ new ConfigListener { DataId = "d1", Group = "g" },
+ new ConfigListener { DataId = "d2", Group = "g", Namespace = "ns" }
+ },
+ NacosConfigurationParser = DefaultJsonConfigurationStringParser.Instance
+ };
+
+ var provider = new NacosV2ConfigurationProvider(cs, _mockSvc.Object, null);
+
+ _mockSvc.Verify(x => x.AddListener("d1", "g", It.IsAny()), Times.Once);
+ _mockSvc.Verify(x => x.AddListener("d2", "g", "ns", It.IsAny()), Times.Once);
+ }
+
[Fact]
public void Dispose_Should_Call_RemoveListener()
{
var provider = GetProviderForMultiListeners();
_mockSvc.Setup(x => x.RemoveListener("d1", "g", It.IsAny())).Returns(Task.CompletedTask);
+ _mockSvc.Setup(x => x.RemoveListener("d2", "g", "ns", It.IsAny())).Returns(Task.CompletedTask);
provider.Dispose();
_mockSvc.Verify(x => x.RemoveListener("d1", "g", It.IsAny()), Times.Once);
+ _mockSvc.Verify(x => x.RemoveListener("d2", "g", "ns", It.IsAny()), Times.Once);
}
[Fact]
@@ -80,11 +105,11 @@ public void MsConfigListener_Should_Not_Overwrite_When_Contains_Same_Key_And_Rec
var provider = GetProviderForMultiListeners();
provider.Load();
- MsConfigListener l1 = new MsConfigListener("d1", "g", false, provider, null);
- MsConfigListener l2 = new MsConfigListener("d2", "g", false, provider, null);
+ MsConfigListener l1 = new MsConfigListener(new ConfigListener() { DataId = "d1", Group = "g" }, provider, null);
+ MsConfigListener l2 = new MsConfigListener(new ConfigListener() { DataId = "d2", Group = "g", Namespace = "ns" }, provider, null);
- provider.SetListener("d1#g", l1);
- provider.SetListener("d2#g", l2);
+ provider.SetListener("cs#d1#g", l1);
+ provider.SetListener("ns#d2#g", l2);
l1.ReceiveConfigInfo(new { all = "d1_1" }.ToJsonString());
@@ -99,11 +124,11 @@ public void MsConfigListener_Should_Not_Overwrite_When_Contains_Same_Key_And_Rec
var provider = GetProviderForMultiListeners();
provider.Load();
- MsConfigListener l1 = new MsConfigListener("d1", "g", false, provider, null);
- MsConfigListener l2 = new MsConfigListener("d2", "g", false, provider, null);
+ MsConfigListener l1 = new MsConfigListener(new ConfigListener() { DataId = "d1", Group = "g" }, provider, null);
+ MsConfigListener l2 = new MsConfigListener(new ConfigListener() { DataId = "d2", Group = "g", Namespace = "ns" }, provider, null);
- provider.SetListener("d1#g", l1);
- provider.SetListener("d2#g", l2);
+ provider.SetListener("cs#d1#g", l1);
+ provider.SetListener("ns#d2#g", l2);
l2.ReceiveConfigInfo(new { all = "d2_1" }.ToJsonString());
@@ -115,7 +140,7 @@ public void MsConfigListener_Should_Not_Overwrite_When_Contains_Same_Key_And_Rec
private NacosV2ConfigurationProvider GetProviderForMultiListeners()
{
_mockSvc.Setup(x => x.GetConfig("d1", "g", 3000)).ReturnsAsync(new { all = "d1" }.ToJsonString());
- _mockSvc.Setup(x => x.GetConfig("d2", "g", 3000)).ReturnsAsync(new { all = "d2" }.ToJsonString());
+ _mockSvc.Setup(x => x.GetConfig("d2", "g", "ns", 3000)).ReturnsAsync(new { all = "d2" }.ToJsonString());
var cs = new NacosV2ConfigurationSource(null, null)
{
@@ -123,7 +148,7 @@ private NacosV2ConfigurationProvider GetProviderForMultiListeners()
Listeners = new System.Collections.Generic.List
{
new ConfigListener { DataId = "d1", Group = "g" },
- new ConfigListener { DataId = "d2", Group = "g" }
+ new ConfigListener { DataId = "d2", Group = "g", Namespace = "ns" }
},
NacosConfigurationParser = DefaultJsonConfigurationStringParser.Instance
};