Пример #1
0
        /// <summary>
        /// 获得FreeSql实例
        /// </summary>
        /// <param name="ib"></param>
        /// <param name="serviceProvider"></param>
        /// <returns></returns>
        public static IFreeSql GetFreeSql(this IdleBus <IFreeSql> ib, IServiceProvider serviceProvider)
        {
            var user      = serviceProvider.GetRequiredService <IUser>();
            var appConfig = serviceProvider.GetRequiredService <AppConfig>();

            if (appConfig.Tenant && user.DataIsolationType == DataIsolationType.OwnDb && user.TenantId.HasValue)
            {
                var tenantName = "tenant_" + user.TenantId.ToString();
                var exists     = ib.Exists(tenantName);
                if (!exists)
                {
                    var dbConfig = serviceProvider.GetRequiredService <DbConfig>();
                    //查询租户数据库信息
                    var freeSql          = serviceProvider.GetRequiredService <IFreeSql>();
                    var tenantRepository = freeSql.GetRepository <TenantEntity>();
                    var tenant           = tenantRepository.Select.DisableGlobalFilter("Tenant").WhereDynamic(user.TenantId).ToOne <CreateFreeSqlTenantDto>();

                    var timeSpan = tenant.IdleTime.HasValue && tenant.IdleTime.Value > 0 ? TimeSpan.FromMinutes(tenant.IdleTime.Value) : TimeSpan.MaxValue;
                    ib.TryRegister(tenantName, () => CreateFreeSql(user, appConfig, dbConfig, tenant), timeSpan);
                }

                return(ib.Get(tenantName));
            }
            else
            {
                var freeSql = serviceProvider.GetRequiredService <IFreeSql>();
                return(freeSql);
            }
        }
Пример #2
0
        public FreeSqlCloud <TDBKey> Register(TDBKey dbkey, Func <IFreeSql> create)
        {
            if (_ib.TryRegister(dbkey, create))
            {
                if (_ib.GetKeys().Length == 1)
                {
                    _dbkeyMaster = dbkey;
                    if (_distributeTraceEnable)
                    {
                        _distributedTraceCall($"{dbkey} 注册成功, 并存储 TCC/SAGA 事务相关数据");
                    }
                    _scheduler = new IdleScheduler.Scheduler(new IdleScheduler.TaskHandlers.TestHandler());

                    _ormMaster.CodeFirst.ConfigEntity <TccMasterInfo>(a => a.Name($"tcc_{DistributeKey}"));
                    _ormMaster.CodeFirst.SyncStructure <TccMasterInfo>();
                    _ormMaster.CodeFirst.ConfigEntity <TccUnitInfo>(a => a.Name($"tcc_{DistributeKey}_unit"));
                    _ormMaster.CodeFirst.SyncStructure <TccUnitInfo>();

                    _ormMaster.CodeFirst.ConfigEntity <SagaMasterInfo>(a => a.Name($"saga_{DistributeKey}"));
                    _ormMaster.CodeFirst.SyncStructure <SagaMasterInfo>();
                    _ormMaster.CodeFirst.ConfigEntity <SagaUnitInfo>(a => a.Name($"saga_{DistributeKey}_unit"));
                    _ormMaster.CodeFirst.SyncStructure <SagaUnitInfo>();

                    #region 加载历史未未成 TCC 事务
                    var tccPendings = _ormMaster.Select <TccMasterInfo>()
                                      .Where(a => a.Status == TccMasterStatus.Pending && a.RetryCount < a.MaxRetryCount)
                                      .OrderBy(a => a.CreateTime)
                                      .ToList();
                    foreach (var pending in tccPendings)
                    {
                        _scheduler.AddTempTask(TimeSpan.FromSeconds(pending.RetryInterval), TccMaster <TDBKey> .GetTempTask(this, pending.Tid, pending.Title, pending.RetryInterval));
                    }
                    if (_distributeTraceEnable)
                    {
                        _distributedTraceCall($"成功加载历史未完成 TCC 事务 {tccPendings.Count} 个");
                    }
                    #endregion

                    #region 加载历史未未成 SAGA 事务
                    var sagaPendings = _ormMaster.Select <SagaMasterInfo>()
                                       .Where(a => a.Status == SagaMasterStatus.Pending && a.RetryCount < a.MaxRetryCount)
                                       .OrderBy(a => a.CreateTime)
                                       .ToList();
                    foreach (var pending in sagaPendings)
                    {
                        _scheduler.AddTempTask(TimeSpan.FromSeconds(pending.RetryInterval), SagaMaster <TDBKey> .GetTempTask(this, pending.Tid, pending.Title, pending.RetryInterval));
                    }
                    if (_distributeTraceEnable)
                    {
                        _distributedTraceCall($"成功加载历史未完成 SAGA 事务 {sagaPendings.Count} 个");
                    }
                    #endregion
                }
            }
            return(this);
        }
