timshannon / badgerhold

BadgerHold is an embeddable NoSQL store for querying Go types built on Badger
MIT License
520 stars 51 forks source link

Define actions interface #13

Open ghost opened 5 years ago

ghost commented 5 years ago

Hi, for my *sql drivers I am using the following interface:

type SqlConnection interface {
    Query(query string, args ...interface{}) (*sql.Rows, error)
    QueryRow(query string, args ...interface{}) *sql.Row
    Exec(query string, args ...interface{}) (sql.Result, error)
}

this allows me to switch between the sql database and sql transaction object, since both support these methods. Then, in my (mysql/...)driver's methods I simply call driver.conn.Query() and so on, and not care about the underlying object.

The driver has the following methods:

BeginTransaction(ctx context.Context) (Driver, error)
CommitTransaction() error
RollbackTransaction() error
InTransaction() bool

with the following implementation:

func (r *repo) BeginTransaction(ctx context.Context) (foo.Repository, error) {
    r.mx.Lock()
    defer r.mx.Unlock()

    // if we're already in transaction, keep the same instance
    if _, ok := r.conn.(driver.Tx); ok {
        return r, nil
    }

    // if we're not in transaction, create new instance
    tx, err := r.opts.db.BeginTx(ctx, nil)
    if err != nil {
        return nil, ErrOut(err)
    }

    inTx := &repo{
        conn: tx,
        opts: r.opts,
    }

    return inTx, nil
}

func (r *repo) CommitTransaction() error {
    r.mx.Lock()
    defer r.mx.Unlock()

    if tx, ok := r.conn.(driver.Tx); ok {
        err := tx.Commit()
        r.conn = r.opts.db
        return ErrOut(err)
    }

    return ErrOut(ErrNotInTx)
}

func (r *repo) RollbackTransaction() error {
    r.mx.Lock()
    defer r.mx.Unlock()

    if tx, ok := r.conn.(driver.Tx); ok {
        err := tx.Rollback()
        r.conn = r.opts.db
        return ErrOut(err)
    }

    return ErrOut(ErrNotInTx)
}

I am now trying to use this library as replacement for mysql db because I think it will work better for me due to some graph edges logic I am needing that mysql is not suitable for.

And it would be nice to be able to follow my established logic with this library instead of having to check if I have open transaction or not and switch between the direct method or the transactioned one(ie. Delete() vs TxDelete()....). so I think having an established interface in bh would take care of this nicely and I tihnk many people would find it useful.