8000 GitHub - Jille/trxwrap: WIP - Database transactions library for use with sqlc
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Jille/trxwrap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Transaction wrapper

This package provides helper code for automatic retries of database transactions. It is primarily intended to be used against sqlc-generated code.

While not strictly necessary, this README assumes you have a pkg/database directory containing your slqc.yaml, schema and queries; the sqlc.yaml is configured such that your generated Go files are at pkg/database/gendb within package gendb. If you have a different structure, modify your import paths below as appropriate.

To get started, create a pkg/database/db.go. First, define a func Init() which creates your database pool and then calls trxwrap.Init(), passing your database handle and a function that wraps a transaction handle within your sqlc-generated Queries object:

package database

import (
  // ...

  "github.com/Jille/trxwrap"
  "github.com/you/yourproject/pkg/database/gendb"
)

var (
  db trxwrap.TrxWrap[gendb.Queries]
)

func Init() {
  // ...
  pgx, err := pgxpool.ConnectConfig(context.Background(), pgxConfig)
  if err != nil {
    log.Fatal(err)
  }
  db = trxwrap.New(pgx, func(tx trxwrap.PGDBTX) *gendb.Queries {
    return gendb.New(tx)
  }
}

Then, after this, you can wrap the transaction functions e.g. as:

func RunRWTransaction(ctx context.Context, isolationLevel pgx.TxIsoLevel, runner func(*gendb.Queries) error) error {
	return db.RunRWTransaction(ctx, isolationLevel, runner)
}

func RunROTransaction(ctx context.Context, isolationLevel pgx.TxIsoLevel, runner func(*gendb.Queries) error) error {
	return db.RunROTransaction(ctx, isolationLevel, runner)
}

Now, you can write your transactions like this:

func GetStudents(ctx context.Context, enrolled bool) ([]Student, error) {
  var res []Student
  err := database.RunRWTransaction(ctx, pgx.RepeatableRead, func(q *gendb.Queries) error {
    // Remember that the transaction can be re-run, so we need to start over
    res = nil

    students, err := q.GetStudents(ctx, gendb.GetStudentsParams{
      Enrolled: enrolled,
    })
    if err != nil {
      return err
    }

    for _, student := range students {
      res = append(res, Student{
        Name:      student.Name,
        Birthdate: student.Birthdate,
      })
    }

    return nil
  })
  return res, err
}

If your transaction fails because of a transient error, e.g. a database instance restarting or a TCP connection drop, the transaction will be retried after a while, performing at most 3 attempts. The error of the last attempt will be returned.

About

WIP - Database transactions library for use with sqlc

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Contributors 2

  •  
  •  

Languages

0