Skip to content

Commit

Permalink
Added gorm
Browse files Browse the repository at this point in the history
  • Loading branch information
aneshas committed Dec 8, 2024
1 parent bad2cc6 commit 7b7549c
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 4 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Coverage Status](https://coveralls.io/repos/github/aneshas/tx/badge.svg)](https://coveralls.io/github/aneshas/tx)
[![Go Reference](https://pkg.go.dev/badge/github.com/aneshas/tx.svg)](https://pkg.go.dev/github.com/aneshas/tx)

`go get github.com/aneshas/tx/v2`
`go get github.com/aneshas/tx/v2@latest`

Package tx provides a simple abstraction which leverages `context.Context` in order to provide a transactional behavior
which one could use in their use case orchestrator (eg. application service, command handler, etc...). You might think of it
Expand All @@ -19,7 +19,7 @@ still does not violate the reasoning behind context package - which is to carry
a database transaction in this case.

## Drivers
Library currently supports `pgx` and stdlib `sql` out of the box although it is very easy to implement any additional ones
Library currently supports `pgx`, `gorm` and stdlib `sql` out of the box although it is very easy to implement any additional ones
you might need.

## Example
Expand Down
8 changes: 6 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
Expand All @@ -32,8 +34,10 @@ require (
go.uber.org/zap v1.25.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/postgres v1.5.11 // indirect
gorm.io/gorm v1.25.12 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down Expand Up @@ -94,6 +98,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -106,6 +112,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand All @@ -124,5 +132,9 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
52 changes: 52 additions & 0 deletions gormtx/gormtx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package gormtx

import (
"context"
"github.com/aneshas/tx/v2"
"gorm.io/gorm"
)

var (
_ tx.DB = &DB{}
_ tx.Transaction = &Tx{}
)

// NewDB instantiates new tx.DB *gorm.DB wrapper
func NewDB(db *gorm.DB) tx.DB {
return &DB{DB: db}
}

// DB implements tx.DB
type DB struct {
*gorm.DB
}

// Begin begins gorm transaction
func (db *DB) Begin(ctx context.Context) (tx.Transaction, error) {
txx := db.WithContext(ctx).Begin()
if txx.Error != nil {
return nil, txx.Error
}

return &Tx{txx}, nil
}

// Tx wraps *gorm.DB in order top implement tx.Transaction
type Tx struct {
*gorm.DB
}

// Commit commits the transaction
func (t Tx) Commit(_ context.Context) error {
return t.DB.Commit().Error
}

// Rollback rolls back the transaction
func (t Tx) Rollback(_ context.Context) error {
return t.DB.Rollback().Error
}

// From returns underlying *gorm.DB (wrapped in *Tx)
func From(ctx context.Context) (*Tx, bool) {
return tx.From[*Tx](ctx)
}
76 changes: 76 additions & 0 deletions gormtx/gormtx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//go:build integration
// +build integration

package gormtx_test

import (
"context"
"fmt"
"github.com/aneshas/tx/v2"
"github.com/aneshas/tx/v2/gormtx"
"github.com/aneshas/tx/v2/testutil"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/stretchr/testify/assert"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"testing"
)

var (
pool *pgxpool.Pool
db *gorm.DB
)

func TestMain(m *testing.M) {
t := new(testing.T)

p, sqlDB := testutil.SetupDB(t)

gormDB, err := gorm.Open(postgres.New(postgres.Config{
Conn: sqlDB,
}), &gorm.Config{})

assert.NoError(t, err)

pool = p
db = gormDB

m.Run()
}

func TestShould_Commit_Sql_Transaction(t *testing.T) {
name := "success_sql"

doSql(t, tx.New(gormtx.NewDB(db)), name, false)
testutil.AssertSuccess(t, pool, name)
}

func TestShould_Rollback_Sql_Transaction(t *testing.T) {
name := "failure_sql"

doSql(t, tx.New(gormtx.NewDB(db)), name, true)
testutil.AssertFailure(t, pool, name)
}

func doSql(t *testing.T, transactor *tx.TX, name string, fail bool) {
t.Helper()

err := transactor.WithTransaction(context.TODO(), func(ctx context.Context) error {
ttx, _ := gormtx.From(ctx)

db := ttx.Exec(`insert into cats (name) values(?)`, name)
if db.Error != nil {
return db.Error
}

if fail {
return fmt.Errorf("db error")
}

return db.Error
})

if !fail {
assert.NoError(t, err)
}
}
3 changes: 3 additions & 0 deletions testtx/testtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package testtx

import "context"

// New creates a new TX
func New() *TX {
return &TX{}
}

// TX is a noop test implementation of tx.DB
type TX struct {
Err error
}

// WithTransaction is a noop test implementation of tx.DB
func (t *TX) WithTransaction(ctx context.Context, f func(ctx context.Context) error) error {
t.Err = f(ctx)

Expand Down

0 comments on commit 7b7549c

Please sign in to comment.