func RunInTxWithRetry(ctx context.Context, db *sql.DB, fn func(context.Context, *sql.Tx) error, retryable func(error) bool) (err error) {
	return RunInTxWithRetryBackoff(
		ctx,
		db,
		fn,
		retryable,
		backoff.NewExponentialBackOff(),  
	)
}
RunInTxWithRetry is like RunInTx but will retry
several times with exponential backoff. In that case, fn must also
be idempotent, i.e. it may be called several times without side effects.
package internal
import (
	"context"
	"database/sql"
	"fmt"
	"time"
	"github.com/cenkalti/backoff"
)
func Run(ctx context.Context, db *sql.DB, fn func(context.Context) error) (err error) {
	defer func() {
		if rerr := recover(); rerr != nil {
			err = fmt.Errorf("%v", rerr)
		}
	}()
	return fn(ctx)
}
func RunWithRetry(ctx context.Context, db *sql.DB, fn func(context.Context) error, retryable func(error) bool) (err error) {
	return RunWithRetryBackoff(
		ctx,
		db,
		fn,
		retryable,
		backoff.NewExponentialBackOff(),  
	)
}
func RunWithRetryBackoff(ctx context.Context, db *sql.DB, fn func(context.Context) error, retryable func(error) bool, b backoff.BackOff) (err error) {
	b.Reset()
	for {
		if err = Run(ctx, db, fn); err == nil {
			return nil
		}
		if retryable != nil && !retryable(err) {
			return err
		}
		delay := b.NextBackOff()
		if delay == backoff.Stop {
			return err
		}
		time.Sleep(delay)
	}
}
func RunInTx(ctx context.Context, db *sql.DB, fn func(context.Context, *sql.Tx) error) (err error) {
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	defer func() {
		if rerr := recover(); rerr != nil {
			err = fmt.Errorf("%v", rerr)
			_ = tx.Rollback()
		}
	}()
	if err = fn(ctx, tx); err != nil {
		_ = tx.Rollback()
		return err
	}
	err = tx.Commit()
	return err
}