Skip to content

Commit 0c14bef

Browse files
author
agile.zhou
committed
Use publish timeline virtual id to compare the version between client
1 parent a52f028 commit 0c14bef

File tree

10 files changed

+157
-34
lines changed

10 files changed

+157
-34
lines changed

src/AgileConfig.Server.Apisite/Controllers/api/ConfigController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using AgileConfig.Server.Apisite.Models.Mapping;
1010
using AgileConfig.Server.Data.Entity;
1111
using AgileConfig.Server.IService;
12+
using Microsoft.AspNetCore.Http;
1213
using Microsoft.AspNetCore.Mvc;
1314
using Microsoft.Extensions.Caching.Memory;
1415

@@ -59,6 +60,9 @@ public async Task<ActionResult<List<ApiConfigVM>>> GetAppConfig(string appId, [F
5960
return NotFound();
6061
}
6162

63+
var publishTimelineId = await _configService.GetLastPublishTimelineVirtualIdAsync(appId, env.Value);
64+
Response.Headers.Append("publish-time-line-id", publishTimelineId);
65+
6266
var cacheKey = $"ConfigController_AppConfig_{appId}_{env.Value}";
6367
List<ApiConfigVM> configs = null;
6468
_cacheMemory?.TryGetValue(cacheKey, out configs);
@@ -67,7 +71,7 @@ public async Task<ActionResult<List<ApiConfigVM>>> GetAppConfig(string appId, [F
6771
return configs;
6872
}
6973

70-
var appConfigs = await _configService.GetPublishedConfigsByAppIdWithInheritanced(appId, env.Value);
74+
var appConfigs = await _configService.GetPublishedConfigsByAppIdWithInheritance(appId, env.Value);
7175
var vms = appConfigs.Select(x => x.ToApiConfigVM()).ToList();
7276

7377
//增加5s的缓存,防止同一个app同时启动造成db的压力过大

src/AgileConfig.Server.Apisite/Websocket/MessageHandlers/MessageHandler.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,19 @@ internal class MessageHandler : IMessageHandler
1919
private readonly IConfigService _configService;
2020
private readonly IRegisterCenterService _registerCenterService;
2121
private readonly IServiceInfoService _serviceInfoService;
22-
22+
23+
private int ClientVersion { get; set; }
24+
2325
public MessageHandler(
24-
IConfigService configService,
25-
IRegisterCenterService registerCenterService,
26+
IConfigService configService,
27+
IRegisterCenterService registerCenterService,
2628
IServiceInfoService serviceInfoService)
2729
{
2830
_configService = configService;
2931
_registerCenterService = registerCenterService;
3032
_serviceInfoService = serviceInfoService;
3133
}
32-
34+
3335
public bool Hit(HttpRequest request)
3436
{
3537
var ver = request.Headers["client-v"];
@@ -40,6 +42,8 @@ public bool Hit(HttpRequest request)
4042

4143
if (int.TryParse(ver.ToString().Replace(".", ""), out var verInt))
4244
{
45+
ClientVersion = verInt;
46+
4347
return verInt >= 160;
4448
}
4549

@@ -63,12 +67,14 @@ public async Task Handle(string message, HttpRequest request, WebsocketClient cl
6367
appId = HttpUtility.UrlDecode(appId);
6468
var env = request.Headers["env"].ToString();
6569
ISettingService.IfEnvEmptySetDefault(ref env);
66-
var md5 = await _configService.AppPublishedConfigsMd5CacheWithInheritanced(appId, env);
70+
71+
var data = await GetCPingData(appId, env);
72+
6773
await SendMessage(client.Client, JsonConvert.SerializeObject(new WebsocketAction()
6874
{
6975
Action = ActionConst.Ping,
7076
Module = ActionModule.ConfigCenter,
71-
Data = md5
77+
Data = data
7278
}));
7379
}
7480
else if (message.StartsWith("s:ping:"))
@@ -98,4 +104,22 @@ await SendMessage(client.Client, JsonConvert.SerializeObject(new WebsocketAction
98104
await SendMessage(client.Client, "0");
99105
}
100106
}
107+
108+
private async Task<string> GetCPingData(string appId, string env)
109+
{
110+
if (ClientVersion <= 176)
111+
{
112+
// 1.7.6及以前的版本,返回V:md5
113+
var md5 = await _configService.AppPublishedConfigsMd5CacheWithInheritance(appId, env);
114+
115+
return md5;
116+
}
117+
else
118+
{
119+
// 1.7.7及以后的版本,返回 publish time line id
120+
var publishTimeLineId = await _configService.GetLastPublishTimelineVirtualIdAsyncWithCache(appId, env);
121+
122+
return publishTimeLineId;
123+
}
124+
}
101125
}

src/AgileConfig.Server.Apisite/Websocket/MessageHandlers/OldMessageHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public async Task Handle(string message, HttpRequest request, WebsocketClient cl
4646
var appId = request.Headers["appid"];
4747
var env = request.Headers["env"].ToString();
4848
env = ISettingService.IfEnvEmptySetDefault(ref env);
49-
var md5 = await _configService.AppPublishedConfigsMd5CacheWithInheritanced(appId, env);
49+
var md5 = await _configService.AppPublishedConfigsMd5CacheWithInheritance(appId, env);
5050
await SendMessage(client.Client, $"V:{md5}");
5151
}
5252
else

src/AgileConfig.Server.Data.Abstraction/IPublishTimelineRepository.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ namespace AgileConfig.Server.Data.Abstraction
44
{
55
public interface IPublishTimelineRepository : IRepository<PublishTimeline, string>
66
{
7+
Task<string> GetLastPublishTimelineNodeIdAsync(string appId, string env);
78
}
89
}

src/AgileConfig.Server.Data.Repository.Freesql/PublishTimelineRepository.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,15 @@ public PublishTimelineRepository(IFreeSql freeSql) : base(freeSql)
1212
{
1313
this.freeSql = freeSql;
1414
}
15+
16+
public async Task<string> GetLastPublishTimelineNodeIdAsync(string appId, string env)
17+
{
18+
var node = await freeSql.Select<PublishTimeline>()
19+
.Where(x => x.AppId == appId && x.Env == env)
20+
.OrderByDescending(x => x.Version)
21+
.FirstAsync();
22+
23+
return node?.Id;
24+
}
1525
}
1626
}
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
namespace AgileConfig.Server.Data.Repository.Mongodb;
1+

