go.mercari.io/datastore@v1.8.2/clouddatastore/transaction.go (about) 1 package clouddatastore 2 3 import ( 4 "context" 5 6 "cloud.google.com/go/datastore" 7 w "go.mercari.io/datastore" 8 "go.mercari.io/datastore/internal/shared" 9 ) 10 11 var _ w.Transaction = (*transactionImpl)(nil) 12 var _ w.Commit = (*commitImpl)(nil) 13 14 type contextTransaction struct{} 15 16 func getTx(ctx context.Context) *datastore.Transaction { 17 tx := ctx.Value(contextTransaction{}) 18 if tx != nil { 19 return tx.(*datastore.Transaction) 20 } 21 22 return nil 23 } 24 25 type transactionImpl struct { 26 client *datastoreImpl 27 cacheInfo *w.MiddlewareInfo 28 } 29 30 type commitImpl struct { 31 commit *datastore.Commit 32 } 33 34 func (tx *transactionImpl) Get(key w.Key, dst interface{}) error { 35 err := tx.GetMulti([]w.Key{key}, []interface{}{dst}) 36 if merr, ok := err.(w.MultiError); ok { 37 return merr[0] 38 } else if err != nil { 39 return err 40 } 41 42 return nil 43 } 44 45 func (tx *transactionImpl) GetMulti(keys []w.Key, dst interface{}) error { 46 cb := shared.NewCacheBridge(tx.cacheInfo, &originalClientBridgeImpl{tx.client}, &originalTransactionBridgeImpl{tx: tx}, nil, tx.client.middlewares) 47 48 err := shared.GetMultiOps(tx.client.ctx, keys, dst, func(keys []w.Key, dst []w.PropertyList) error { 49 return cb.GetMultiWithTx(tx.cacheInfo, keys, dst) 50 }) 51 52 return err 53 } 54 55 func (tx *transactionImpl) Put(key w.Key, src interface{}) (w.PendingKey, error) { 56 pKeys, err := tx.PutMulti([]w.Key{key}, []interface{}{src}) 57 if merr, ok := err.(w.MultiError); ok { 58 return nil, merr[0] 59 } else if err != nil { 60 return nil, err 61 } 62 63 return pKeys[0], nil 64 } 65 66 func (tx *transactionImpl) PutMulti(keys []w.Key, src interface{}) ([]w.PendingKey, error) { 67 cb := shared.NewCacheBridge(tx.cacheInfo, &originalClientBridgeImpl{tx.client}, &originalTransactionBridgeImpl{tx: tx}, nil, tx.client.middlewares) 68 69 _, pKeys, err := shared.PutMultiOps(tx.client.ctx, keys, src, func(keys []w.Key, src []w.PropertyList) ([]w.Key, []w.PendingKey, error) { 70 pKeys, err := cb.PutMultiWithTx(tx.cacheInfo, keys, src) 71 return nil, pKeys, err 72 }) 73 74 if err != nil { 75 return nil, err 76 } 77 78 return pKeys, nil 79 } 80 81 func (tx *transactionImpl) Delete(key w.Key) error { 82 err := tx.DeleteMulti([]w.Key{key}) 83 if merr, ok := err.(w.MultiError); ok { 84 return merr[0] 85 } else if err != nil { 86 return err 87 } 88 89 return nil 90 } 91 92 func (tx *transactionImpl) DeleteMulti(keys []w.Key) error { 93 cb := shared.NewCacheBridge(tx.cacheInfo, &originalClientBridgeImpl{tx.client}, &originalTransactionBridgeImpl{tx: tx}, nil, tx.client.middlewares) 94 95 err := shared.DeleteMultiOps(tx.client.ctx, keys, func(keys []w.Key) error { 96 return cb.DeleteMultiWithTx(tx.cacheInfo, keys) 97 }) 98 99 return err 100 } 101 102 func (tx *transactionImpl) Commit() (w.Commit, error) { 103 baseTx := getTx(tx.client.ctx) 104 if baseTx == nil { 105 return nil, nil 106 } 107 108 commit, err := baseTx.Commit() 109 if err != nil { 110 return nil, toWrapperError(err) 111 } 112 113 cb := shared.NewCacheBridge(tx.cacheInfo, &originalClientBridgeImpl{tx.client}, &originalTransactionBridgeImpl{tx: tx}, nil, tx.client.middlewares) 114 commitImpl := &commitImpl{commit} 115 err = cb.PostCommit(tx.cacheInfo, tx, commitImpl) 116 117 if err != nil { 118 return nil, err 119 } 120 121 return commitImpl, nil 122 } 123 124 func (tx *transactionImpl) Rollback() error { 125 baseTx := getTx(tx.client.ctx) 126 if tx == nil { 127 return nil 128 } 129 130 err := baseTx.Rollback() 131 if err != nil { 132 return toWrapperError(err) 133 } 134 135 cb := shared.NewCacheBridge(tx.cacheInfo, &originalClientBridgeImpl{tx.client}, &originalTransactionBridgeImpl{tx: tx}, nil, tx.client.middlewares) 136 return cb.PostRollback(tx.cacheInfo, tx) 137 } 138 139 func (tx *transactionImpl) Batch() *w.TransactionBatch { 140 return &w.TransactionBatch{Transaction: tx} 141 } 142 143 func (c *commitImpl) Key(p w.PendingKey) w.Key { 144 pk := toOriginalPendingKey(p) 145 key := c.commit.Key(pk) 146 return toWrapperKey(key) 147 }