dotnetcore / AgileConfig

基于.NET Core开发的轻量级分布式配置中心 / .NET Core lightweight configuration server
MIT License
1.46k stars 296 forks source link

Mongodb 支持 #152

Closed pengqian089 closed 5 months ago

pengqian089 commented 6 months ago

暂时还没测试,前端编译了一下午,还在编译

有什么办法嘛?

pengqian089 commented 6 months ago

单元测试有些通过不了,比如这个

    [Test]
    public async Task SearchTest()
    {
        await ConfigRepository.DeleteAsync(x => true);

        var id = Guid.NewGuid().ToString();
        var source = new Config
        {
            AppId = "001",
            Id = id,
            Group = "group",
            Key = "key",
            Value = "v",
            Description = "d",
            CreateTime = DateTime.Now,
            UpdateTime = DateTime.Now,
            Status = ConfigStatus.Enabled,
            OnlineStatus = OnlineStatus.Online
        };
        var id1 = Guid.NewGuid().ToString();
        var source1 = new Config
        {
            AppId = "001",
            Id = id1,
            Group = "g",
            Key = "k",
            Value = "v",
            Description = "d",
            CreateTime = DateTime.Now,
            UpdateTime = DateTime.Now,
            Status = ConfigStatus.Deleted,
            OnlineStatus = OnlineStatus.Online
        };
        var id2 = Guid.NewGuid().ToString();
        var source2 = new Config
        {
            AppId = "002",
            Id = id2,
            Group = "g",
            Key = "k",
            Value = "v",
            Description = "d",
            CreateTime = DateTime.Now,
            UpdateTime = DateTime.Now,
            Status = ConfigStatus.Deleted,
            OnlineStatus = OnlineStatus.Online
        };
        var result = await service.AddAsync(source, "");
        Assert.IsTrue(result);
        var result1 = await service.AddAsync(source1, "");
        Assert.IsTrue(result1);
        var result2 = await service.AddAsync(source2, "");
        Assert.IsTrue(result2);

        var configs = await service.Search("001", "", "", "");
        Assert.IsNotNull(configs);
        Assert.AreEqual(1, configs.Count);
        var configs1 = await service.Search("", "o", "", "");
        Assert.IsNotNull(configs1);
        Assert.AreEqual(1, configs1.Count);
        var configs2 = await service.Search("", "", "e", "");
        Assert.IsNotNull(configs2);
        Assert.AreEqual(1, configs2.Count);
    }

Search 实现:

    public Task<List<Config>> Search(string appId, string group, string key, string env)
    {
        var q = GetRepository<Config>(env).SearchFor(c => c.Status == ConfigStatus.Enabled && c.Env == env);
        if (!string.IsNullOrEmpty(appId))
        {
            q = q.Where(c => c.AppId == appId);
        }

        if (!string.IsNullOrEmpty(group))
        {
            q = q.Where(c => c.Group.Contains(group));
        }

        if (!string.IsNullOrEmpty(key))
        {
            q = q.Where(c => c.Key.Contains(key));
        }

        return q.ToListAsync();
    }

这是因为 Config 实体没有给 Env 属性赋值,Env 为 null,所以在查询的时候 c.Env == env 条件不成立, 想问一下,这样写单元测试的目的是什么?

pengqian089 commented 6 months ago

另外SysLog 的 Id 为 int 类型,生成Id 有更好的方式吗?

https://github.com/pengqian089/AgileConfig/blob/3c4b6fd65048b7997e7efe7340fb2b3a2f3b2296/src/AgileConfig.Server.Mongodb.Service/SysLogService.cs#L36

kklldog commented 6 months ago

太感谢了,我一直想做这个功能。 不用管单元测试,后面很多单元测试我都没修复。 我最近没空,有空了我会好好看看。

kklldog commented 6 months ago

@pengqian089 Hi , 我今天看了下你的 PR。非常棒。 但是我觉得咱们可能不应该从 IService 层开始隔离 Freesql 跟 Mongodb 。 我抽象了一层 IRepository 作为通用的数据访问接口。 我们的依赖关系是这样:controller > service > repository > (freeSql or mongodb repository) 我会实现 freesql repositories, 你来实现 mongodb repository。 这样的结构的话,后面方便实现其他的驱动,比如 redis。 现在我还没完全重构好,你可以先看看结构。等我实现好了,你再来实现 mongodb 的。 谢谢。

pengqian089 commented 6 months ago

@kklldog 可以的,我当时就想过了,抽象出Repository,那样只需要维护一个 Service层就好了。 当时写的比较匆忙,所以没有去做

kklldog commented 6 months ago

@pengqian089 Hi, 我刚重构了 ConfigService; 并且我把获取 Env 参数放到了 EnvAccessor 里面,然后注入到 EnvFreeSqlFactory里。这样在 Service 里的方法就不用显式写在方法上了。后面这些方法上的 string env 都会拿走。这个你可以注意以下。 重构的东西还很多,估计还需要几个周时间。

pengqian089 commented 6 months ago