Пример #3
0
        /// <summary>
        /// 临时任务(程序重启会丢失)
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="handle"></param>
        /// <returns></returns>
        public string AddTempTask(TimeSpan timeout, Action handle)
        {
            var id  = Guid.NewGuid().ToString();
            var bus = new IdleTimeout(() =>
            {
                _ib.TryRemove(id);
                Interlocked.Decrement(ref _quantityTempTask);
                if (handle != null)
                {
                    _wq.Enqueue(handle);
                }
            });

            if (_ib.TryRegister(id, () => bus, timeout))
            {
                _ib.Get(id);
                Interlocked.Increment(ref _quantityTempTask);
            }
            return(id);
        }
Пример #4
0
            public PoolingAdapter(RedisClient topOwner, ConnectionStringBuilder connectionString, params ConnectionStringBuilder[] slaveConnectionStrings)
            {
                UseType       = UseType.Pooling;
                TopOwner      = topOwner;
                _masterHost   = connectionString.Host;
                _rw_splitting = slaveConnectionStrings?.Any() == true;
                _is_single    = !_rw_splitting && connectionString.MaxPoolSize == 1;

                _ib = new IdleBus <RedisClientPool>(TimeSpan.FromMinutes(10));
                _ib.Register(_masterHost, () => new RedisClientPool(connectionString, null, TopOwner));

                if (_rw_splitting)
                {
                    foreach (var slave in slaveConnectionStrings)
                    {
                        _ib.TryRegister($"slave_{slave.Host}", () => new RedisClientPool(slave, null, TopOwner));
                    }
                }
            }
Пример #5
0
            public PoolingAdapter(RedisClient cli, ConnectionStringBuilder connectionString, params ConnectionStringBuilder[] slaveConnectionStrings)
            {
                UseType      = UseType.Pooling;
                _cli         = cli;
                _masterHost  = connectionString.Host;
                _rw_plitting = slaveConnectionStrings?.Any() == true;

                _ib         = new IdleBus <RedisClientPool>();
                _ib.Notice += new EventHandler <IdleBus <string, RedisClientPool> .NoticeEventArgs>((_, e) => { });
                _ib.Register(_masterHost, () => new RedisClientPool(connectionString, null, _cli.Serialize, _cli.Deserialize));

                if (_rw_plitting)
                {
                    foreach (var slave in slaveConnectionStrings)
                    {
                        _ib.TryRegister($"slave_{slave.Host}", () => new RedisClientPool(slave, null, _cli.Serialize, _cli.Deserialize));
                    }
                }
            }
