Giter Club home page Giter Club logo

go-transaction-manager's People

Contributors

dependabot[bot] avatar hound672 avatar maranqz avatar scukerman avatar zeryoshka avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-transaction-manager's Issues

transaction options

The isolation level is mainly in the RDBMS.

NoSQL DBs have variations which are not the same as in RDBMS.

Separate drivers

Hello.
For now this github repository contains main functionality and drivers/plugins for different databases.
Do you think about separated repositories?
One with main functionality, and another for drivers/plugins (each for plugin: 1 for pgx, 1 for redis etc).

Add pgx support

Currently library supports postgres through sqlx, but not pgx.

Support for dgraph-io/badger

Hello, I've wanted to add support for https://github.com/dgraph-io/badger, but most recent badger/v4 uses go 1.19, and trm is 1.13 due to backward compatibility. So I have a few questions

  1. will go-transaction-manager bump its go version someday?
  2. How can I contribute with badger support without bumping go version? I am aming for supporting badger/v4, maybe with separate it with build-tags?
  3. Could I fork go-transaction-manager for my personal usage and bump go there?

Redis

Add processing of https://github.com/go-redis/redis

There is a problem, go-redis open and close transaction inside closure.
To solve it, we can start goroutine for closure to getting transaction and stop it after Commit or Rollback of Transaction.

Transaction controlling

Processing cases when:

  1. Nested code committed/rolled back the transaction.
  2. Goroutine gets a transaction and can check a status.

Transaction Manager over GORM

Description

Gorm currently has a transaction management feature, but the code for many operations looks overloaded.

Example

We have a service (UserService) to work with the user. When debiting a user's account, we must:

  1. Get the record with the user's balance
  2. Сheck whether funds can be debited from the user's account
  3. Debit from the user's account
  4. Create a transaction that the debit was successful

If we get an error on one of these, we must roll back. Code samples:

Implementation transaction service

cat internal/service/transaction.go
package service


...


type TransactionService struct {
	repository *repository.TransactionRepository
}


...


func (s *TransactionService) Create(
	transactionCreate *dto.TransactionCreate, tx ...*gorm.DB,
) (*entity.Transaction, error) {
	return s.repository.Create(
		&entity.Transaction{
			Type:      transactionCreate.Type,
			Amount:    transactionCreate.Amount,
			UserID:    transactionCreate.UserID,
			OrderID:   transactionCreate.OrderID,
			ServiceID: transactionCreate.ServiceID,
		}, tx...,
	)
}

Implementation user service

cat internal/service/user.go
package service


...


type UserService struct {
	repository         *repository.UserRepository
	transactionService *TransactionService
}


...


func (s *UserService) WithdrawUserBalance(
	userID uuid.UUID, userWithdrawal *dto.UserWithdrawal, tx ...*gorm.DB,
) (*entity.User, error) {
	var user *entity.User
	err := s.repository.Transaction(func(tx *gorm.DB) (err error) {
		user, err = s.FindOne(userID, tx)
		if err != nil {
			return
		}
		user, err = s.repository.WithdrawUserBalance(
			user, userWithdrawal.Amount, tx,
		)
		if err != nil {
			return
		}
		_, err = s.transactionService.Create(&dto.TransactionCreate{
			Type:      "withdrawal",
			Amount:    userWithdrawal.Amount,
			UserID:    userID,
			OrderID:   userWithdrawal.OrderID,
			ServiceID: userWithdrawal.ServiceID,
		}, tx)
		if err != nil {
			return
		}

		return
	}, tx...)

	return user, err
}

Implementation transaction repository

cat internal/repository/transaction.go
package repository


...


type TransactionRepository struct {
	db *gorm.DB
}


...


func (r *TransactionRepository) txDefault(tx ...*gorm.DB) *gorm.DB {
	if len(tx) < 1 {
		return r.db
	}

	return tx[0]
}

func (r *TransactionRepository) Create(
	transaction *entity.Transaction, tx ...*gorm.DB,
) (*entity.Transaction, error) {
	err := r.txDefault(tx...).Create(transaction).Error
	if err != nil {
		return nil, err
	}

	return transaction, nil
}

Implementation user repository

cat internal/repository/user.go
package repository


...


type UserRepository struct {
	db *gorm.DB
}


...


func (r *UserRepository) Transaction(
	fn func(*gorm.DB) error, tx ...*gorm.DB,
) error {
	return r.txDefault(tx...).Transaction(fn)
}

func (r *UserRepository) txDefault(tx ...*gorm.DB) *gorm.DB {
	if len(tx) < 1 {
		return r.db
	}

	return tx[0]
}


...


func (r *UserRepository) WithdrawUserBalance(
	user *entity.User, amount uint, tx ...*gorm.DB,
) (*entity.User, error) {
	if user.Balance < amount || user.Balance == 0 {
		return nil, errors.New("user balance is not enough")
	}
	user.Balance -= amount
	err := r.txDefault(tx...).Save(user).Error
	if err != nil {
		return nil, err
	}

	return user, nil
}

Сonclusion

Using the standard gorm transaction manager forces you to add transaction management logic on both the service and the repository level, and the code nesting when opening a transaction is not good enough.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.