/// <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); } }
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); }
/// <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); }
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)); } } }
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)); } } }
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); }); }
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)); }
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(); }
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); } }
//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); }
/// <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); }