1

I am writing a service that can make a transactional query, (in this question I will be using GORM)

UserService

type userService struct {
    UserRepository  repository.IUserRepository
    TokenRepository repository.ITokenRepository
}

type IUserService interface {
WithTrx() IUserService
CommitTrx() error
RollbackTrx()

Create(ctx context.Context, name string) (*model.User, error)
...
...
}

here is some implementation of the service

user.go

func (s *userService) WithTrx() IUserService {
    newService := &userService{
        UserRepository:       s.UserRepository.WithTrx(),
        TokenRepository:      s.TokenRepository,
    
    }
    return newService
}
func (s *userService) Create(ctx context.Context, name string) (*model.User, error) {
... 
// s.UserRepository.Create() 
// then return the user, error 
...
}


and for the UserRepository.WithTrx() is basically just returning the interface itself

type psqlUserRepository struct {
    DB *gorm.DB
}

type IUserRepository interface {
    WithTrx() IUserRepository
    CommitTrx() error
    RollbackTrx()

    Create(ctx context.Context, u model.User) (*model.User, error)
...
}

func (r *psqlUserRepository) WithTrx() IUserRepository {
    return &psqlUserRepository{DB: r.DB.Begin()}
}

So when I need user service to create a user using transactional query, I just:


trx:= userserviceInstance.WithTrx()
user, err := trx.Create(ctx, name)
// err handling and rollback
commitErr := trx.CommitTrx()

Is there any similar approach like this? What is it called? I am not sure whether this is the right pattern to create a transactional query.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

1 Answers1

3

I guess there are a few moments here.

The Repository pattern is normally used to hide the implementation details of a storage.

A Transaction is a technical detail which should not be exposed to the higher layers.

In other words the Repository interface (architectural element) you have shouldn't expose the transaction (technical details).

Is there any similar approach like this? What is it called? I am not sure whether this is the right pattern to create a transactional query You may want to learn more about Unit of Work pattern which can be useful for your purpose.

You may take a look at Unit of Work Pattern.

Bellow are some examples which you may find useful: