github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/google.golang.org/appengine/datastore/transaction.go (about)

     1  // Copyright 2011 Google Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package datastore
     6  
     7  import (
     8  	"errors"
     9  
    10  	"golang.org/x/net/context"
    11  
    12  	"google.golang.org/appengine/internal"
    13  	pb "google.golang.org/appengine/internal/datastore"
    14  )
    15  
    16  func init() {
    17  	internal.RegisterTransactionSetter(func(x *pb.Query, t *pb.Transaction) {
    18  		x.Transaction = t
    19  	})
    20  	internal.RegisterTransactionSetter(func(x *pb.GetRequest, t *pb.Transaction) {
    21  		x.Transaction = t
    22  	})
    23  	internal.RegisterTransactionSetter(func(x *pb.PutRequest, t *pb.Transaction) {
    24  		x.Transaction = t
    25  	})
    26  	internal.RegisterTransactionSetter(func(x *pb.DeleteRequest, t *pb.Transaction) {
    27  		x.Transaction = t
    28  	})
    29  }
    30  
    31  // ErrConcurrentTransaction is returned when a transaction is rolled back due
    32  // to a conflict with a concurrent transaction.
    33  var ErrConcurrentTransaction = errors.New("datastore: concurrent transaction")
    34  
    35  // RunInTransaction runs f in a transaction. It calls f with a transaction
    36  // context tc that f should use for all App Engine operations.
    37  //
    38  // If f returns nil, RunInTransaction attempts to commit the transaction,
    39  // returning nil if it succeeds. If the commit fails due to a conflicting
    40  // transaction, RunInTransaction retries f, each time with a new transaction
    41  // context. It gives up and returns ErrConcurrentTransaction after three
    42  // failed attempts. The number of attempts can be configured by specifying
    43  // TransactionOptions.Attempts.
    44  //
    45  // If f returns non-nil, then any datastore changes will not be applied and
    46  // RunInTransaction returns that same error. The function f is not retried.
    47  //
    48  // Note that when f returns, the transaction is not yet committed. Calling code
    49  // must be careful not to assume that any of f's changes have been committed
    50  // until RunInTransaction returns nil.
    51  //
    52  // Since f may be called multiple times, f should usually be idempotent.
    53  // datastore.Get is not idempotent when unmarshaling slice fields.
    54  //
    55  // Nested transactions are not supported; c may not be a transaction context.
    56  func RunInTransaction(c context.Context, f func(tc context.Context) error, opts *TransactionOptions) error {
    57  	xg := false
    58  	if opts != nil {
    59  		xg = opts.XG
    60  	}
    61  	attempts := 3
    62  	if opts != nil && opts.Attempts > 0 {
    63  		attempts = opts.Attempts
    64  	}
    65  	for i := 0; i < attempts; i++ {
    66  		if err := internal.RunTransactionOnce(c, f, xg); err != internal.ErrConcurrentTransaction {
    67  			return err
    68  		}
    69  	}
    70  	return ErrConcurrentTransaction
    71  }
    72  
    73  // TransactionOptions are the options for running a transaction.
    74  type TransactionOptions struct {
    75  	// XG is whether the transaction can cross multiple entity groups. In
    76  	// comparison, a single group transaction is one where all datastore keys
    77  	// used have the same root key. Note that cross group transactions do not
    78  	// have the same behavior as single group transactions. In particular, it
    79  	// is much more likely to see partially applied transactions in different
    80  	// entity groups, in global queries.
    81  	// It is valid to set XG to true even if the transaction is within a
    82  	// single entity group.
    83  	XG bool
    84  	// Attempts controls the number of retries to perform when commits fail
    85  	// due to a conflicting transaction. If omitted, it defaults to 3.
    86  	Attempts int
    87  }