github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/kv/txn.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package kv 15 16 import ( 17 "math" 18 "math/rand" 19 "time" 20 21 "github.com/insionng/yougam/libraries/juju/errors" 22 "github.com/insionng/yougam/libraries/ngaut/log" 23 ) 24 25 // RunInNewTxn will run the f in a new transaction environment. 26 func RunInNewTxn(store Storage, retryable bool, f func(txn Transaction) error) error { 27 var ( 28 err error 29 txn Transaction 30 ) 31 for i := 0; i < maxRetryCnt; i++ { 32 txn, err = store.Begin() 33 if err != nil { 34 log.Errorf("[kv] RunInNewTxn error - %v", err) 35 return errors.Trace(err) 36 } 37 38 err = f(txn) 39 if retryable && IsRetryableError(err) { 40 log.Warnf("[kv] Retry txn %v", txn) 41 txn.Rollback() 42 continue 43 } 44 if err != nil { 45 txn.Rollback() 46 return errors.Trace(err) 47 } 48 49 err = txn.Commit() 50 if retryable && IsRetryableError(err) { 51 log.Warnf("[kv] Retry txn %v", txn) 52 txn.Rollback() 53 BackOff(i) 54 continue 55 } 56 if err != nil { 57 return errors.Trace(err) 58 } 59 break 60 } 61 return errors.Trace(err) 62 } 63 64 var ( 65 // Max retry count in RunInNewTxn 66 maxRetryCnt = 100 67 // retryBackOffBase is the initial duration, in microsecond, a failed transaction stays dormancy before it retries 68 retryBackOffBase = 1 69 // retryBackOffCap is the max amount of duration, in microsecond, a failed transaction stays dormancy before it retries 70 retryBackOffCap = 100 71 ) 72 73 // BackOff Implements exponential backoff with full jitter. 74 // Returns real back off time in microsecond. 75 // See: http://www.awsarchitectureblog.com/2015/03/backoff.html. 76 func BackOff(attempts int) int { 77 upper := int(math.Min(float64(retryBackOffCap), float64(retryBackOffBase)*math.Pow(2.0, float64(attempts)))) 78 sleep := time.Duration(rand.Intn(upper)) * time.Millisecond 79 time.Sleep(sleep) 80 return int(sleep) 81 }