blob: 84156bd4f38533a139b8f5cc4e7ab19baea343db [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syncbase
import (
"v.io/v23/context"
wire "v.io/v23/services/syncbase"
"v.io/v23/verror"
)
func newBatch(parentFullName string, id wire.Id, batchHandle wire.BatchHandle) *batch {
if batchHandle == "" {
panic("batch must have non-empty handle")
}
return &batch{databaseBatch: *newDatabaseBatch(parentFullName, id, batchHandle)}
}
type batch struct {
databaseBatch
}
var _ BatchDatabase = (*batch)(nil)
// Commit implements BatchDatabase.Commit.
func (b *batch) Commit(ctx *context.T) error {
return b.c.Commit(ctx, b.bh)
}
// Abort implements BatchDatabase.Abort.
func (b *batch) Abort(ctx *context.T) error {
return b.c.Abort(ctx, b.bh)
}
// RunInBatch runs the given fn in a batch, managing retries and commit/abort.
// Writable batches are committed, retrying if commit fails. Readonly batches
// are aborted.
func RunInBatch(ctx *context.T, d Database, opts wire.BatchOptions, fn func(b BatchDatabase) error) error {
attemptInBatch := func() error {
b, err := d.BeginBatch(ctx, opts)
if err != nil {
return err
}
// Use defer for Abort to make sure it gets called in case fn panics.
commitCalled := false
defer func() {
if !commitCalled {
b.Abort(ctx)
}
}()
if err = fn(b); err != nil {
return err
}
// A readonly batch should be Aborted; Commit would fail.
if opts.ReadOnly {
return nil
}
// Commit is about to be called, do not call Abort.
commitCalled = true
return b.Commit(ctx)
}
var err error
// TODO(sadovsky): Make the number of attempts configurable.
for i := 0; i < 3; i++ {
// TODO(sadovsky): Commit() can fail for a number of reasons, e.g. RPC
// failure or ErrConcurrentTransaction. Depending on the cause of failure,
// it may be desirable to retry the Commit() and/or to call Abort().
if err = attemptInBatch(); verror.ErrorID(err) != wire.ErrConcurrentBatch.ID {
return err
}
}
return err
}