2+
namespace AgileConfig.Server.Data.Repository.Mongodb;
23

3-
public class PublishTimelineRepository: MongodbRepository<PublishTimeline, string>, IPublishTimelineRepository
4+
public class PublishTimelineRepository : MongodbRepository<PublishTimeline, string>, IPublishTimelineRepository
45
{
56
public PublishTimelineRepository(string? connectionString) : base(connectionString)
67
{
@@ -10,4 +11,11 @@ public PublishTimelineRepository(string? connectionString) : base(connectionStri
1011
public PublishTimelineRepository(IConfiguration configuration) : base(configuration)
1112
{
1213
}
14+
15+
public async Task<string> GetLastPublishTimelineNodeIdAsync(string appId, string env)
16+
{
17+
var nodes = await this.QueryPageAsync(x => x.AppId == appId && x.Env == env, 1, 1, nameof(PublishTimeline.Version), "DESC");
18+
19+
return nodes?.FirstOrDefault()?.Id;
20+
}
1321
}

src/AgileConfig.Server.IService/IConfigService.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ public interface IConfigService: IDisposable
3636
/// </summary>
3737
/// <param name="appId"></param>
3838
/// <returns></returns>
39-
Task<List<Config>> GetPublishedConfigsByAppIdWithInheritanced(string appId, string env);
39+
Task<List<Config>> GetPublishedConfigsByAppIdWithInheritance(string appId, string env);
4040
/// <summary>
4141
/// 获取app的配置项继承的app配置合并进来转换为字典
4242
/// </summary>
4343
/// <param name="appId"></param>
4444
/// <returns></returns>
45-
Task<Dictionary<string, Config>> GetPublishedConfigsByAppIdWithInheritanced_Dictionary(string appId, string env);
45+
Task<Dictionary<string, Config>> GetPublishedConfigsByAppIdWithInheritance_Dictionary(string appId, string env);
4646
Task<bool> AddAsync(Config config, string env);
4747

4848
Task<bool> AddRangeAsync(List<Config> configs, string env);
@@ -77,7 +77,7 @@ public interface IConfigService: IDisposable
7777
/// </summary>
7878
/// <param name="appId"></param>
7979
/// <returns></returns>
80-
Task<string> AppPublishedConfigsMd5WithInheritanced(string appId, string env);
80+
Task<string> AppPublishedConfigsMd5WithInheritance(string appId, string env);
8181

8282
/// <summary>
8383
/// 计算已发布配置项的MD5进行缓存
@@ -91,7 +91,7 @@ public interface IConfigService: IDisposable
9191
/// </summary>
9292
/// <param name="appId"></param>
9393
/// <returns></returns>
94-
Task<string> AppPublishedConfigsMd5CacheWithInheritanced(string appId, string env);
94+
Task<string> AppPublishedConfigsMd5CacheWithInheritance(string appId, string env);
9595

9696
/// <summary>
9797
/// 构造key
@@ -213,5 +213,10 @@ public interface IConfigService: IDisposable
213213
/// clear all cache
214214
/// </summary>
215215
void ClearCache();
216+
217+
Task<string> GetLastPublishTimelineVirtualIdAsync(string appId, string env);
218+
219+
Task<string> GetLastPublishTimelineVirtualIdAsyncWithCache(string appId, string env);
220+
216221
}
217222
}

