我有以下模型
type UsersModel struct {
db *pgx.Conn
}
func (u *UsersModel) SignupUser(ctx context.Context, payload SignupRequest) (SignupQueryResult, error) {
err := u.db.Exec("...")
return SignupQueryResult{}, err
}type SessionsModel struct {
db *pgx.Conn
}
func (s *SessionsModel) CreateSession(ctx context.Context, payload CreateSessionRequest) error {
_, err := s.db.Exec("...")
return err
}我的服务调用UsersModel.SignupUser如下所示
type SignupService struct {
userModel signupServiceUserModel
}
func (ss *SignupService) Signup(ctx context.Context, request SignupRequest) (SignupQueryResult, error) {
return ss.userModel.SignupUser(ctx, request)
}现在,我需要将SignupUser和CreateSession绑定到一个事务中,而不是孤立的操作中,不确定构建这是什么最佳方式,以及如何在维护服务中特定于DB的抽象的同时传递事务。或者我应该直接调用sessions表insert查询(这是我在*SessionsModel.CreateSession中直接放在*UsersModel.SignupUser中的)
作为参考,pgx中的事务是通过调用*pgx.Conn.Begin()来实现的,后者返回一个具体的pgx.Tx,在该pgx.Tx上执行与在*px.Conn上相同的函数,然后是*pgx.Tx.Commit()或*pgx.Tx.Rollback()
我有以下问题:
发布于 2021-11-04 07:54:18
这没有正确或错误的答案,因为有多种方法可以做到这一点。然而,我分享了我如何做这件事以及为什么。
确保服务层没有任何具体的DB实现,因此如果切换到一个全新的DB,则不需要更改其他部分。
关于解决方案,我将创建一个名为SignupUserAndCreateSession的全新方法,它包含您所需的所有逻辑。我不担心,因为您将两个原始方法放在一起,根据我在这个场景中的理解,这两个方法都被设计紧密地耦合在一起,所以这将不是反模式。
我将避免在方法之间移动*pgx.Tx,因为无论如何,您将依赖于确保提交或回滚的另一个级别,这可能会在将来的实现中导致错误。
https://stackoverflow.com/questions/69834111
复制相似问题