Skip to content

Commit

Permalink
Merge pull request #99 from kozmod/feature/98_default_impl_for_the_fa…
Browse files Browse the repository at this point in the history
…mous_libs

[#98] default impl for the famous libs
  • Loading branch information
kozmod authored Mar 2, 2024
2 parents 4ff133a + 961ccfb commit e30a674
Show file tree
Hide file tree
Showing 26 changed files with 599 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.20.7
go-version: 1.21.0
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ name: Release

on:
push:
branches:
- main
tags:
- "*"
- "v*.*.*"

jobs:
release:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.20.7
go-version: 1.21.0

- name: Test
run: go test -v ./... -cover -coverprofile cover.out && go tool cover -func cover.out
Expand Down
38 changes: 32 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.PHONT: tools
TAG_TEMPLATE:= ^[v][0-9]+[.][0-9]+[.][0-9]([-]{0}|[-]{1}[0-9a-zA-Z]+[.]?[0-9a-zA-Z]+)+$$

PHONT: tools
tools: ## Run tools (vet, gofmt, goimports, tidy, etc.)
@go version
gofmt -w .
Expand All @@ -9,26 +11,50 @@ tools: ## Run tools (vet, gofmt, goimports, tidy, etc.)
.PHONT: tools.update
tools.update: ## Update or install tools
go install golang.org/x/tools/cmd/goimports@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

.PHONT: deps.update
deps.update: ## Update dependencies versions
go get -u all
go mod tidy
deps.update: ## Update dependencies versions (root and sub modules)
@go get -u all
@go mod tidy
@for d in */ ; do pushd "$$d" && go get -u all && go mod tidy && popd; done

.PHONT: go.sync
go.sync: ## Sync modules
@go work sync

.PHONT: test
test: ## Run tests with coverage
go test ./... -cover
@go test ./... -cover

.PHONT: test.cover.all
test.cover.all: ## Run tests with coverage (show all coverage)
go test -v ./... -cover -coverprofile cover.out && go tool cover -func cover.out
@go test -v ./... -cover -coverprofile cover.out && go tool cover -func cover.out

.PHONY: lint
lint: ## Run `golangci-lint`
@go version
@golangci-lint --version
@golangci-lint run .

.PHONT: tags.add
tags.add: ## Set root module and submodules tags (git)
@(val=$$(echo $(t)| tr -d ' ') && \
if [[ ! $$val =~ ${TAG_TEMPLATE} ]] ; then echo "not semantic version tag [$$val]" && exit 2; fi && \
git tag "$$val" && echo "set root module's tag [$$val]" && \
for d in */ ; do git tag "$$d$$val" && echo "set submodule's tag [$$d$$val]"; done)

.PHONT: tags.del
tags.del: ## Delete root module and submodules tags (git)
@(val=$$(echo $(t)| tr -d ' ') && \
if [[ ! $$val =~ ${TAG_TEMPLATE} ]] ; then echo "not semantic version tag [$$val]" && exit 2; fi && \
git tag --delete "$$val" && echo "delete root module's tag [$$val]" && \
for d in */ ; do git tag --delete "$$d$$val" && echo "delete submodule's tag [$$d$$val]"; done)

.PHONT: tags.list
tags.list: ## List all exists tags (git)
@(git for-each-ref refs/tags --sort=-taggerdate --format='%(refname)')

.PHONY: help
help: ## List all make targets with description
@grep -h -E '^[.a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
Expand Down
73 changes: 42 additions & 31 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# OnionTx <img align="right" src=".github/assets/onion_1.png" alt="drawing" width="90" />
# oniontx <img align="right" src=".github/assets/onion_1.png" alt="drawing" width="90" />
[![test](https://github.com/kozmod/oniontx/actions/workflows/test.yml/badge.svg)](https://github.com/kozmod/oniontx/actions/workflows/test.yml)
[![Release](https://github.com/kozmod/oniontx/actions/workflows/release.yml/badge.svg)](https://github.com/kozmod/oniontx/actions/workflows/release.yml)
![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/kozmod/oniontx)
Expand All @@ -7,13 +7,14 @@
![GitHub last commit](https://img.shields.io/github/last-commit/kozmod/oniontx)
[![GitHub MIT license](https://img.shields.io/github/license/kozmod/oniontx)](https://github.com/kozmod/oniontx/blob/dev/LICENSE)

`OnionTx` allows to move transferring transaction management from the `Persistence` (repository) layer to the `Application` (service) layer using owner defined contract.
`oniotx` allows to move transferring transaction management from the `Persistence` (repository) layer to the `Application` (service) layer using owner defined contract.
# <img src=".github/assets/clean_arch+uml.png" alt="drawing" width="700" />
🔴 **NOTE:** `Transactor` was designed to work with only the same instance of the "repository" (`*sql.DB`, etc.)
### The key features:
- [**`stdlib` implementation out of the box**](#stdlib)
- [**default implementation for `stdlib`**](#stdlib)
- [**default implementation for popular libraries**](#libs)
- [**custom implementation's contract**](#custom)
- [**simple integration with popular libraries**](#integration_examples)
- [**simple testing with testing frameworks**](#testing)

---
### <a name="stdlib"><a/>`stdlib` package
Expand All @@ -29,14 +30,14 @@ import (
"log"
"testing"

oniontx "github.com/kozmod/oniontx/stdlib"
ostdlib "github.com/kozmod/oniontx/stdlib"
)

func main() {
var (
db *sql.DB // database instance

tr = oniontx.NewTransactor(db)
tr = ostdlib.NewTransactor(db)
r1 = repoA{t: tr}
r2 = repoB{t: tr}
)
Expand All @@ -62,7 +63,7 @@ func main() {
}

type repoA struct {
t *oniontx.Transactor
t *ostdlib.Transactor
}

func (r *repoA) InsertInTx(ctx context.Context, val string) error {
Expand All @@ -75,7 +76,7 @@ func (r *repoA) InsertInTx(ctx context.Context, val string) error {
}

type repoB struct {
t *oniontx.Transactor
t *ostdlib.Transactor
}

func (r *repoB) InsertInTx(ctx context.Context, val string) error {
Expand All @@ -87,13 +88,27 @@ func (r *repoB) InsertInTx(ctx context.Context, val string) error {
return nil
}
```
[oniontx-examples](https://github.com/kozmod/oniontx-examples) contains more complicated
[example](https://github.com/kozmod/oniontx-examples/tree/master/internal/stdlib).

---
### <a name="libs"><a/>Default implementation for database libs
`oniontx` has default implementation (as submodules) for maintaining transactions for database libraries:
[sqlx](https://github.com/jmoiron/sqlx),
[pgx](https://github.com/jackc/pgx),
[gorm](https://github.com/go-gorm/gorm).

Examples:
- [sqlx](https://github.com/kozmod/oniontx-examples/tree/master/internal/sqlx)
- [pgx](https://github.com/kozmod/oniontx-examples/tree/master/internal/pgx)
- [gorm](https://github.com/kozmod/oniontx-examples/tree/master/internal/gorm)

---
## <a name="custom"><a/>Custom realisation
If it's required, `OnionTx` allowed opportunity to implements custom algorithms for maintaining transactions
(it is convenient if the persistence to DB implements not standard library: [sqlx](https://github.com/jmoiron/sqlx), [pgx](https://github.com/jackc/pgx), [gorm](https://github.com/go-gorm/gorm) etc.
Look at the [integration's examples](#integration_examples) section).

#### `OnitonTx` interfaces implementation
## <a name="custom"><a/>Custom implementation
If it's required, `oniontx` allowed opportunity to implements custom algorithms for maintaining transactions (examples).

#### Interfaces:
```go
type (
// Mandatory
Expand Down Expand Up @@ -123,9 +138,9 @@ type (
)
```
### Examples
***All examples based on `stdlib`.***
``***This examples based on `stdlib` pacakge.***

`TxBeginner` and `Tx` implementations example:
`TxBeginner` and `Tx` implementations:
```go
// Prepared contracts for execution
package db
Expand Down Expand Up @@ -169,7 +184,7 @@ func (t *Tx) Commit(_ context.Context) error {
return t.Tx.Commit()
}
```
`Repositories` implementation example:
`Repositories` implementation:
```go
package repoA

Expand Down Expand Up @@ -228,7 +243,7 @@ func (r RepositoryB) Insert(ctx context.Context, val int) error {
return nil
}
```
`UseCase` implementation example:
`UseCase` implementation:
```go
package usecase

Expand Down Expand Up @@ -272,16 +287,16 @@ func (s *UseCase) Exec(ctx context.Context, insert int) error {
return nil
}
```
Configuring example:
Configuring:
```go
package main

import (
"context"
"database/sql"
"os"
"github.com/kozmod/oniontx"

oniontx "github.com/kozmod/oniontx"

"github.com/user/some_project/internal/repoA"
"github.com/user/some_project/internal/repoB"
Expand Down Expand Up @@ -349,7 +364,7 @@ func WithIsolationLevel(level int) oniontx.Option[*sql.TxOptions] {
}

```
UsCase
UsCase:
```go
func (s *Usecase) Do(ctx context.Context) error {
err := s.Transactor.WithinTxWithOpts(ctx, func(ctx context.Context) error {
Expand All @@ -373,7 +388,7 @@ func (s *Usecase) Do(ctx context.Context) error {
#### Execution transaction in the different use cases
***Execution the same transaction for different `usecases` with the same `oniontx.Transactor` instance***

UseCases
UseCases:
```go
package a

Expand Down Expand Up @@ -465,7 +480,7 @@ func (s *UseCaseB) Exec(ctx context.Context, insertA string, insertB int, delete
return nil
}
```
Main
Main:
```go
package main

Expand All @@ -474,7 +489,7 @@ import (
"database/sql"
"os"

"github.com/kozmod/oniontx"
oniontx "github.com/kozmod/oniontx"

"github.com/user/some_project/internal/db"
"github.com/user/some_project/internal/repoA"
Expand Down Expand Up @@ -512,12 +527,8 @@ func main() {
}
```

### <a name="integration_examples"><a/>Integration's examples
### <a name="testing"><a/>Testing

[oniontx-examples](https://github.com/kozmod/oniontx-examples) repository contains useful examples for integrations:
[oniontx-examples](https://github.com/kozmod/oniontx-examples) repository contains useful examples for creating unit test:

- [sqlx](https://github.com/kozmod/oniontx-examples/tree/master/internal/sqlx)
- [pgx](https://github.com/kozmod/oniontx-examples/tree/master/internal/pgx)
- [gorm](https://github.com/kozmod/oniontx-examples/tree/master/internal/gorm)
- [stdlib](https://github.com/kozmod/oniontx-examples/tree/master/internal/stdlib)
- [mockery](https://github.com/kozmod/oniontx-examples/tree/master/internal/mock/mockery)
- [vektra/mockery **+** stretchr/testify](https://github.com/kozmod/oniontx-examples/tree/master/internal/mock/mockery)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/kozmod/oniontx

go 1.20
go 1.21.0
9 changes: 9 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
go 1.21.0

use (
.
gorm
pgx
sqlx
stdlib
)
20 changes: 20 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5 changes: 5 additions & 0 deletions gorm/Redme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## gorm/oniontx

Default implementation `gorm` of the `Transactor`.

[Examples](https://github.com/kozmod/oniontx-examples/tree/master/internal/gorm)
15 changes: 15 additions & 0 deletions gorm/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module github.com/kozmod/oniontx/gorm

go 1.21.0

replace github.com/kozmod/oniontx => ../

require (
github.com/kozmod/oniontx v0.0.0
gorm.io/gorm v1.25.7
)

require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
)
6 changes: 6 additions & 0 deletions gorm/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
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=
gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
33 changes: 33 additions & 0 deletions gorm/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package gorm

import (
"database/sql"

"github.com/kozmod/oniontx"
)

// TxOption implements oniontx.Option.
type TxOption func(opt *sql.TxOptions)

// Apply the TxOption to [sql.TxOptions].
func (o TxOption) Apply(opt *sql.TxOptions) {
o(opt)
}

// WithReadOnly set `ReadOnly` sql.TxOptions option.
//
// Look at [sql.TxOptions.ReadOnly].
func WithReadOnly(readonly bool) oniontx.Option[*sql.TxOptions] {
return TxOption(func(opt *sql.TxOptions) {
opt.ReadOnly = readonly
})
}

// WithIsolationLevel set sql.TxOptions isolation level.
//
// Look at [sql.TxOptions.Isolation].
func WithIsolationLevel(level int) oniontx.Option[*sql.TxOptions] {
return TxOption(func(opt *sql.TxOptions) {
opt.Isolation = sql.IsolationLevel(level)
})
}
Loading

0 comments on commit e30a674

Please sign in to comment.