src/AgileConfig.Server.Service/ConfigService.cs

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,14 @@ private string AppPublishedConfigsMd5CacheKey(string appId, string env)
308308
return $"ConfigService_AppPublishedConfigsMd5Cache_{appId}_{env}";
309309
}
310310

311-
private string AppPublishedConfigsMd5CacheKeyWithInheritanced(string appId, string env)
311+
private string AppPublishedConfigsMd5CacheKeyWithInheritance(string appId, string env)
312312
{
313-
return $"ConfigService_AppPublishedConfigsMd5CacheWithInheritanced_{appId}_{env}";
313+
return $"ConfigService_AppPublishedConfigsMd5CacheWithInheritance_{appId}_{env}";
314+
}
315+
316+
private string AppPublishTimelineVirtualIdCacheKey(string appId, string env)
317+
{
318+
return $"ConfigService_AppPublishTimelineVirtualIdWithCache_{appId}_{env}";
314319
}
315320

316321
private void ClearAppPublishedConfigsMd5Cache(string appId, string env)
@@ -319,9 +324,15 @@ private void ClearAppPublishedConfigsMd5Cache(string appId, string env)
319324
_memoryCache?.Remove(cacheKey);
320325
}
321326

322-
private void ClearAppPublishedConfigsMd5CacheWithInheritanced(string appId, string env)
327+
private void ClearAppPublishedConfigsMd5CacheWithInheritance(string appId, string env)
328+
{
329+
var cacheKey = AppPublishedConfigsMd5CacheKeyWithInheritance(appId, env);
330+
_memoryCache?.Remove(cacheKey);
331+
}
332+
333+
private void ClearAppPublishTimelineVirtualIdCache(string appId, string env)
323334
{
324-
var cacheKey = AppPublishedConfigsMd5CacheKeyWithInheritanced(appId, env);
335+
var cacheKey = AppPublishTimelineVirtualIdCacheKey(appId, env);
325336
_memoryCache?.Remove(cacheKey);
326337
}
327338