Пример #6
0
        public static void AddFreeSql(this IServiceCollection services, Action <FreeSqlOptions> action = null)
        {
            FreeSqlOptions freeSqlOptions = new FreeSqlOptions();

            action?.Invoke(freeSqlOptions);
            services.AddSingleton(freeSqlOptions);
            IdleBus <IFreeSql> ib = new IdleBus <IFreeSql>(freeSqlOptions.TimeSpan);

            //Dictionary<string, IFreeSql> dic = new Dictionary<string, IFreeSql>();
            foreach (var item in freeSqlOptions.FreeSqlDbs)
            {
                var isRegisterSucess = ib.TryRegister(item.Name, () =>
                {
                    var freesql = new FreeSqlBuilder()
                                  .UseConnectionString(item.DataType, item.ConnectString)
                                  .UseAutoSyncStructure(item.IsAutoSyncStructure) //自动同步实体结构到数据库
                                  .UseNoneCommandParameter(item.IsNoneCommandParameter)
                                  .UseLazyLoading(item.IsLazyLoading)
                                  .UseNameConvert(item.NameConvertType)
                                  .UseMonitorCommand(item.Executing, item.Executed).Build();
                    freesql.UseJsonMap();
                    return(freesql);
                });
                if (!isRegisterSucess)
                {
                    throw new Exception($"{item.Name}数据库注入失败");
                }
            }

            services.AddSingleton <IFreeSqlTransPortService, FreeSqlTransPortService>();
            services.AddSingleton(ib);
            TransPortServiceDependencyInjection.AddFunc((serviceProvider, name) =>
            {
                if (name.Equals(FreeSqlConstant.FREESQLNAME, StringComparison.OrdinalIgnoreCase))
                {
                    return(serviceProvider.GetService <IFreeSqlTransPortService>());
                }
                return(null);
            });
        }
Пример #7
0
        public IFreeSql Db(string dbKey = "default")
        {
            if (Tenant == null)
            {
                return(null);
            }

            var currentDbOption = Tenant.DbOptions.Where(e => e.Key.ToLower() == dbKey.ToLower()).FirstOrDefault();

            if (currentDbOption == null)
            {
                throw new Exception("没有找到对应数据库信息,请检查key是否配置正确");
            }

            var dbType     = (FreeSql.DataType)Enum.Parse(typeof(FreeSql.DataType), currentDbOption.DbType);
            var fristName  = $"{Tenant.Id}#{dbKey}#";
            var dbCacheKey = fristName + currentDbOption.SerializeToString().Md5();

            // TryRegister 内部做了如果存在KEY,就什么不做,不存在就创建
            _ib.TryRegister(dbCacheKey, () => CreateDb(dbType, currentDbOption));
            return(_ib.Get(dbCacheKey));
        }
Пример #8
0
        static void Main(string[] args)
        {
            //超过20秒没有使用,就销毁【实例】
            var ib = new IdleBus(TimeSpan.FromSeconds(20));

            ib.Notice += (_, e) =>
            {
                Console.WriteLine("    " + e.Log);

                if (e.NoticeType == IdleBus <IDisposable> .NoticeType.AutoRelease)
                {
                    Console.WriteLine($"    [{DateTime.Now.ToString("g")}] {e.Key} 空闲被回收");
                }
            };

            while (true)
            {
                Console.WriteLine("输入 > ");
                var line = Console.ReadLine().Trim();
                if (string.IsNullOrEmpty(line))
                {
                    break;
                }

                // 注册
                ib.TryRegister(line, () => new TestInfo());

                // 第一次:创建
                TestInfo item = ib.Get(line) as TestInfo;

                // 第二次:直接获取,长驻内存直到空闲销毁
                item = ib.Get(line) as TestInfo;
            }

            ib.Dispose();
        }
