private Task <IList <string> > CheckUpdateDataIds(IList <CacheData> cacheDatas, IList <string> inInitializingCacheList) { StringBuilder sb = new StringBuilder(); foreach (var cacheData in cacheDatas) { if (!cacheData.IsUseLocalConfig) { sb.Append(cacheData.DataId).Append(Constants.WORD_SEPARATOR); sb.Append(cacheData.Group).Append(Constants.WORD_SEPARATOR); if (string.IsNullOrEmpty(cacheData.Tenant)) { sb.Append(cacheData.MD5).Append(Constants.LINE_SEPARATOR); } else { sb.Append(cacheData.MD5).Append(Constants.WORD_SEPARATOR); sb.Append(cacheData.Tenant).Append(Constants.LINE_SEPARATOR); } if (cacheData.IsInitializing) { inInitializingCacheList.Add(GroupKey.GetKeyTenant(cacheData.DataId, cacheData.Group, cacheData.Tenant)); } } } bool isInitializingCacheList = inInitializingCacheList.Count > 0; return(CheckUpdateConfigStr(sb.ToString(), isInitializingCacheList)); }
private async Task <List <string> > CheckUpdateDataIds(List <CacheData> cacheDatas, List <string> inInitializingCacheList) { StringBuilder sb = new StringBuilder(); foreach (CacheData cacheData in cacheDatas) { if (!cacheData.IsUseLocalConfig) { sb.Append(cacheData.DataId).Append(Constants.WORD_SEPARATOR); sb.Append(cacheData.Group).Append(Constants.WORD_SEPARATOR); if (cacheData.Tenant.IsNullOrWhiteSpace()) { sb.Append(cacheData.Md5).Append(Constants.LINE_SEPARATOR); } else { sb.Append(cacheData.Md5).Append(Constants.WORD_SEPARATOR); sb.Append(cacheData.Tenant).Append(Constants.LINE_SEPARATOR); } if (cacheData.IsInitializing) { // It updates when cacheData occours in cacheMap by first time. inInitializingCacheList .Add(GroupKey.GetKeyTenant(cacheData.DataId, cacheData.Group, cacheData.Tenant)); } } } var isInitializingCacheList = inInitializingCacheList != null && inInitializingCacheList.Any(); return(await CheckUpdateConfigStr(sb.ToString(), isInitializingCacheList)); }
public CommonResponse RequestReply(CommonRequest request) { if (request is ConfigChangeNotifyRequest configChangeNotifyRequest) { string groupKey = GroupKey.GetKeyTenant(configChangeNotifyRequest.DataId, configChangeNotifyRequest.Group, configChangeNotifyRequest.Tenant); if (_cacheMap.TryGetValue(groupKey, out var cacheData)) { if (configChangeNotifyRequest.ContentPush && cacheData.LastModifiedTs < configChangeNotifyRequest.LastModifiedTs) { cacheData.SetContent(configChangeNotifyRequest.Content); cacheData.Type = configChangeNotifyRequest.Type; cacheData.CheckListenerMd5(); } cacheData.IsListenSuccess = false; // notifyListenConfig _func.Invoke().Wait(); } _logger?.LogDebug("Config RequestReply => {0}", request.ToJsonString()); return(new ConfigChangeNotifyResponse()); } return(null); }
private async Task <CacheData> AddCacheDataIfAbsent(string dataId, string group, string tenant) { var cache = GetCache(dataId, group, tenant); if (cache != null) { return(cache); } string key = GroupKey.GetKeyTenant(dataId, group, tenant); var cacheFromMap = GetCache(dataId, group, tenant); if (cacheFromMap != null) { cache = cacheFromMap; cache.IsInitializing = true; } else { cache = new CacheData(_configFilterChainManager, _localConfigInfoProcessor, _agent.GetName(), dataId, group, tenant); if (_enableRemoteSyncConfig) { string content = await GetServerConfig(dataId, group, tenant); cache.Content = content; } } _cacheMap.AddOrUpdate(key, cache, (k, v) => cache); _logger.Info($"[{_agent.GetName()}] [subscribe] {key}"); return(cache); }
private void RemoveCache(string dataId, string group, string tenant) { var groupKey = GroupKey.GetKeyTenant(dataId, group, tenant); _cacheMap.TryRemove(groupKey, out _); _logger?.LogInformation("[{0}] [unsubscribe] {1}", GetNameInner(), groupKey); }
internal void RemoveCache(string dataId, string group, string tenant = null) { string groupKey = tenant == null?GroupKey.GetKey(dataId, group) : GroupKey.GetKeyTenant(dataId, group, tenant); _cacheMap.TryRemove(groupKey, out _); _logger?.LogInformation("[{0}] [unsubscribe] {1}", this._agent.GetName(), groupKey); }
public CacheData GetCache(string dataId, string group, string tenant) { if (dataId == null || group == null) { throw new ArgumentException(); } return(_cacheMap.TryGetValue(GroupKey.GetKeyTenant(dataId, group, tenant), out var cache) ? cache : null); }
private void RemoveCache(string dataId, string group, string tenant) { string groupKey = GroupKey.GetKeyTenant(dataId, group, tenant); CacheData cache; _cacheMap.TryRemove(groupKey, out cache); _logger.Info($"[{_agent.GetName()}] [unsubscribe] {groupKey}"); }
private List <string> ParseUpdateDataIdResponse(string response) { if (string.IsNullOrEmpty(response)) { return(new List <string>()); } response = System.Net.WebUtility.UrlDecode(response); var updateList = new List <string>(); foreach (string dataIdAndGroup in response.SplitByString(Constants.LINE_SEPARATOR)) { if (!string.IsNullOrEmpty(dataIdAndGroup)) { var keyArr = dataIdAndGroup.SplitByString(Constants.WORD_SEPARATOR); if (keyArr.Length < 2) { continue; } string dataId = keyArr[0]; string group = keyArr[1]; if (keyArr.Length == 2) { updateList.Add(GroupKey.GetKey(dataId, group)); _logger?.LogInformation( "[{0}] [polling-resp] config changed. dataId={1}, group={2}", _agent.GetName(), dataId, group); } else if (keyArr.Length == 3) { string tenant = keyArr[2]; updateList.Add(GroupKey.GetKeyTenant(dataId, group, tenant)); _logger?.LogInformation( "[{0}] [polling-resp] config changed. dataId={1}, group={2}, tenant={3}", _agent.GetName(), dataId, group, tenant); } else { _logger?.LogError("[{0}] [polling-resp] invalid dataIdAndGroup error {1}", _agent.GetName(), dataIdAndGroup); } } } return(updateList); }
private CacheData GetCache(string dataId, string group, string tenant) { if (string.IsNullOrEmpty(dataId)) { throw new ArgumentNullException(nameof(dataId)); } if (string.IsNullOrEmpty(group)) { throw new ArgumentNullException(nameof(group)); } CacheData result = null; if (_cacheMap.TryGetValue(GroupKey.GetKeyTenant(dataId, group, tenant), out result)) { return(result); } return(result); }
private IList <string> ParseUpdateDataIdResponse(string response) { if (string.IsNullOrEmpty(response)) { return(null); } response = WebUtility.UrlDecode(response); var updateList = new List <string>(); foreach (string dataIdAndGroup in response.Split(Constants.LINE_SEPARATOR)) { if (!string.IsNullOrEmpty(dataIdAndGroup)) { var keyArr = dataIdAndGroup.Split(Constants.WORD_SEPARATOR); if (keyArr.Length < 2) { continue; } string dataId = keyArr[0]; string group = keyArr[1]; if (keyArr.Length == 2) { updateList.Add(GroupKey.GetKey(dataId, group)); _logger.Info($"[{_agent.GetName()}] [polling-resp] config changed. dataId={dataId}, group={group}"); } else if (keyArr.Length == 3) { string tenant = keyArr[2]; updateList.Add(GroupKey.GetKeyTenant(dataId, group, tenant)); _logger.Info($"[{_agent.GetName()}] [polling-resp] config changed. dataId={dataId}, group={group}, tenant={tenant}"); } else { _logger.Error($"[{_agent.GetName()}] [polling-resp] invalid dataIdAndGroup error {dataIdAndGroup}"); } } } return(updateList); }
protected async override Task ExecuteConfigListen() { var listenCachesMap = new Dictionary <string, List <CacheData> >(); var removeListenCachesMap = new Dictionary <string, List <CacheData> >(); // TODO: should update logic here..... foreach (var item in _cacheMap.Values) { if (item.GetListeners() != null && item.GetListeners().Any() && !item.IsListenSuccess) { if (!item.IsUseLocalConfig) { if (!listenCachesMap.TryGetValue(item.TaskId.ToString(), out var list)) { list = new List <CacheData>(); listenCachesMap[item.TaskId.ToString()] = list; } list.Add(item); } } else if ((item.GetListeners() == null || !item.GetListeners().Any()) && item.IsListenSuccess) { if (!item.IsUseLocalConfig) { if (!removeListenCachesMap.TryGetValue(item.TaskId.ToString(), out var list)) { list = new List <CacheData>(); removeListenCachesMap[item.TaskId.ToString()] = list; } list.Add(item); } } } if (listenCachesMap != null && listenCachesMap.Any()) { foreach (var task in listenCachesMap) { var taskId = task.Key; var listenCaches = task.Value; var request = new ConfigBatchListenRequest() { Listen = true }; foreach (var item in listenCaches) { request.AddConfigListenContext(item.Tenant, item.Group, item.DataId, item.Md5); } if (request.ConfigListenContexts != null && request.ConfigListenContexts.Any()) { try { var rpcClient = EnsureRpcClient(taskId); var configChangeBatchListenResponse = (ConfigChangeBatchListenResponse)(await RequestProxy(rpcClient, request)); if (configChangeBatchListenResponse != null && configChangeBatchListenResponse.IsSuccess()) { var changeKeys = new HashSet <string>(); if (configChangeBatchListenResponse.ChangedConfigs != null && configChangeBatchListenResponse.ChangedConfigs.Any()) { foreach (var item in configChangeBatchListenResponse.ChangedConfigs) { var changeKey = GroupKey.GetKeyTenant(item.DataId, item.Group, item.Tenant); changeKeys.Add(changeKey); await RefreshContentAndCheck(changeKey, true); } } foreach (var item in listenCaches) { if (!changeKeys.Contains(GroupKey.GetKeyTenant(item.DataId, item.Group, item.Tenant))) { item.IsListenSuccess = true; } } } } catch (Exception ex) { _logger?.LogError(ex, "async listen config change error "); } } } } if (removeListenCachesMap != null && removeListenCachesMap.Any()) { foreach (var task in removeListenCachesMap) { var taskId = task.Key; var removeListenCaches = task.Value; var request = new ConfigBatchListenRequest { Listen = false }; foreach (var item in removeListenCaches) { request.AddConfigListenContext(item.Tenant, item.Group, item.DataId, item.Md5); } if (request.ConfigListenContexts != null && request.ConfigListenContexts.Any()) { try { RpcClient rpcClient = EnsureRpcClient(taskId); var response = await RequestProxy(rpcClient, request); if (response != null && response.IsSuccess()) { foreach (var item in removeListenCaches) { RemoveCache(item.DataId, item.Group, item.Tenant); } } } catch (Exception ex) { _logger?.LogError(ex, "async remove listen config change error "); } } } } }
private Timer LongPolling(int taskId) { return(new Timer( async x => { var cacheDatas = new List <CacheData>(); var inInitializingCacheList = new List <string>(); int selfTaskId = -1; int.TryParse(x.ToString(), out selfTaskId); try { foreach (var cacheData in _cacheMap.Values) { // no listener should stop here. if (cacheData.TaskId == selfTaskId && cacheData.GetListeners() != null && cacheData.GetListeners().Any()) { cacheDatas.Add(cacheData); try { await CheckLocalConfig(_agent.GetName(), cacheData); if (cacheData.IsUseLocalConfig) { cacheData.CheckListenerMd5(); } } catch (Exception ex) { _logger?.LogError(ex, "get local config info error"); } } } var changedGroupKeys = await CheckUpdateDataIds(cacheDatas, inInitializingCacheList); foreach (string groupKey in changedGroupKeys) { string[] key = GroupKey.ParseKey(groupKey); string dataId = key[0]; string group = key[1]; string tenant = null; if (key.Length == 3) { tenant = key[2]; } try { List <string> ct = await GetServerConfig(dataId, group, tenant, 3000L, true); if (_cacheMap.TryGetValue(GroupKey.GetKeyTenant(dataId, group, tenant), out var cache)) { cache.SetContent(ct[0]); if (ct[1] != null) { cache.Type = ct[1]; } _logger?.LogInformation("[{0}] [data-received] dataId={1}, group={2}, tenant={3}, md5={4}, content={5}, type={6}", _agent.GetName(), dataId, group, tenant, cache.Md5, ContentUtils.TruncateContent(ct[0]), ct[1]); } } catch (Exception ioe) { _logger?.LogError(ioe, "[{0}] [get-update] get changed config exception. dataId={0}, group={2}, tenant={3}", _agent.GetName(), dataId, group, tenant); } } foreach (var cacheData in cacheDatas) { if (!cacheData.IsInitializing || inInitializingCacheList.Contains(GroupKey.GetKeyTenant(cacheData.DataId, cacheData.Group, cacheData.Tenant))) { cacheData.CheckListenerMd5(); cacheData.IsInitializing = false; } } inInitializingCacheList.Clear(); if (_longPollingMap.TryGetValue(selfTaskId, out var t)) { t.Change(1, Timeout.Infinite); } } catch (Exception ex) { _logger?.LogError(ex, "longPolling error"); if (_longPollingMap.TryGetValue(selfTaskId, out var t)) { t.Change(_taskPenaltyTime, Timeout.Infinite); } } }, taskId, 0, Timeout.Infinite)); }
protected override async Task <ConfigResponse> QueryConfig(string dataId, string group, string tenant, long readTimeous, bool notify) { try { var request = new ConfigQueryRequest(dataId, group, tenant); request.PutHeader(ConfigConstants.NOTIFY_HEADER, notify.ToString()); var rpcClient = GetOneRunningClient(); if (notify) { var key = GroupKey.GetKeyTenant(dataId, group, tenant); if (_cacheMap.TryGetValue(key, out var cacheData)) { rpcClient = EnsureRpcClient(cacheData.TaskId.ToString()); } } var response = (ConfigQueryResponse) await RequestProxy(rpcClient, request).ConfigureAwait(false); ConfigResponse configResponse = new ConfigResponse(); if (response.IsSuccess()) { await FileLocalConfigInfoProcessor.SaveSnapshotAsync(this.GetName(), dataId, group, tenant, response.Content).ConfigureAwait(false); configResponse.SetContent(response.Content); configResponse.SetConfigType(response.ContentType.IsNotNullOrWhiteSpace() ? response.ContentType : "text"); // in nacos 2.0.2 still do not return the EncryptedDataKey // so this always be null at this time!!! string encryptedDataKey = response.EncryptedDataKey; await FileLocalConfigInfoProcessor.SaveEncryptDataKeySnapshot(this.GetName(), dataId, group, tenant, encryptedDataKey).ConfigureAwait(false); configResponse.SetEncryptedDataKey(encryptedDataKey); return(configResponse); } else if (response.ErrorCode.Equals(ConfigQueryResponse.CONFIG_NOT_FOUND)) { await FileLocalConfigInfoProcessor.SaveSnapshotAsync(this.GetName(), dataId, group, tenant, null).ConfigureAwait(false); await FileLocalConfigInfoProcessor.SaveEncryptDataKeySnapshot(this.GetName(), dataId, group, tenant, null).ConfigureAwait(false); return(configResponse); } else if (response.ErrorCode.Equals(ConfigQueryResponse.CONFIG_QUERY_CONFLICT)) { _logger?.LogError( "[{0}] [sub-server-error] get server config being modified concurrently, dataId={1}, group={2}, tenant={3}", GetName(), dataId, group, tenant); throw new NacosException(NacosException.CONFLICT, $"data being modified, dataId={dataId},group={group},tenant={tenant}"); } else { _logger?.LogError( "[{0}] [sub-server-error] dataId={1}, group={2}, tenant={3}, code={4}", GetName(), dataId, group, tenant, response.ToJsonString()); throw new NacosException(response.ErrorCode, $"http error, code={response.ErrorCode}, dataId={dataId},group={group},tenant={tenant}"); } } catch (Exception ex) { _logger?.LogError(ex, "[{0}] [sub-server-error] dataId={1}, group={2}, tenant={3}, code={4} ", GetName(), dataId, group, tenant, ex.Message); throw; } }
private Timer LongPolling(int taskId) { return(new Timer(async x => { var cacheDatas = new List <CacheData>(); var inInitializingCacheList = new List <string>(); int selfTaskId = -1; int.TryParse(x.ToString(), out selfTaskId); try { foreach (var cacheData in _cacheMap.Values) { if (cacheData.TaskId == selfTaskId) { cacheDatas.Add(cacheData); try { CheckLocalConfig(cacheData); if (cacheData.IsUseLocalConfig) { cacheData.CheckListenerMD5(); } } catch (Exception ex) { _logger.Error(ex, "get local config info error"); } } } var changedGroupKeys = await CheckUpdateDataIds(cacheDatas, inInitializingCacheList); foreach (string groupKey in changedGroupKeys) { string[] key = GroupKey.ParseKey(groupKey); string dataId = key[0]; string group = key[1]; string tenant = null; if (key.Length == 3) { tenant = key[2]; } try { string content = await GetServerConfig(dataId, group, tenant); CacheData cache = null; if (_cacheMap.TryGetValue(GroupKey.GetKeyTenant(dataId, group, tenant), out cache)) { cache.Content = content; _logger.Info($"[{_agent.GetName()}] [data-received] dataId={dataId}, group={group}, tenant={tenant}, md5={cache.MD5}, content={ContentUtils.TruncateContent(content)}"); } } catch (Exception ex) { _logger.Error(ex, $"[{_agent.GetName()}] [get-update] get changed config exception. dataId={dataId}, group={group}, tenant={tenant}"); } } foreach (var cacheData in cacheDatas) { if (!cacheData.IsInitializing || inInitializingCacheList.Contains(GroupKey.GetKeyTenant(cacheData.DataId, cacheData.Group, cacheData.Tenant))) { cacheData.CheckListenerMD5(); cacheData.IsInitializing = false; } } inInitializingCacheList.Clear(); Timer t = null; if (_longPollingMap.TryGetValue(selfTaskId, out t)) { t.Change(1, Timeout.Infinite); } } catch (Exception ex) { _logger.Error(ex, "longPolling error"); Timer t = null; if (_longPollingMap.TryGetValue(selfTaskId, out t)) { t.Change(_taskPenaltyTime, Timeout.Infinite); } } }, taskId, 0, Timeout.Infinite)); }