feat(uow): transaction share by retun tx

This commit is contained in:
Kristian Borgwarth 2026-04-02 17:24:18 +02:00
parent ae99233e4b
commit f070674cdb
4 changed files with 35 additions and 38 deletions

View file

@ -17,13 +17,9 @@ type createNoteCommand struct {
Vars map[string]string `json:"vars"` Vars map[string]string `json:"vars"`
} }
type CreateNoteHandler struct { type CreateNoteHandler struct {}
uow *repositories.UnitOfWork
}
func NewCreateNoteHandler(uow *repositories.UnitOfWork) *CreateNoteHandler { func NewCreateNoteHandler(uow *repositories.UnitOfWork) *CreateNoteHandler
return &CreateNoteHandler{uow: uow}
}
func (h CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) { func (h CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (any, error) {
var cmd createNoteCommand var cmd createNoteCommand

View file

@ -2,6 +2,7 @@ package repositories
import ( import (
"context" "context"
"database/sql"
) )
type NoteRepository interface { type NoteRepository interface {
@ -9,11 +10,11 @@ type NoteRepository interface {
} }
type noteRepository struct { type noteRepository struct {
dbCtx DBContext Transaction *sql.Tx
} }
func NewNoteRepository(dbContext DBContext) NoteRepository { func NewNoteRepository(tx *sql.Tx) NoteRepository {
return &noteRepository{dbCtx: dbContext} return &noteRepository{Transaction: tx}
} }
func (r *noteRepository) Upsert(ctx context.Context, title string, path string, slug string) error { func (r *noteRepository) Upsert(ctx context.Context, title string, path string, slug string) error {
@ -24,6 +25,6 @@ func (r *noteRepository) Upsert(ctx context.Context, title string, path string,
SET title = EXCLUDED.title, SET title = EXCLUDED.title,
path = EXCLUDED.path; path = EXCLUDED.path;
` `
_, err := r.dbCtx.ExecContext(ctx, query, title, path, slug) _, err := r.Transaction.ExecContext(ctx, query, title, path, slug)
return err return err
} }

View file

@ -2,6 +2,7 @@ package repositories
import ( import (
"context" "context"
"database/sql"
"strings" "strings"
) )
@ -10,11 +11,11 @@ type TagRepository interface {
} }
type tagRepository struct { type tagRepository struct {
dbContext DBContext Transaction *sql.Tx
} }
func NewTagRepository(dbContext DBContext) TagRepository { func NewTagRepository(tx *sql.Tx) TagRepository {
return &tagRepository{dbContext: dbContext} return &tagRepository{Transaction: tx}
} }
func (r *tagRepository) Upsert(ctx context.Context, names []string) error { func (r *tagRepository) Upsert(ctx context.Context, names []string) error {
@ -36,7 +37,7 @@ func (r *tagRepository) Upsert(ctx context.Context, names []string) error {
"SELECT name FROM input " + "SELECT name FROM input " +
"ON CONFLICT(name) DO NOTHING;" "ON CONFLICT(name) DO NOTHING;"
_, err := r.dbContext.ExecContext(ctx, query, args) _, err := r.Transaction.ExecContext(ctx, query, args)
if err != nil { if err != nil {
return err return err
} }
@ -64,7 +65,7 @@ func (r *tagRepository) UpsertNoteTags(noteID int64, tagIDs []int64) error {
"ON CONFLICT(note_id, tag_id) DO NOTHING" + "ON CONFLICT(note_id, tag_id) DO NOTHING" +
"SELECT note_id, tag_id FROM input;" "SELECT note_id, tag_id FROM input;"
_, err := r.dbContext.ExecContext(context.Background(), query, args) _, err := r.Transaction.ExecContext(context.Background(), query, args)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,40 +1,39 @@
package repositories package repositories
import ( import (
"context"
"database/sql" "database/sql"
) )
type DBContext interface {
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}
type UnitOfWork struct { type UnitOfWork struct {
db *sql.DB db *sql.DB
Transaction *sql.Tx
} }
func NewUnitOfWork(db *sql.DB) *UnitOfWork { func NewUnitOfWork(db *sql.DB) *UnitOfWork {
return &UnitOfWork{db: db} return &UnitOfWork{db: db}
} }
func (u *UnitOfWork) Execute(ctx context.Context, fn func(tx *sql.Tx) error) (err error) { func (u *UnitOfWork) Begin() (tx *sql.Tx, err error) {
transcation, err := u.db.BeginTx(ctx, nil) tx, err = u.db.Begin()
if err != nil { if err != nil {
return err return nil, err
}
u.Transaction = tx
return tx, nil
} }
defer func() { func (u *UnitOfWork) Commit() error {
if err != nil { if u.Transaction == nil {
_ = transcation.Rollback() return nil
} }
}() return u.Transaction.Commit()
if err = fn(transcation); err != nil {
return err
} }
err = transcation.Commit() func (u *UnitOfWork) Rollback() error {
return err if u.Transaction == nil {
return nil
} }
return u.Transaction.Rollback()
}