Пример #9
0
            internal void ResetSentinel()
            {
                if (ResetSentinelFlag != 0)
                {
                    return;
                }
                if (Interlocked.Increment(ref ResetSentinelFlag) != 1)
                {
                    Interlocked.Decrement(ref ResetSentinelFlag);
                    return;
                }
                string masterhostEnd = _masterHost;
                var    allkeys       = _ib.GetKeys().ToList();

                for (int i = 0; i < _sentinels.Count; i++)
                {
                    if (i > 0)
                    {
                        var first = _sentinels.First;
                        _sentinels.RemoveFirst();
                        _sentinels.AddLast(first.Value);
                    }

                    try
                    {
                        using (var sentinelcli = new RedisSentinelClient(_sentinels.First.Value))
                        {
                            var masterhost             = sentinelcli.GetMasterAddrByName(_connectionString.Host);
                            var masterConnectionString = localTestHost(masterhost, RoleType.Master);
                            if (masterConnectionString == null)
                            {
                                continue;
                            }
                            masterhostEnd = masterhost;

                            if (_rw_splitting)
                            {
                                foreach (var slave in sentinelcli.Salves(_connectionString.Host))
                                {
                                    ConnectionStringBuilder slaveConnectionString = localTestHost($"{slave.ip}:{slave.port}", RoleType.Slave);
                                    if (slaveConnectionString == null)
                                    {
                                        continue;
                                    }
                                }
                            }

                            foreach (var sentinel in sentinelcli.Sentinels(_connectionString.Host))
                            {
                                var remoteSentinelHost = $"{sentinel.ip}:{sentinel.port}";
                                if (_sentinels.Contains(remoteSentinelHost))
                                {
                                    continue;
                                }
                                _sentinels.AddLast(remoteSentinelHost);
                            }
                        }
                        break;
                    }
                    catch { }
                }

                foreach (var spkey in allkeys)
                {
                    _ib.TryRemove(spkey, true);
                }
                Interlocked.Exchange(ref _masterHost, masterhostEnd);
                Interlocked.Decrement(ref ResetSentinelFlag);

                ConnectionStringBuilder localTestHost(string host, RoleType role)
                {
                    ConnectionStringBuilder connectionString = _connectionString.ToString();

                    connectionString.Host        = host;
                    connectionString.MinPoolSize = 1;
                    connectionString.MaxPoolSize = 1;
                    using (var cli = new RedisClient(connectionString))
                    {
                        if (cli.Role().role != role)
                        {
                            return(null);
                        }

                        if (role == RoleType.Master)
                        {
                            //test set/get
                        }
                    }
                    connectionString.MinPoolSize = connectionString.MinPoolSize;
                    connectionString.MaxPoolSize = connectionString.MaxPoolSize;

                    _ib.TryRegister(host, () => new RedisClientPool(connectionString, null, TopOwner));
                    allkeys.Remove(host);

                    return(connectionString);
                }
            }
