Skip to content

Commit

Permalink
V2 (#96)
Browse files Browse the repository at this point in the history
Separated drivers
  • Loading branch information
maranqz authored Jan 4, 2024
1 parent f1e5dc8 commit ac493a6
Show file tree
Hide file tree
Showing 162 changed files with 1,550 additions and 2,084 deletions.
40 changes: 25 additions & 15 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,30 +112,40 @@ jobs:
- name: Tests with real databases
run: make test.coverage.with_real_db

- name: Code coverage data
run: |
set -x
COVERAGE_TOTAL=`go tool cover -func=coverage.out | grep total | grep -Eo '[0-9]+\.[0-9]+'`
echo "COVERAGE_TOTAL=$COVERAGE_TOTAL" >> $GITHUB_ENV
- uses: jandelgado/[email protected]
with:
outfile: ./coverage.lcov

- name: Coveralls
uses: coverallsapp/github-action@master
uses: coverallsapp/github-action@v2
with:
path-to-lcov: ./coverage.lcov
format: golang
file: ./coverage.out
github-token: ${{ secrets.GITHUB_TOKEN }}

golangci:
name: lint
# https://github.com/golangci/golangci-lint/issues/828
generate-pkgs-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Fetch Repository
uses: actions/checkout@v4
- id: set-matrix
run: |
DIRECTORIES=$(find . -not -path "*/vendor/*" -type f -name go.mod -exec sh -c 'echo $(dirname {})' \; | jq -R -s -c 'split("\n")[:-1]')
echo "matrix=${DIRECTORIES}" >> $GITHUB_OUTPUT
lint:
needs: generate-pkgs-matrix
runs-on: ubuntu-latest
strategy:
matrix:
modules: ${{fromJson(needs.generate-pkgs-matrix.outputs.matrix)}}
steps:
- uses: actions/setup-go@v3
- name: Fetch Repository
uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_TARGET_VERSION }}
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
args: --timeout=3m -v
working-directory: ${{ matrix.modules }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ vendor/

# Code coverage
coverage.*
coverage/
16 changes: 5 additions & 11 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
linters-settings:
enable-all: true

run:
skip-dirs:
- trm/mock
Expand Down Expand Up @@ -68,9 +65,6 @@ linters:

issues:
exclude-use-default: false
errcheck:
check-type-assertions: true
check-blank: true
exclude:
- ST1000 # ST1000: at least one file in a package should have a package comment
exclude-rules:
Expand All @@ -95,28 +89,28 @@ issues:
linters:
- staticcheck
text: "SA1029: should not use built-in type string as key for value; define your own type to avoid collisions"
- path: .+/context\.go
- path: (.+/)?context\.go
linters:
- ireturn
- path: .+/transaction\.go
- path: (.+/)?transaction\.go
linters:
- ireturn
source: \) Begin\(ctx
- path: .+/settings\.go
- path: (.+/)?settings\.go
linters:
- ireturn
source: "(?:EnrichBy|SetPropagation|SetCtxKey|CtxKey|SetCancelable|SetTimeout)"
- linters:
- gochecknoglobals
source: "DefaultCtxGetter"
- &internal_text
path: ^internal
path: (^trm/internal|^internal)
text: "var-naming: don't use an underscore in package name"
- <<: *internal_text
text: "package-comments: should have a package comment"
- <<: *internal_text
text: "ST1003: should not use underscores in package names"
- path: (_test\.go|^internal)
- path: (_test\.go|^trm/internal|^internal)
linters:
- funlen
- gochecknoglobals
Expand Down
51 changes: 42 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,25 +1,58 @@
CVPKG=go list ./... | grep -v mocks | grep -v internal/
GO_TEST=go test `$(CVPKG)` -race
GO_TEST_WITH_REAL_DB=$(GO_TEST) --tags=with_real_db
COVERAGE_FILE="coverage.out"
DIR=$(PWD)

GO_TEST=cd ./sh && bash ./go.test.sh
GO_TEST_COVERAGE=cd ./sh && bash ./go.test.coverage.sh

GO_TEST_WITH_REAL_DB=--tags=with_real_db

test:
$(GO_TEST)

test.with_real_db:
$(GO_TEST_WITH_REAL_DB)
$(GO_TEST) $(GO_TEST_WITH_REAL_DB)

test.coverage:
$(GO_TEST) -covermode=atomic -coverprofile=$(COVERAGE_FILE)
$(GO_TEST_COVERAGE)

test.coverage.with_real_db:
$(GO_TEST_WITH_REAL_DB) -covermode=atomic -coverprofile=$(COVERAGE_FILE)
$(GO_TEST_COVERAGE) $(GO_TEST_WITH_REAL_DB)

fmt:
go fmt ./...
cd sh && sh ./go.fmt.sh

lint:
golangci-lint run -v --timeout=2m
cd sh && sh ./lint.sh

lint.verbose:
cd sh && sh ./lint.sh -v

lint.cache.clean:
golangci-lint cache clean

generate:
go generate ./...

go.mod.tidy:
cd sh && sh ./go.mod.tidy.sh

go.mod.vendor:
cd sh && sh ./go.mod.vendor.sh

go.work.sync:
go work sync


tag: git.tag tag.pkg

tag.pkg:
cd sh && sh ./tag.pkg.sh $(version)

git.tag: git.tag.create git.tag.push

# 1.0, "v2." added automatically
# make git.tag version="0.0-rc1"
git.tag.create:
cd sh && sh ./git.tag.sh $(version)

git.tag.push:
git push origin --tags
70 changes: 45 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Go transaction manager

[![Go Reference](https://pkg.go.dev/badge/github.com/avito-tech/go-transaction-manager.svg)](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager)
[![Go Reference](https://pkg.go.dev/badge/github.com/avito-tech/go-transaction-manager.svg)](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/trm/v2)
[![Test Status](https://github.com/avito-tech/go-transaction-manager/actions/workflows/main.yaml/badge.svg)](https://github.com/avito-tech/go-transaction-manager/actions?query=branch%3Amain)
[![Coverage Status](https://coveralls.io/repos/github/avito-tech/go-transaction-manager/badge.svg?branch=main)](https://coveralls.io/github/avito-tech/go-transaction-manager?branch=main)
[![Go Report Card](https://goreportcard.com/badge/github.com/avito-tech/go-transaction-manager)](https://goreportcard.com/report/github.com/avito-tech/go-transaction-manager)
[![Go Report Card](https://goreportcard.com/badge/github.com/avito-tech/go-transaction-manager)](https://goreportcard.com/report/github.com/avito-tech/go-transaction-manager/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Transaction manager is an abstraction to coordinate database transaction boundaries.
Expand All @@ -12,45 +12,56 @@ Easiest way to get the perfect repository.

## Supported implementations

* [database/sql](https://pkg.go.dev/database/sql), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/sql) (Go 1.13)
* [jmoiron/sqlx](https://github.com/jmoiron/sqlx), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/sqlx) (Go 1.13)
* [gorm](https://github.com/go-gorm/gorm), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/gorm) (Go 1.16)
* [mongo-go-driver](https://github.com/mongodb/mongo-go-driver), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/mongo) (Go 1.13)
* [go-redis/redis](https://github.com/go-redis/redis), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/redis) (Go 1.17)
* [pgx_v4](https://github.com/jackc/pgx/tree/v4), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/pgxv4) (Go 1.16)
* [pgx_v5](https://github.com/jackc/pgx), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/pgxv5) (Go 1.19)
* [database/sql](https://pkg.go.dev/database/sql), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/sql/v2) (
Go 1.13)
* [jmoiron/sqlx](https://github.com/jmoiron/sqlx), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/sqlx/v2) (
Go 1.13)
* [gorm](https://github.com/go-gorm/gorm), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/gorm/v2) (
Go 1.18)
* [mongo-go-driver](https://github.com/mongodb/mongo-go-driver), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/mongo/v2) (
Go 1.13)
* [go-redis/redis](https://github.com/go-redis/redis), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/goredis8/v2) (
Go 1.17)
* [pgx_v4](https://github.com/jackc/pgx/tree/v4), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/pgxv4/v2) (
Go 1.16)
* [pgx_v5](https://github.com/jackc/pgx), [docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/drivers/pgxv5/v2) (
Go 1.19)

## Installation

```bash
go get github.com/avito-tech/go-transaction-manager
go get github.com/avito-tech/go-transaction-manager/trm/v2
```

To install some support database use `go get github.com/avito-tech/go-transaction-manager/drivers/{name}`.

For example `go get github.com/avito-tech/go-transaction-manager/drivers/sqlx/v2`.

### Backwards Compatibility

The library is compatible with the most recent two versions of Go.
Compatibility beyond that is not guaranteed.

## Usage

**To use multiple transactions from different databases**, you need to set CtxKey in [Settings](trm/settings.go) by [WithCtxKey](trm/settings/option.go).
**To use multiple transactions from different databases**, you need to set CtxKey in [Settings](trm/settings.go)
by [WithCtxKey](trm/settings/option.go) ([docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/trm/v2)).

**For nested transactions with different transaction managers**, you need to use [ChainedMW](trm/manager/chain.go) ([docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/trm/manager)).
**For nested transactions with different transaction managers**, you need to use [ChainedMW](trm/manager/chain.go) ([docs](https://pkg.go.dev/github.com/avito-tech/go-transaction-manager/trm/v2/manager)).

**To skip a transaction rollback due to an error, use [ErrSkip](trm/manager.go#L20) or [Skippable](trm/manager.go#L24)**
**To skip a transaction rollback due to an error, use [ErrSkip](manager.go#L20) or [Skippable](manager.go#L24)**

### Explanation of the approach ([English](https://www.youtube.com/watch?v=aRsea6FFAyA), [Russian](https://habr.com/ru/companies/avito/articles/727168/))
### Explanation of the approach [English](https://www.youtube.com/watch?v=aRsea6FFAyA), Russian [article](https://habr.com/ru/companies/avito/articles/727168/) and [youtube](https://www.youtube.com/watch?v=fcdckM5sUxA).

### Examples with an ideal *repository* and nested transactions.

* [database/sql](sql/example_test.go)
* [jmoiron/sqlx](sqlx/example_test.go)
* [gorm](gorm/example_test.go)
* [mongo-go-driver](mongo/example_test.go)
* [go-redis/redis](redis/example_test.go)
* [pgx_v4](pgxv4/example_test.go)
* [pgx_v5](pgxv5/example_test.go)

* [database/sql](drivers/sql/example_test.go)
* [jmoiron/sqlx](drivers/sqlx/example_test.go)
* [gorm](drivers/gorm/example_test.go)
* [mongo-go-driver](drivers/mongo/example_test.go)
* [go-redis/redis](drivers/goredis8/example_test.go)
* [pgx_v4](drivers/pgxv4/example_test.go)
* [pgx_v5](drivers/pgxv5/example_test.go)

Below is an example how to start usage.

Expand All @@ -64,8 +75,8 @@ import (
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"

trmsqlx "github.com/avito-tech/go-transaction-manager/sqlx"
"github.com/avito-tech/go-transaction-manager/trm/manager"
trmsqlx "github.com/avito-tech/go-transaction-manager/drivers/sqlx/v2"
"github.com/avito-tech/go-transaction-manager/trm/v2/manager"
)

func main() {
Expand All @@ -85,6 +96,7 @@ func main() {
err = trManager.Do(ctx, func(ctx context.Context) error {
checkErr(r.Save(ctx, u))

// example of nested transactions
return trManager.Do(ctx, func(ctx context.Context) error {
u.Username = "new_username"
return r.Save(ctx, u)
Expand Down Expand Up @@ -146,4 +158,12 @@ func (r *repo) Save(ctx context.Context, u *user) error {

## Benchmark

[Comparing](internal/benchmark/with_or_without_trm/README.md) examples with and without trm.
[Comparing](trm/internal/benchmark/with_or_without_trm/README.md) examples with and without trm.

## Contribution

1. To local development sync dependencies use `make go.work.sync`.
2. After finalizing of changes bump up version in all drivers.

* To install all dependencies use `make go.mod.tidy` or `make go.mod.vendor`.
* To run all tests use `make go.test` or `make go.test.with_real_db` for integration tests.
12 changes: 6 additions & 6 deletions redis/context.go → drivers/goredis8/context.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package redis
package goredis8

import (
"context"

"github.com/go-redis/redis/v8"

"github.com/avito-tech/go-transaction-manager/trm"
trmcontext "github.com/avito-tech/go-transaction-manager/trm/context"
"github.com/avito-tech/go-transaction-manager/trm/v2"
trmcontext "github.com/avito-tech/go-transaction-manager/trm/v2/context"
)

// DefaultCtxGetter is the CtxGetter with settings.DefaultCtxKey.
var DefaultCtxGetter = NewCtxGetter(trmcontext.DefaultManager)

// CtxGetter gets redis.Pipeliner from trm.СtxManager by casting trm.Transaction to redis.UniversalClient.
// CtxGetter gets goredis8.Pipeliner from trm.СtxManager by casting trm.Transaction to redis.UniversalClient.
type CtxGetter struct {
ctxManager trm.СtxManager
}
Expand All @@ -22,7 +22,7 @@ func NewCtxGetter(c trm.СtxManager) *CtxGetter {
return &CtxGetter{ctxManager: c}
}

// DefaultTrOrDB returns Cmdable from context.Context or DB(redis.Cmdable) otherwise.
// DefaultTrOrDB returns Cmdable from context.Context or DB(goredis8.Cmdable) otherwise.
func (c *CtxGetter) DefaultTrOrDB(ctx context.Context, db redis.Cmdable) redis.Cmdable {
if tr := c.ctxManager.Default(ctx); tr != nil {
return c.convert(tr)
Expand All @@ -31,7 +31,7 @@ func (c *CtxGetter) DefaultTrOrDB(ctx context.Context, db redis.Cmdable) redis.C
return db
}

// TrOrDB returns Cmdable from context.Context by trm.CtxKey or DB(redis.Cmdable) otherwise.
// TrOrDB returns Cmdable from context.Context by trm.CtxKey or DB(goredis8.Cmdable) otherwise.
func (c *CtxGetter) TrOrDB(ctx context.Context, key trm.CtxKey, db redis.Cmdable) redis.Cmdable {
if tr := c.ctxManager.ByKey(ctx, key); tr != nil {
return c.convert(tr)
Expand Down
11 changes: 6 additions & 5 deletions redis/example_test.go → drivers/goredis8/example_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build with_real_db
// +build with_real_db

package redis_test
package goredis8_test

import (
"context"
Expand All @@ -10,10 +10,11 @@ import (

"github.com/go-redis/redis/v8"

trmredis "github.com/avito-tech/go-transaction-manager/redis"
"github.com/avito-tech/go-transaction-manager/trm"
"github.com/avito-tech/go-transaction-manager/trm/manager"
"github.com/avito-tech/go-transaction-manager/trm/settings"
trmredis "github.com/avito-tech/go-transaction-manager/drivers/goredis8/v2"

"github.com/avito-tech/go-transaction-manager/trm/v2"
"github.com/avito-tech/go-transaction-manager/trm/v2/manager"
"github.com/avito-tech/go-transaction-manager/trm/v2/settings"
)

// Example demonstrates the implementation of the Repository pattern by trm.Manager.
Expand Down
4 changes: 2 additions & 2 deletions redis/factory.go → drivers/goredis8/factory.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package redis
package goredis8

import (
"context"

"github.com/go-redis/redis/v8"

"github.com/avito-tech/go-transaction-manager/trm"
trm "github.com/avito-tech/go-transaction-manager/trm/v2"
)

// NewDefaultFactory creates default trm.Transaction(redis.UniversalClient).
Expand Down
14 changes: 14 additions & 0 deletions drivers/goredis8/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/avito-tech/go-transaction-manager/drivers/goredis8/v2

go 1.14

require (
github.com/avito-tech/go-transaction-manager/trm/v2 v2.0.0-rc6
github.com/go-redis/redis/v8 v8.11.5
github.com/go-redis/redismock/v8 v8.11.5
github.com/kr/pretty v0.3.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/stretchr/testify v1.8.2
golang.org/x/net v0.10.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
Loading

0 comments on commit ac493a6

Please sign in to comment.