From 62ac34b6f6b70b75fb531dced938421ef846c23c Mon Sep 17 00:00:00 2001 From: phil Date: Tue, 14 Jan 2020 17:29:34 +0800 Subject: [PATCH] [feature]:implement transaction --- article/mocks/Repository.go | 18 +++++++++++++++++- article/repository.go | 1 + article/repository/mysql_article.go | 27 ++++++++++++++++++++++++++- go.mod | 6 +++--- go.sum | 12 ++++++------ types/db.go | 15 +++++++++++++++ 6 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 types/db.go diff --git a/article/mocks/Repository.go b/article/mocks/Repository.go index 5541e8b..e7bc3e7 100644 --- a/article/mocks/Repository.go +++ b/article/mocks/Repository.go @@ -1,6 +1,8 @@ -// Code generated by mockery v1.0.0 +// Code generated by mockery v1.0.0. DO NOT EDIT. + package mocks +import article "github.com/bxcodec/go-clean-arch/article" import context "context" import mock "github.com/stretchr/testify/mock" import models "github.com/bxcodec/go-clean-arch/models" @@ -127,3 +129,17 @@ func (_m *Repository) Update(ctx context.Context, ar *models.Article) error { return r0 } + +// WithTransaction provides a mock function with given fields: _a0 +func (_m *Repository) WithTransaction(_a0 func(article.Repository) error) error { + ret := _m.Called(_a0) + + var r0 error + if rf, ok := ret.Get(0).(func(func(article.Repository) error) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/article/repository.go b/article/repository.go index bbcc1f7..4aac964 100644 --- a/article/repository.go +++ b/article/repository.go @@ -14,4 +14,5 @@ type Repository interface { Update(ctx context.Context, ar *models.Article) error Store(ctx context.Context, a *models.Article) error Delete(ctx context.Context, id int64) error + WithTransaction(func(Repository)error) error } diff --git a/article/repository/mysql_article.go b/article/repository/mysql_article.go index 173ca4c..df6ad83 100644 --- a/article/repository/mysql_article.go +++ b/article/repository/mysql_article.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "encoding/base64" + "errors" "fmt" "time" @@ -11,6 +12,7 @@ import ( "github.com/bxcodec/go-clean-arch/article" "github.com/bxcodec/go-clean-arch/models" + "github.com/bxcodec/go-clean-arch/types" ) const ( @@ -18,7 +20,7 @@ const ( ) type mysqlArticleRepository struct { - Conn *sql.DB + Conn types.DB } // NewMysqlArticleRepository will create an object that represent the article.Repository interface @@ -213,3 +215,26 @@ func EncodeCursor(t time.Time) string { return base64.StdEncoding.EncodeToString([]byte(timeString)) } + +func (m *mysqlArticleRepository) WithTransaction(f func(repo article.Repository) error) error { + if db, ok := m.Conn.(*sql.DB); ok { + tx, err := db.Begin() + if err != nil { + return err + } + + defer tx.Rollback() + + if err := f(&mysqlArticleRepository{Conn: tx}); err != nil { + return err + } + + return tx.Commit() + } + + if _, ok := m.Conn.(*sql.Tx); ok { + return f(m) + } + + return errors.New("unknow DB type") +} diff --git a/go.mod b/go.mod index 1aaf67b..c03148c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.12 require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/bxcodec/faker v1.4.2 - github.com/davecgh/go-spew v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect github.com/go-sql-driver/mysql v1.3.0 @@ -26,8 +26,8 @@ require ( github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec // indirect github.com/spf13/pflag v1.0.1 // indirect github.com/spf13/viper v1.0.2 - github.com/stretchr/objx v0.1.0 // indirect - github.com/stretchr/testify v1.2.1 + github.com/stretchr/objx v0.1.1 // indirect + github.com/stretchr/testify v1.2.2 github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect golang.org/x/crypto v0.0.0-20180426230345-b49d69b5da94 // indirect diff --git a/go.sum b/go.sum index b77ed38..a86a0b3 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/bxcodec/faker v1.4.2 h1:PlGLUcQ/yo/JUiwn3kUGnFkDbcv2o18oryc+ch+AkqY= github.com/bxcodec/faker v1.4.2/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= @@ -51,10 +51,10 @@ github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= -github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8= diff --git a/types/db.go b/types/db.go new file mode 100644 index 0000000..273fa15 --- /dev/null +++ b/types/db.go @@ -0,0 +1,15 @@ +package types + +import ( + "context" + "database/sql" +) + +type DB interface { + Query(query string, args ...interface{}) (*sql.Rows, error) + QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) + Prepare(query string) (*sql.Stmt, error) + PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) + Exec(query string, args ...interface{}) (sql.Result, error) + ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) +}