@pengqian089 Hi, 我刚重构了 ConfigService; 并且我把获取 Env 参数放到了 EnvAccessor 里面,然后注入到 EnvFreeSqlFactory里。这样在 Service 里的方法就不用显式写在方法上了。后面这些方法上的 string env 都会拿走。这个你可以注意以下。 重构的东西还很多,估计还需要几个周时间。

@kklldog 好的,如果有需要帮忙的也可以跟我说

pengqian089 commented 6 months ago

@kklldog 你好,我修改了一部分 注入方式IEventRegister ConfigStatusUpdateRegister ISettingService 的实现重构了一部分,还没有合并到当前PR。

你看看这样的思路可行吗? 如果可行,剩余的部分我也按照这样的方式重构

kklldog commented 6 months ago

wow,感谢。 可以啊,原来还可以这样注入瞬态的服务,学到了。 就是有些原来的同步方法,你不用迁就,直接改成异步方法,对应调用的地方也直接改成异步。不用使用 .Result 这种办法来兼容。反正这次重构改动这么多地方,也不差这些了。 我们可以先把代码重构完,然后试跑,把基本功能都做出来。然后补或者干脆全部重写单元测试,拉一下覆盖率。 后面要添加新的驱动就简单了。

kklldog commented 6 months ago

新增对 IFreeSqlFactory 实现 DeaultFreesqlFactory,使用默认连接串。因为并不是所有的 repository 都需要根据 env 来切换连接串的。 并且使用 .NET8 中最新的 [FromKeyedServices] 特性来注入正确的实现。

kklldog commented 6 months ago

我实现了一个 Unitofwork 模式来包装事务,不知道目前这个抽象能不能适配到 mongodb 上。 mongodb 有事务吗? @pengqian089

pengqian089 commented 6 months ago

我实现了一个 Unitofwork 模式来包装事务,不知道目前这个抽象能不能适配到 mongodb 上。 mongodb 有事务吗? @pengqian089

@kklldog mongodb支持有限的事务,只有在集群部署下才可以使用。 可以适配,但是用单服务器部署会报错

pengqian089 commented 6 months ago

我实现了一个 Unitofwork 模式来包装事务,不知道目前这个抽象能不能适配到 mongodb 上。 mongodb 有事务吗? @pengqian089

@kklldog mongodb支持有限的事务,只有在集群部署下才可以使用。 可以适配,但是用单服务器部署会报错

这里有说明

  • In version 4.0, MongoDB supports multi-document transactions on replica sets.
  • In version 4.2, MongoDB introduces distributed transactions, which adds support for multi-document transactions on sharded clusters and incorporates the existing support for multi-document transactions on replica sets.
  • To use transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2.

mongodb 4.0 以上版本 & 副本集(4.0+)| 分片集(4.2+)

如果是单服务器部署,可以将独立部署转换为单节点副本集启用事务 https://www.mongodb.com/docs/manual/tutorial/convert-standalone-to-replica-set/

好的,我直接实现了一个空的 Uow,你可以去完善它,要么干脆就这样。

kklldog commented 6 months ago

目前为止,Freesql 这边基本功能应该差不多了。 Mongodb 我也简单测试了一下,大部分功能应该没啥问题。不过在发布配置的时候会报错。 也就是对应的 ConfigService.Publish 方法,具体大概是 628 行在报错,貌似 configPublishedRepository.UpdateAsync(publishedConfigs) publishedConfigs这个list是个空的(count=0)的时候会报错。 有空可以帮忙查一下,谢谢。 @pengqian089

kklldog commented 6 months ago

另外还有一个小问题,syslog表原来为了排序性能主键直接选择了自增。但是看了 mongodb 搞自增应该挺麻烦(估计其他非关系数据库都会麻烦),so 我干脆改成 string 了。但是改成 string 后就不能按 Id desc了。所以我在 SysLogService 里把 Search 方法里的排序指定了 LogTime,但是切到 mongodb 下貌似也在报错,有空的话帮忙看看,谢谢; · var list = await _sysLogRepository.QueryPageAsync(exp, pageIndex, pageSize, defaultSortField: "LogTime", defaultSortType: "DESC");·

@pengqian089

pengqian089 commented 6 months ago

syslog表原来为了排序性能主键直接选择了自增。但是看了 mongodb 搞自增应该挺麻烦(估计其他非关系数据库都会麻烦),so 我干脆改成 string 了。但是改成 string 后就不能按 Id desc了。

这个可以解决 ,如果要改回自增 id ,我也会去适配

kklldog commented 6 months ago

syslog表原来为了排序性能主键直接选择了自增。但是看了 mongodb 搞自增应该挺麻烦(估计其他非关系数据库都会麻烦),so 我干脆改成 string 了。但是改成 string 后就不能按 Id desc了。

这个可以解决 ,如果要改回自增 id ,我也会去适配

不用,咱就用string得了,省得对接其他存储的时候麻烦。

kklldog commented 5 months ago

Thanks very much! @pengqian089