我知道这个问题已经问过很多次了,但我没有找到一个很好的答案。我使用SQLC来生成查询数据库的方法。当使用启动时初始化的一个连接时,一切都很正常。现在,我需要在多租户环境中设置它,在这个环境中,每个租户将有一个单独的DB。现在,我想从一个连接映射( connection,mapstring*sql.DB)开始,它用数据库连接连接租户。我的问题是在运行时重写/选择连接。通过一个连接,存储库将初始化如下:
type Repository interface {
GetCustomerById(ctx context.Context, id int64) (Customer, error)
ListCustomers(ctx context.Context) ([]Customer, error)
}
type repoSvc struct {
*Queries
db *sql.DB
}
func NewRepository(dbconn *sql.DB) Repository {
return &repoSvc{
Queries: New(dbconn),
db: dbconn,
}
}
customerRepo := customerRepo.NewRepository(conn)GetCustomerById是SQLC生成的方法,conn是数据库连接。
如何根据参数(从cookie或上下文)建立连接?
发布于 2021-08-06 00:38:31
假设您使用的是单独的数据库,最简单的方法是维护map[tenantID]Repository,其中tenantID是区分租户的方法(例如包含租户ID的string或uint )。
这样,您就可以在运行时完成所有操作:
当需要添加租户时,只需实例化租户的connection
Repository并关闭DB
Repository,并使用它来执行对租户的查询。
如果上述操作可能同时发生,请确保在访问映射(例如,sync.Map或sync.RWMutex)时使用某种同步机制来避免数据竞争。
如果您有一个存储租户及其DB连接URI的数据库表,则仍然可以使用这种方法:当您需要执行查询检查时,如果Repository存在于map中:如果缺少,请查询租户表并将该租户的Repository添加到映射中。然后,您可以定期扫描map并删除任何已经有一段时间没有使用的Repository。
为了使这一切更容易,您还可以将整个机器封装到一个MultitenantRepository接口中,这个接口与Repository接口相同,但在每个方法上接受一个额外的tenantID参数:
type MultitenantRepository interface {
GetCustomerById(ctx context.Context, tenant tenantID, id int64) (Customer, error)
ListCustomers(ctx context.Context, tenant tenantID) ([]Customer, error)
}这将避免将多租户设置的所有复杂性暴露在业务逻辑中。
https://stackoverflow.com/questions/68656132
复制相似问题