]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/google.golang.org/appengine/datastore/transaction.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / google.golang.org / appengine / datastore / transaction.go
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 readOnly := false
62 if opts != nil {
63 readOnly = opts.ReadOnly
64 }
65 attempts := 3
66 if opts != nil && opts.Attempts > 0 {
67 attempts = opts.Attempts
68 }
69 var t *pb.Transaction
70 var err error
71 for i := 0; i < attempts; i++ {
72 if t, err = internal.RunTransactionOnce(c, f, xg, readOnly, t); err != internal.ErrConcurrentTransaction {
73 return err
74 }
75 }
76 return ErrConcurrentTransaction
77 }
78
79 // TransactionOptions are the options for running a transaction.
80 type TransactionOptions struct {
81 // XG is whether the transaction can cross multiple entity groups. In
82 // comparison, a single group transaction is one where all datastore keys
83 // used have the same root key. Note that cross group transactions do not
84 // have the same behavior as single group transactions. In particular, it
85 // is much more likely to see partially applied transactions in different
86 // entity groups, in global queries.
87 // It is valid to set XG to true even if the transaction is within a
88 // single entity group.
89 XG bool
90 // Attempts controls the number of retries to perform when commits fail
91 // due to a conflicting transaction. If omitted, it defaults to 3.
92 Attempts int
93 // ReadOnly controls whether the transaction is a read only transaction.
94 // Read only transactions are potentially more efficient.
95 ReadOnly bool
96 }