【问题标题】:How to structure my Go app for transactions via pgx如何通过 pgx 构建我的 Go 应用程序以进行交易
【发布时间】:2021-11-04 03:04:38
【问题描述】:

我有以下型号

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)
}

现在,我需要将 SignupUserCreateSession 绑定在一个事务中,而不是孤立的操作,不确定构建它的最佳方法是什么,以及如何在保持对 DB 特定内容的抽象的同时传递事务服务。或者我应该只调用会话表插入查询(我直接在*SessionsModel.CreateSession 中放入*UsersModel.SignupUser

作为参考,pgx 中的事务通过调用 *pgx.Conn.Begin() 发生,它返回一个具体的 pgx.Tx ,您可以在其上执行与 *px.Conn 相同的功能,然后是 *pgx.Tx.Commit()*pgx.Tx.Rollback()

我的问题是:

  • 从哪里开始事务 - 模型还是服务?
  • 如果在服务中,我如何在从服务中抽象出底层数据库的同时做到这一点?
  • 如何在模型之间传递事务?

【问题讨论】:

    标签: go design-patterns pgx


    【解决方案1】:

    对此没有正确或错误的答案,因为有多种方法可以做到这一点。不过,我会分享我的做法以及原因。

    确保服务层没有任何具体的数据库实现,因此如果您切换到全新的数据库,则无需更改其他部分。

    关于解决方案,我将创建一个名为SignupUserAndCreateSession 的全新方法,其中包含您需要的所有逻辑。我不会担心,因为您将两种原始方法合二为一,根据我在这种情况下的理解,它们在设计上都是紧密耦合的,因此这不是反模式。

    我会避免在方法之间移动*pgx.Tx,因为无论如何您将依赖另一个确保提交或回滚的级别,这可能会导致未来实现中的错误。

    【讨论】:

      猜你喜欢
      • 2021-11-23
      • 1970-01-01
      • 2021-06-24
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      相关资源
      最近更新 更多