feat: support shared tenant database sharding
This commit is contained in:
@@ -23,7 +23,7 @@ const registryDbGroup = "imRegistry"
|
||||
|
||||
var registryDbGroupOnce sync.Once
|
||||
|
||||
// DB resolves a tenant registry record and returns the corresponding business DB.
|
||||
// DB resolves a tenant registry record and returns the shared IM business DB.
|
||||
func DB(ctx context.Context, tenantId int64) (db gdb.DB, tenant *entity.ImTenant, err error) {
|
||||
if tenantId <= 0 {
|
||||
return nil, nil, gerror.New("租户ID不能为空")
|
||||
@@ -36,27 +36,48 @@ func DB(ctx context.Context, tenantId int64) (db gdb.DB, tenant *entity.ImTenant
|
||||
return nil, nil, gerror.New("租户不存在")
|
||||
}
|
||||
|
||||
link, err := tenantLink(ctx, tenant)
|
||||
db, err = SharedDB(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return db, tenant, nil
|
||||
}
|
||||
|
||||
group := fmt.Sprintf("im_tenant_%d_%x", tenant.Id, hash(link))
|
||||
// SharedDB returns the common IM database configured by the default tenant.
|
||||
// Tenant isolation inside this database is implemented by tenant_id predicates
|
||||
// and the three tenant-partitioned high-volume table families.
|
||||
func SharedDB(ctx context.Context) (gdb.DB, error) {
|
||||
var sharedTenant *entity.ImTenant
|
||||
if err := RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).
|
||||
Where(dao.ImTenant.Columns().Code, "default").Scan(&sharedTenant); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取共享业务库配置失败")
|
||||
}
|
||||
if sharedTenant == nil || sharedTenant.Id <= 0 {
|
||||
return nil, gerror.New("默认商户不存在,无法确定共享业务库")
|
||||
}
|
||||
link, err := tenantLink(ctx, sharedTenant)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dbForLink(link, sharedTenant.Id)
|
||||
}
|
||||
|
||||
func dbForLink(link string, ownerID int64) (gdb.DB, error) {
|
||||
group := fmt.Sprintf("im_shared_%d_%x", ownerID, hash(link))
|
||||
if cached, ok := tenantDbGroups.Load(group); ok && cached == link {
|
||||
db, err = gdb.Instance(group)
|
||||
return db, tenant, err
|
||||
return gdb.Instance(group)
|
||||
}
|
||||
|
||||
if err = gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
|
||||
return nil, nil, gerror.Wrap(err, "初始化租户业务库连接失败")
|
||||
if err := gdb.SetConfigGroup(group, gdb.ConfigGroup{{Link: link}}); err != nil {
|
||||
return nil, gerror.Wrap(err, "初始化共享业务库连接失败")
|
||||
}
|
||||
tenantDbGroups.Store(group, link)
|
||||
|
||||
db, err = gdb.Instance(group)
|
||||
db, err := gdb.Instance(group)
|
||||
if err != nil {
|
||||
return nil, nil, gerror.Wrap(err, "获取租户业务库连接失败")
|
||||
return nil, gerror.Wrap(err, "获取共享业务库连接失败")
|
||||
}
|
||||
return db, tenant, nil
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// RegistryDB returns the dedicated tenant registry connection, or the default
|
||||
|
||||
Reference in New Issue
Block a user