From e37858c01c3eb90499703e413c786c35f2ec9f21 Mon Sep 17 00:00:00 2001 From: "agile.zhou" Date: Wed, 3 Jan 2024 02:54:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=A8=20freesql=20?= =?UTF-8?q?=E4=B8=8B=E7=9A=84=E4=B8=80=E4=BA=9B=E9=97=AE=E9=A2=98=E3=80=82?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=9A=84=E8=AF=A5=E5=88=A0=E9=99=A4=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E8=83=BD=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AgileConfig.sln | 15 +- .../Controllers/ServerNodeController.cs | 19 ++- .../appsettings.Development.json | 8 +- .../appsettings.json | 3 - .../IRepository.cs | 2 +- .../AgileConfig.Server.Data.Freesql.csproj | 3 +- .../EnvFreeSqlFactory.cs | 7 +- .../FreeSQL.cs | 5 + .../FreesqlRepository.cs | 4 +- .../ServiceCollectionExt.cs | 2 +- .../SysInitRepository.cs | 2 +- ...fig.Server.Data.Repository.Selector.csproj | 15 ++ .../RepositoryExtension.cs | 151 ++++++++++++++++++ .../ConfigService.cs | 5 +- 14 files changed, 216 insertions(+), 25 deletions(-) create mode 100644 src/AgileConfig.Server.Data.Repository.Selector/AgileConfig.Server.Data.Repository.Selector.csproj create mode 100644 src/AgileConfig.Server.Data.Repository.Selector/RepositoryExtension.cs diff --git a/AgileConfig.sln b/AgileConfig.sln index 9c9334c3..cc090078 100644 --- a/AgileConfig.sln +++ b/AgileConfig.sln @@ -38,13 +38,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.CommonTe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.OIDC", "src\AgileConfig.Server.OIDC\AgileConfig.Server.OIDC.csproj", "{E49A2006-6D07-4434-AEC1-27E356A767AE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Data.Mongodb", "src\AgileConfig.Server.Data.Mongodb\AgileConfig.Server.Data.Mongodb.csproj", "{4803646E-8327-4F69-8BA5-2244CB58BBA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.Data.Mongodb", "src\AgileConfig.Server.Data.Mongodb\AgileConfig.Server.Data.Mongodb.csproj", "{4803646E-8327-4F69-8BA5-2244CB58BBA2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Data.Abstraction", "src\AgileConfig.Server.Data.Abstraction\AgileConfig.Server.Data.Abstraction.csproj", "{E8101403-72C9-40FB-BCEE-16ED5C23A495}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.Data.Abstraction", "src\AgileConfig.Server.Data.Abstraction\AgileConfig.Server.Data.Abstraction.csproj", "{E8101403-72C9-40FB-BCEE-16ED5C23A495}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Data.Repository.Freesql", "src\AgileConfig.Server.Data.Repository.Freesql\AgileConfig.Server.Data.Repository.Freesql.csproj", "{955F64CC-9EAC-4563-804D-6E2CF9547357}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.Data.Repository.Freesql", "src\AgileConfig.Server.Data.Repository.Freesql\AgileConfig.Server.Data.Repository.Freesql.csproj", "{955F64CC-9EAC-4563-804D-6E2CF9547357}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Data.Repository.Mongodb", "src\AgileConfig.Server.Data.Repository.Mongodb\AgileConfig.Server.Data.Repository.Mongodb.csproj", "{C6B7A5A6-7287-4A20-9336-EBE82A5256F1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AgileConfig.Server.Data.Repository.Mongodb", "src\AgileConfig.Server.Data.Repository.Mongodb\AgileConfig.Server.Data.Repository.Mongodb.csproj", "{C6B7A5A6-7287-4A20-9336-EBE82A5256F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Data.Repository.Selector", "src\AgileConfig.Server.Data.Repository.Selector\AgileConfig.Server.Data.Repository.Selector.csproj", "{15089E5A-12E4-4953-BA35-0CBB2B1189C0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -112,6 +114,10 @@ Global {C6B7A5A6-7287-4A20-9336-EBE82A5256F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6B7A5A6-7287-4A20-9336-EBE82A5256F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6B7A5A6-7287-4A20-9336-EBE82A5256F1}.Release|Any CPU.Build.0 = Release|Any CPU + {15089E5A-12E4-4953-BA35-0CBB2B1189C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15089E5A-12E4-4953-BA35-0CBB2B1189C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15089E5A-12E4-4953-BA35-0CBB2B1189C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15089E5A-12E4-4953-BA35-0CBB2B1189C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -132,6 +138,7 @@ Global {E8101403-72C9-40FB-BCEE-16ED5C23A495} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E} {955F64CC-9EAC-4563-804D-6E2CF9547357} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E} {C6B7A5A6-7287-4A20-9336-EBE82A5256F1} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E} + {15089E5A-12E4-4953-BA35-0CBB2B1189C0} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7F10DB58-5B6F-4EAC-994F-14E8046B306F} diff --git a/src/AgileConfig.Server.Apisite/Controllers/ServerNodeController.cs b/src/AgileConfig.Server.Apisite/Controllers/ServerNodeController.cs index 53c2eb70..23058edf 100644 --- a/src/AgileConfig.Server.Apisite/Controllers/ServerNodeController.cs +++ b/src/AgileConfig.Server.Apisite/Controllers/ServerNodeController.cs @@ -32,7 +32,7 @@ public ServerNodeController(IServerNodeService serverNodeService, [TypeFilter(typeof(PremissionCheckAttribute), Arguments = new object[] { "Node.Add", Functions.Node_Add })] [HttpPost] - public async Task Add([FromBody]ServerNodeVM model) + public async Task Add([FromBody] ServerNodeVM model) { if (model == null) { @@ -64,7 +64,7 @@ public async Task Add([FromBody]ServerNodeVM model) TinyEventBus.Instance.Fire(EventKeys.ADD_NODE_SUCCESS, param); await _remoteServerNodeProxy.TestEchoAsync(node.Id); } - + return Json(new { data = node, @@ -75,7 +75,7 @@ public async Task Add([FromBody]ServerNodeVM model) [TypeFilter(typeof(PremissionCheckAttribute), Arguments = new object[] { "Node.Delete", Functions.Node_Delete })] [HttpPost] - public async Task Delete([FromBody]ServerNodeVM model) + public async Task Delete([FromBody] ServerNodeVM model) { if (Appsettings.IsPreviewMode) { @@ -120,10 +120,21 @@ public async Task All() { var nodes = await _serverNodeService.GetAllNodesAsync(); + var vms = nodes.OrderBy(x => x.CreateTime).Select(x => + { + return new ServerNodeVM + { + Address = x.Id, + Remark = x.Remark, + LastEchoTime = x.LastEchoTime, + Status = x.Status + }; + }); + return Json(new { success = true, - data = nodes.OrderBy(n => n.CreateTime) + data = vms }); } } diff --git a/src/AgileConfig.Server.Apisite/appsettings.Development.json b/src/AgileConfig.Server.Apisite/appsettings.Development.json index 8855c93a..7a6779ab 100644 --- a/src/AgileConfig.Server.Apisite/appsettings.Development.json +++ b/src/AgileConfig.Server.Apisite/appsettings.Development.json @@ -14,10 +14,10 @@ "pathBase": "", //使用反向代理的时候,或许需要修改这个值 /xxx 必须/开头 "adminConsole": true, "cluster": false, // 集群模式:服务启动后自动加入节点列表,服务启动的时候会获取容器的ip,端口默认5000,适合 docker compose 环境使用 - "preview_mode": true, + "preview_mode": false, "db": { - "provider": "mongodb", //sqlite,mysql,sqlserver,npgsql,oracle,mongodb - "conn": "mongodb://localhost:27017,localhost:37017/AgileConfig", + "provider": "sqlite", //sqlite,mysql,sqlserver,npgsql,oracle,mongodb + "conn": "Data Source=agile_config.db", //"provider": "sqlserver", //"conn": "Encrypt=True;TrustServerCertificate=True;Persist Security Info = False; User ID =dev; Password =dev@123; Initial Catalog =agile_config; Server =192.168.18.82" //"provider": "npgsql", @@ -26,6 +26,8 @@ //"conn": "user id=CLINIC;password=CLINIC;data source=192.168.0.91/orcl" //"provider": "mysql", //"conn": "Database=agile_config;Data Source=192.168.0.125;User Id=root;Password=x;port=13306;Allow User Variables=true;", + //"provider": "mongodb", + //"conn": "mongodb://localhost:27017,localhost:37017/AgileConfig", "env": { "TEST": { "provider": "sqlite", //sqlite,mysql,sqlserver,npgsql,oracle diff --git a/src/AgileConfig.Server.Apisite/appsettings.json b/src/AgileConfig.Server.Apisite/appsettings.json index 9940e82b..8227ccb6 100644 --- a/src/AgileConfig.Server.Apisite/appsettings.json +++ b/src/AgileConfig.Server.Apisite/appsettings.json @@ -18,9 +18,6 @@ "db": { "provider": "", //sqlite,mysql,sqlserver,npgsql,oracle,mongodb "conn": "", - //"conn": "Data Source=agile_config.db" - //"conn": "Persist Security Info = False; User ID =dev; Password =dev@123; Initial Catalog =agile_config; Server =." - //"conn": "mongodb://user:password@localhost:27017,localhost:37017/database-name?authSource=admin" "env": { "TEST": { "provider": "", //sqlite,mysql,sqlserver,npgsql,oracle diff --git a/src/AgileConfig.Server.Data.Abstraction/IRepository.cs b/src/AgileConfig.Server.Data.Abstraction/IRepository.cs index 062393d4..584dc22a 100644 --- a/src/AgileConfig.Server.Data.Abstraction/IRepository.cs +++ b/src/AgileConfig.Server.Data.Abstraction/IRepository.cs @@ -12,7 +12,7 @@ public interface IRepository : IDisposable where T : IEntity Task UpdateAsync(IList entities); Task DeleteAsync(T1 id); - + Task DeleteAsync(T entity); Task DeleteAsync(IList entities); diff --git a/src/AgileConfig.Server.Data.Freesql/AgileConfig.Server.Data.Freesql.csproj b/src/AgileConfig.Server.Data.Freesql/AgileConfig.Server.Data.Freesql.csproj index f4a5e629..d6fec744 100644 --- a/src/AgileConfig.Server.Data.Freesql/AgileConfig.Server.Data.Freesql.csproj +++ b/src/AgileConfig.Server.Data.Freesql/AgileConfig.Server.Data.Freesql.csproj @@ -1,7 +1,8 @@  - net8.0 + enable + net8.0 diff --git a/src/AgileConfig.Server.Data.Freesql/EnvFreeSqlFactory.cs b/src/AgileConfig.Server.Data.Freesql/EnvFreeSqlFactory.cs index 78c5f80d..44cff2c5 100644 --- a/src/AgileConfig.Server.Data.Freesql/EnvFreeSqlFactory.cs +++ b/src/AgileConfig.Server.Data.Freesql/EnvFreeSqlFactory.cs @@ -4,14 +4,15 @@ namespace AgileConfig.Server.Data.Freesql { public class EnvFreeSqlFactory : IFreeSqlFactory { - private readonly IEnvAccessor _envAccessor; + private readonly string _env; public EnvFreeSqlFactory(IEnvAccessor envAccessor) { - _envAccessor = envAccessor; + _env = envAccessor.Env; } + public IFreeSql Create() { - return FreeSQL.GetInstanceByEnv(_envAccessor.Env); + return FreeSQL.GetInstanceByEnv(_env); } } } diff --git a/src/AgileConfig.Server.Data.Freesql/FreeSQL.cs b/src/AgileConfig.Server.Data.Freesql/FreeSQL.cs index c7f42a07..ade93a16 100644 --- a/src/AgileConfig.Server.Data.Freesql/FreeSQL.cs +++ b/src/AgileConfig.Server.Data.Freesql/FreeSQL.cs @@ -37,6 +37,11 @@ public static IFreeSql GetInstanceByEnv(string env) var provider = Global.Config[$"db:env:{env}:provider"]; var conn = Global.Config[$"db:env:{env}:conn"]; + if (string.IsNullOrEmpty(provider)) + { + return Instance; + } + var key = provider; if (_envFreesqls.ContainsKey(key)) diff --git a/src/AgileConfig.Server.Data.Freesql/FreesqlRepository.cs b/src/AgileConfig.Server.Data.Freesql/FreesqlRepository.cs index c6e93d84..9a8fed47 100644 --- a/src/AgileConfig.Server.Data.Freesql/FreesqlRepository.cs +++ b/src/AgileConfig.Server.Data.Freesql/FreesqlRepository.cs @@ -37,7 +37,7 @@ public Task DeleteAsync(IList entities) return _repository.DeleteAsync(entities); } - public Task GetAsync(T1 id) + public Task GetAsync(T1 id) { return _repository.Where(x => x.Id.Equals(id)).ToOneAsync(); } @@ -91,7 +91,7 @@ private Expression> Sort(string defaultSortField) return defaultSort; } - public async Task CountAsync(Expression> exp = null) + public async Task CountAsync(Expression>? exp = null) { return await (exp == null ? _repository.Select.CountAsync() : _repository.Select.Where(exp).CountAsync()); } diff --git a/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs b/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs index 281ddbbe..9a6c4e79 100644 --- a/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs +++ b/src/AgileConfig.Server.Data.Repository.Freesql/ServiceCollectionExt.cs @@ -22,7 +22,7 @@ public static void AddFreeSqlRepository(this IServiceCollection sc) sc.AddScoped(); sc.AddScoped(); sc.AddScoped(); - sc.AddScoped(); + sc.AddScoped(); sc.AddSingleton(); } diff --git a/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs b/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs index 3f8996f0..f5b2f8e4 100644 --- a/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs +++ b/src/AgileConfig.Server.Data.Repository.Freesql/SysInitRepository.cs @@ -16,6 +16,6 @@ public class SysInitRepository : ISysInitRepository public void SaveInitSetting(Setting setting) { - FreeSQL.Instance.Insert(setting); + FreeSQL.Instance.Insert(setting).ExecuteAffrows(); } } \ No newline at end of file diff --git a/src/AgileConfig.Server.Data.Repository.Selector/AgileConfig.Server.Data.Repository.Selector.csproj b/src/AgileConfig.Server.Data.Repository.Selector/AgileConfig.Server.Data.Repository.Selector.csproj new file mode 100644 index 00000000..9aad88be --- /dev/null +++ b/src/AgileConfig.Server.Data.Repository.Selector/AgileConfig.Server.Data.Repository.Selector.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/src/AgileConfig.Server.Data.Repository.Selector/RepositoryExtension.cs b/src/AgileConfig.Server.Data.Repository.Selector/RepositoryExtension.cs new file mode 100644 index 00000000..5f88048a --- /dev/null +++ b/src/AgileConfig.Server.Data.Repository.Selector/RepositoryExtension.cs @@ -0,0 +1,151 @@ +using AgileConfig.Server.Common; +using AgileConfig.Server.Data.Abstraction; +using AgileConfig.Server.Data.Freesql; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System.Security.Cryptography; + +namespace AgileConfig.Server.Data.Repository.Selector +{ + public static class RepositoryExtension + { + public static IServiceCollection AddRepositories(this IServiceCollection sc) + { + sc.AddFreeRepository(); + + var config = Global.Config; + var defaultProvider = config["db:provider"]; + + if (string.IsNullOrEmpty(defaultProvider)) + { + throw new ArgumentNullException(nameof(defaultProvider)); + } + + if (defaultProvider.Equals("mongodb", StringComparison.OrdinalIgnoreCase)) + { + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddSingleton(); + } + else + { + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddSingleton(); + } + + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + sc.AddScoped(); + + sc.AddScoped>(sp => env => + { + string envProvider = GetEnvProvider(env, config, defaultProvider); + + if (envProvider.Equals("mongodb", StringComparison.OrdinalIgnoreCase)) + { + return sp.GetService(); + } + else + { + var envAccssor = new ManualEnvAccessor(env); + var factory = new EnvFreeSqlFactory(envAccssor); + return new Freesql.ConfigPublishedRepository(factory); + } + }); + + sc.AddScoped>(sp => env => + { + string envProvider = GetEnvProvider(env, config, defaultProvider); + + if (envProvider.Equals("mongodb", StringComparison.OrdinalIgnoreCase)) + { + return sp.GetService(); + } + else + { + var envAccssor = new ManualEnvAccessor(env); + var factory = new EnvFreeSqlFactory(envAccssor); + return new Freesql.ConfigRepository(factory); + } + }); + + sc.AddScoped>(sp => env => + { + string envProvider = GetEnvProvider(env, config, defaultProvider); + + if (envProvider.Equals("mongodb", StringComparison.OrdinalIgnoreCase)) + { + return sp.GetService(); + } + else + { + var envAccssor = new ManualEnvAccessor(env); + var factory = new EnvFreeSqlFactory(envAccssor); + return new Freesql.PublishDetailRepository(factory); + } + }); + + sc.AddScoped((Func>)(sp => env => + { + string envProvider = GetEnvProvider(env, config, defaultProvider); + + if (envProvider.Equals("mongodb", StringComparison.OrdinalIgnoreCase)) + { + return sp.GetService(); + } + else + { + var envAccssor = new ManualEnvAccessor(env); + var factory = new EnvFreeSqlFactory(envAccssor); + return new Freesql.PublishTimelineRepository(factory); + } + })); + + return sc; + } + + private static string GetEnvProvider(string env, IConfiguration config, string defaultProvider) + { + var envProviderKey = $"db:env:{env}:provider"; + var envProvider = config[envProviderKey]; + if (string.IsNullOrEmpty(envProvider)) + { + // use default provider + envProvider = defaultProvider; + } + + return envProvider; + } + + class ManualEnvAccessor : IEnvAccessor + { + string _env; + public ManualEnvAccessor(string env) + { + _env = env; + } + public string Env => _env; + } + } +} diff --git a/src/AgileConfig.Server.Service/ConfigService.cs b/src/AgileConfig.Server.Service/ConfigService.cs index 1f6db9ec..c93f70a9 100644 --- a/src/AgileConfig.Server.Service/ConfigService.cs +++ b/src/AgileConfig.Server.Service/ConfigService.cs @@ -466,7 +466,8 @@ public void Dispose() waitPublishConfigs = waitPublishConfigs.Where(x => ids.Contains(x.Id)).ToList(); } //这里默认admin console 实例只部署一个,如果部署多个同步操作,高并发的时候这个version会有问题 - var versionMax = (await _publishTimelineRepository.QueryAsync(x => x.AppId == appId)).Max(x => x.Version); + var publishList = await _publishTimelineRepository.QueryAsync(x => x.AppId == appId); + var versionMax = publishList.Any() ? publishList.Max(x => x.Version) : 0; var user = await _userService.GetUserAsync(operatorr); @@ -732,7 +733,7 @@ public async Task RollbackAsync(string publishTimelineId, string env) //删除发布时间轴version之后的版本 var deletePublishTimeLineItems = await _publishTimelineRepository.QueryAsync(x => x.AppId == appId && x.Env == env && x.Version > version); await _publishTimelineRepository.DeleteAsync(deletePublishTimeLineItems); - var deletePublishDetailItems = await _publishDetailRepository.QueryAsync(x => x.PublishTimelineId == publishTimelineId && x.Env == env); + var deletePublishDetailItems = await _publishDetailRepository.QueryAsync(x => x.AppId == appId && x.Env == env && x.Version > version); await _publishDetailRepository.DeleteAsync(deletePublishDetailItems); ClearAppPublishedConfigsMd5Cache(appId, env);