-
Notifications
You must be signed in to change notification settings - Fork 0
/
transaction.go
45 lines (37 loc) · 1.2 KB
/
transaction.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package nds
import (
"sync"
"golang.org/x/net/context"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine/memcache"
)
var transactionKey = "used for *transaction"
type transaction struct {
sync.Mutex
lockMemcacheItems []*memcache.Item
}
func transactionFromContext(c context.Context) (*transaction, bool) {
tx, ok := c.Value(&transactionKey).(*transaction)
return tx, ok
}
// RunInTransaction works just like datastore.RunInTransaction however it
// interacts correctly with memcache. You should always use this method for
// transactions if you are using the NDS package.
func RunInTransaction(c context.Context, f func(tc context.Context) error,
opts *datastore.TransactionOptions) error {
return datastore.RunInTransaction(c, func(tc context.Context) error {
tx := &transaction{}
tc = context.WithValue(tc, &transactionKey, tx)
if err := f(tc); err != nil {
return err
}
// tx.Unlock() is not called as the tx context should never be called
//again so we rather block than allow people to misuse the context.
tx.Lock()
memcacheCtx, err := memcacheContext(tc)
if err != nil {
return err
}
return memcacheSetMulti(memcacheCtx, tx.lockMemcacheItems)
}, opts)
}