Пример #10
0
 //closure connectionString
 void RegisterClusterNode(ConnectionStringBuilder connectionString)
 {
     _ib.TryRegister(connectionString.Host, () => new RedisClientPool(connectionString, null, TopOwner));
 }
        /// <summary>
        /// 添加租户数据库
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        public static void AddTenantDb(this IServiceCollection services, IHostEnvironment env)
        {
            services.AddScoped <MyUnitOfWorkManager>();

            var dbConfig  = new ConfigHelper().Get <DbConfig>("dbconfig", env.EnvironmentName);
            var appConfig = new ConfigHelper().Get <AppConfig>("appconfig", env.EnvironmentName);
            var user      = services.BuildServiceProvider().GetService <IUser>();

            int idleTime = dbConfig.IdleTime > 0 ? dbConfig.IdleTime : 10;

            IdleBus <IFreeSql> ib = new IdleBus <IFreeSql>(TimeSpan.FromMinutes(idleTime));

            var tenantName = AdminConsts.TenantName;

            if (appConfig.TenantType == TenantType.Own)
            {
                tenantName = "tenant_" + user.TenantId.ToString();
            }
            ib.TryRegister(tenantName, () =>
            {
                #region FreeSql
                var freeSqlBuilder = new FreeSqlBuilder()
                                     .UseConnectionString(dbConfig.Type, dbConfig.ConnectionString)
                                     .UseLazyLoading(false)
                                     .UseNoneCommandParameter(true);

                #region 监听所有命令
                if (dbConfig.MonitorCommand)
                {
                    freeSqlBuilder.UseMonitorCommand(cmd => { }, (cmd, traceLog) =>
                    {
                        Console.WriteLine($"{cmd.CommandText}\r\n");
                    });
                }
                #endregion

                var fsql = freeSqlBuilder.Build();
                fsql.GlobalFilter.Apply <IEntitySoftDelete>("SoftDelete", a => a.IsDeleted == false);

                //配置实体
                DbHelper.ConfigEntity(fsql, appConfig);

                //共享数据库
                if (appConfig.TenantType == TenantType.Share)
                {
                    fsql.GlobalFilter.ApplyIf <ITenant>("Tenant", () => user.TenantId > 0, a => a.TenantId == user.TenantId);
                }

                #region 监听Curd操作
                if (dbConfig.Curd)
                {
                    fsql.Aop.CurdBefore += (s, e) =>
                    {
                        Console.WriteLine($"{e.Sql}\r\n");
                    };
                }
                #endregion

                #region 审计数据
                //计算服务器时间
                var serverTime       = fsql.Select <DualEntity>().Limit(1).First(a => DateTime.UtcNow);
                var timeOffset       = DateTime.UtcNow.Subtract(serverTime);
                fsql.Aop.AuditValue += (s, e) =>
                {
                    if (user == null || user.Id <= 0)
                    {
                        return;
                    }

                    if (e.AuditValueType == FreeSql.Aop.AuditValueType.Insert)
                    {
                        switch (e.Property.Name)
                        {
                        case "CreatedUserId":
                            e.Value = user.Id;
                            break;

                        case "CreatedUserName":
                            e.Value = user.Name;
                            break;

                        case "TenantId":
                            e.Value = user.TenantId;
                            break;
                        }
                        if (e.Property.GetCustomAttribute <ServerTimeAttribute>(false) != null && (e.Column.CsType == typeof(DateTime) || e.Column.CsType == typeof(DateTime?)) &&
                            (e.Value == null || (DateTime)e.Value == default || (DateTime?)e.Value == default))
                        {
                            e.Value = DateTime.Now.Subtract(timeOffset);
                        }
                    }
        /// <summary>
        /// 添加租户数据库
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        public static void AddTenantDb(this IServiceCollection services, IHostEnvironment env)
        {
            services.AddScoped <MyUnitOfWorkManager>();

            var dbConfig  = new ConfigHelper().Get <DbConfig>("dbconfig", env.EnvironmentName);
            var appConfig = new ConfigHelper().Get <AppConfig>("appconfig", env.EnvironmentName);
            var user      = services.BuildServiceProvider().GetService <IUser>();

            int idleTime = dbConfig.IdleTime > 0 ? dbConfig.IdleTime : 10;

            IdleBus <IFreeSql> ib = new IdleBus <IFreeSql>(TimeSpan.FromMinutes(idleTime));

            ib.TryRegister("tenant_" + user.TenantId.ToString(), () =>
            {
                #region FreeSql
                var freeSqlBuilder = new FreeSqlBuilder()
                                     .UseConnectionString(dbConfig.Type, dbConfig.ConnectionString)
                                     .UseLazyLoading(false)
                                     .UseNoneCommandParameter(true);

                #region 监听所有命令
                if (dbConfig.MonitorCommand)
                {
                    freeSqlBuilder.UseMonitorCommand(cmd => { }, (cmd, traceLog) =>
                    {
                        Console.WriteLine($"{cmd.CommandText}\r\n");
                    });
                }
                #endregion

                var fsql = freeSqlBuilder.Build();
                fsql.GlobalFilter.Apply <IEntitySoftDelete>("SoftDelete", a => a.IsDeleted == false);
                //共享数据库
                if (appConfig.TenantType == TenantType.Share)
                {
                    fsql.GlobalFilter.ApplyIf <ITenant>("Tenant", () => user.TenantId > 0, a => a.TenantId == user.TenantId);
                }

                #region 监听Curd操作
                if (dbConfig.Curd)
                {
                    fsql.Aop.CurdBefore += (s, e) =>
                    {
                        Console.WriteLine($"{e.Sql}\r\n");
                    };
                }
                #endregion

                #region 审计数据
                fsql.Aop.AuditValue += (s, e) =>
                {
                    if (user == null || user.Id <= 0)
                    {
                        return;
                    }

                    if (e.AuditValueType == FreeSql.Aop.AuditValueType.Insert)
                    {
                        switch (e.Property.Name)
                        {
                        case "CreatedUserId":
                            e.Value = user.Id;
                            break;

                        case "CreatedUserName":
                            e.Value = user.Name;
                            break;

                        case "TenantId":
                            e.Value = user.TenantId;
                            break;
                        }
                    }
                    else if (e.AuditValueType == FreeSql.Aop.AuditValueType.Update)
                    {
                        switch (e.Property.Name)
                        {
                        case "ModifiedUserId":
                            e.Value = user.Id;
                            break;

                        case "ModifiedUserName":
                            e.Value = user.Name;
                            break;
                        }
                    }
                };
                #endregion
                #endregion

                return(fsql);
            });

            services.AddSingleton(ib);
        }
Пример #13
0
        /// <summary>
        /// 添加租户数据库
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        public static void AddTenantDb(this IServiceCollection services, IHostEnvironment env)
        {
            services.AddScoped <MyUnitOfWorkManager>();

            var dbConfig  = new ConfigHelper().Get <DbConfig>("dbconfig", env.EnvironmentName);
            var appConfig = new ConfigHelper().Get <AppConfig>("appconfig", env.EnvironmentName);
            var user      = services.BuildServiceProvider().GetService <IUser>();

            int idleTime = dbConfig.IdleTime > 0 ? dbConfig.IdleTime : 10;

            IdleBus <IFreeSql> ib = new IdleBus <IFreeSql>(TimeSpan.FromMinutes(idleTime));

            var tenantName = AdminConsts.TenantName;

            if (appConfig.TenantType == TenantType.Own)
            {
                tenantName = "tenant_" + user.TenantId?.ToString();
            }
            ib.TryRegister(tenantName, () =>
            {
                #region FreeSql
                var freeSqlBuilder = new FreeSqlBuilder()
                                     .UseConnectionString(dbConfig.Type, dbConfig.ConnectionString)
                                     .UseAutoSyncStructure(false)
                                     .UseLazyLoading(false)
                                     .UseNoneCommandParameter(true);

                #region 监听所有命令
                if (dbConfig.MonitorCommand)
                {
                    freeSqlBuilder.UseMonitorCommand(cmd => { }, (cmd, traceLog) =>
                    {
                        Console.WriteLine($"{cmd.CommandText}\r\n");
                    });
                }
                #endregion

                var fsql = freeSqlBuilder.Build();
                fsql.GlobalFilter.Apply <IEntitySoftDelete>("SoftDelete", a => a.IsDeleted == false);

                //配置实体
                DbHelper.ConfigEntity(fsql, appConfig);

                //共享数据库
                if (appConfig.TenantType == TenantType.Share)
                {
                    fsql.GlobalFilter.ApplyIf <ITenant>("Tenant", () => user.TenantId > 0, a => a.TenantId == user.TenantId);
                }

                #region 监听Curd操作
                if (dbConfig.Curd)
                {
                    fsql.Aop.CurdBefore += (s, e) =>
                    {
                        Console.WriteLine($"{e.Sql}\r\n");
                    };
                }
                #endregion

                #region 审计数据
                //计算服务器时间
                var serverTime       = fsql.Select <DualEntity>().Limit(1).First(a => DateTime.UtcNow);
                var timeOffset       = DateTime.UtcNow.Subtract(serverTime);
                fsql.Aop.AuditValue += (s, e) =>
                {
                    DbHelper.AuditValue(e, timeOffset, user);
                };
                #endregion
                #endregion

                return(fsql);
            });

            services.AddSingleton(ib);
        }