func (c *Counted) txWarp(ctx context.Context, f func(tx *Tx) error) error {
	tx, err := c.newTransaction(ctx)
	if err != nil {
		return err
	}
	defer tx.transaction.Discard()
	var commitError error
	for {
		if err := f(tx); err != nil {
			return multierr.Combine(err, commitError)
		}
		if commitError = tx.transaction.Commit(); commitError == nil {
			return nil
		}
		if err := tx.reset(c.ds); err != nil {
			return multierr.Combine(err, commitError)
		}
	}
}
txWarp handles resource management and commit retry for a transaction
package sharedforeststore
import (
	"context"
	"io"
	"strings"
	"github.com/ipfs/go-cid"
	"github.com/ipfs/go-datastore"
	"github.com/ipfs/go-datastore/query"
	"go.uber.org/multierr"
)
type DatabaseOptions struct {
	LinkDecoder LinkDecoderFunc
}
type Counted struct {
	opt DatabaseOptions
	ds  datastore.TxnDatastore
}
var _ CounterStore = (*Counted)(nil)
type Tx struct {
	context.Context
	transaction datastore.Txn
}
func NewCountedStore(ds datastore.TxnDatastore, opt *DatabaseOptions) *Counted {
	if opt == nil {
		opt = &DatabaseOptions{}
	}
	if opt.LinkDecoder == nil {
		opt.LinkDecoder = LinkDecoder
	}
	return &Counted{
		opt: *opt,
		ds:  ds,
	}
}
func (c *Counted) newTransaction(ctx context.Context) (*Tx, error) {
	if err := ctx.Err(); err != nil {
		return nil, err
	}
	tx, err := c.ds.NewTransaction(false)
	if err != nil {
		return nil, err
	}
	return &Tx{
		Context:     ctx,
		transaction: tx,
	}, err
}