@@ -338,8 +349,10 @@ public async Task<bool> AddRangeAsync(List<Config> configs, string env)
338349
using var repository = _configRepositoryAccessor(env);
339350
await repository.InsertAsync(configs);
340351

341-
ClearAppPublishedConfigsMd5Cache(configs.First().AppId, env);
342-
ClearAppPublishedConfigsMd5CacheWithInheritanced(configs.First().AppId, env);
352+
var appId = configs.First().AppId;
353+
ClearAppPublishedConfigsMd5Cache(appId,env);
354+
ClearAppPublishedConfigsMd5CacheWithInheritance(appId, env);
355+
ClearAppPublishTimelineVirtualIdCache(appId, env);
343356

344357
return true;
345358
}
@@ -349,9 +362,9 @@ public async Task<bool> AddRangeAsync(List<Config> configs, string env)
349362
/// </summary>
350363
/// <param name="appId"></param>
351364
/// <returns></returns>
352-
public async Task<List<Config>> GetPublishedConfigsByAppIdWithInheritanced(string appId, string env)
365+
public async Task<List<Config>> GetPublishedConfigsByAppIdWithInheritance(string appId, string env)
353366
{
354-
var configs = await GetPublishedConfigsByAppIdWithInheritanced_Dictionary(appId, env);
367+
var configs = await GetPublishedConfigsByAppIdWithInheritance_Dictionary(appId, env);
355368

356369
return configs.Values.ToList();
357370
}
@@ -361,7 +374,7 @@ public async Task<List<Config>> GetPublishedConfigsByAppIdWithInheritanced(strin
361374
/// </summary>
362375
/// <param name="appId"></param>
363376
/// <returns></returns>
364-
public async Task<Dictionary<string, Config>> GetPublishedConfigsByAppIdWithInheritanced_Dictionary(
377+
public async Task<Dictionary<string, Config>> GetPublishedConfigsByAppIdWithInheritance_Dictionary(
365378
string appId, string env)
366379
{
367380
var apps = new List<string>();
@@ -401,9 +414,9 @@ public async Task<Dictionary<string, Config>> GetPublishedConfigsByAppIdWithInhe
401414
return configs;
402415
}
403416

404-
public async Task<string> AppPublishedConfigsMd5WithInheritanced(string appId, string env)
417+
public async Task<string> AppPublishedConfigsMd5WithInheritance(string appId, string env)
405418
{
406-
var configs = await GetPublishedConfigsByAppIdWithInheritanced(appId, env);
419+
var configs = await GetPublishedConfigsByAppIdWithInheritance(appId, env);
407420

408421
var keyStr = string.Join('&', configs.Select(c => GenerateKey(c)).ToArray().OrderBy(k => k, StringComparer.Ordinal));
409422
var valStr = string.Join('&', configs.Select(c => c.Value).ToArray().OrderBy(v => v, StringComparer.Ordinal));
@@ -417,15 +430,15 @@ public async Task<string> AppPublishedConfigsMd5WithInheritanced(string appId, s
417430
/// </summary>
418431
/// <param name="appId"></param>
419432
/// <returns></returns>
420-
public async Task<string> AppPublishedConfigsMd5CacheWithInheritanced(string appId, string env)
433+
public async Task<string> AppPublishedConfigsMd5CacheWithInheritance(string appId, string env)
421434
{
422-
var cacheKey = AppPublishedConfigsMd5CacheKeyWithInheritanced(appId, env);
435+
var cacheKey = AppPublishedConfigsMd5CacheKeyWithInheritance(appId, env);
423436
if (_memoryCache != null && _memoryCache.TryGetValue(cacheKey, out string md5))
424437
{
425438
return md5;
426439
}
427440

428-
md5 = await AppPublishedConfigsMd5WithInheritanced(appId, env);
441+
md5 = await AppPublishedConfigsMd5WithInheritance(appId, env);
429442

430443
var cacheOp = new MemoryCacheEntryOptions()
431444
.SetAbsoluteExpiration(TimeSpan.FromSeconds(60));
@@ -614,7 +627,8 @@ public void Dispose()
614627
await uow?.SaveChangesAsync();
615628

616629
ClearAppPublishedConfigsMd5Cache(appId, env);
617-
ClearAppPublishedConfigsMd5CacheWithInheritanced(appId, env);
630+
ClearAppPublishedConfigsMd5CacheWithInheritance(appId, env);
631+
ClearAppPublishTimelineVirtualIdCache(appId, env);
618632

619633
return (true, publishTimelineNode.Id);
620634
}
@@ -777,7 +791,8 @@ public async Task<bool> RollbackAsync(string publishTimelineId, string env)
777791
await uow?.SaveChangesAsync();
778792

779793
ClearAppPublishedConfigsMd5Cache(appId, env);
780-
ClearAppPublishedConfigsMd5CacheWithInheritanced(appId, env);
794+
ClearAppPublishedConfigsMd5CacheWithInheritance(appId, env);
795+
ClearAppPublishTimelineVirtualIdCache(appId,env);
781796

782797
return true;
783798
}
@@ -1077,5 +1092,61 @@ public async Task<bool> SaveKvListAsync(string kvString, string appId, string en
10771092

10781093
return ("", key);
10791094
}
1095+
1096+
/// <summary>
1097+
/// Generate the virtual id representing the last publish timeline node of the app and its inherited apps.
1098+
/// </summary>
1099+
/// <param name="appId"></param>
1100+
/// <param name="env"></param>
1101+
/// <returns></returns>
1102+
public async Task<string> GetLastPublishTimelineVirtualIdAsync(string appId, string env)
1103+
{
1104+
using var publishTimelineRepository = _publishTimelineRepositoryAccsssor(env);
1105+
1106+
var apps = new List<string>();
1107+
var inheritanceApps = await _appService.GetInheritancedAppsAsync(appId);
1108+
for (int i = 0; i < inheritanceApps.Count; i++)
1109+
{
1110+
if (inheritanceApps[i].Enabled)
1111+
{
1112+
apps.Add(inheritanceApps[i].Id as string); //后继承的排在后面
1113+
}
1114+
}
1115+
1116+
apps.Add(appId); //本应用放在最后
1117+
1118+
var ids = new List<string>();
1119+
1120+
foreach (var app in apps)
1121+
{
1122+
var id = await publishTimelineRepository.GetLastPublishTimelineNodeIdAsync(app, env);
1123+
ids.Add(id);
1124+
}
1125+
1126+
return string.Join('|', ids);
1127+
}
1128+
1129+
/// <summary>
1130+
/// Generate the virtual id representing the last publish timeline node of the app and its inherited apps, with cache.
1131+
/// </summary>
1132+
/// <param name="appId"></param>
1133+
/// <param name="env"></param>
1134+
/// <returns></returns>
1135+
public async Task<string> GetLastPublishTimelineVirtualIdAsyncWithCache(string appId, string env)
1136+
{
1137+
var cacheKey = AppPublishTimelineVirtualIdCacheKey(appId, env);
1138+
if (_memoryCache != null && _memoryCache.TryGetValue(cacheKey, out string vId))
1139+
{
1140+
return vId;
1141+
}
1142+
1143+
vId = await GetLastPublishTimelineVirtualIdAsync(appId, env);
1144+
1145+
var cacheOp = new MemoryCacheEntryOptions()
1146+
.SetAbsoluteExpiration(TimeSpan.FromSeconds(60));
1147+
_memoryCache?.Set(cacheKey, vId, cacheOp);
1148+
1149+
return vId;
1150+
}
10801151
}
10811152
}

0 commit comments

Comments
 (0)