github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/kv/kv.go (about)

     1  // Copyright 2022 zGraph Authors. All rights reserved.
     2  //
     3  // Copyright 2015 PingCAP, Inc.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package kv
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/pingcap/errors"
    23  )
    24  
    25  // Pair represents a key/value pair.
    26  type Pair struct {
    27  	Key Key
    28  	Val []byte
    29  }
    30  
    31  const retry = 5
    32  
    33  // TxnContext creates a new transaction and call the user-define transaction callback.
    34  // The transaction will be committed automatically.
    35  func TxnContext(ctx context.Context, store Storage, fn func(ctx context.Context, txn Transaction) error) error {
    36  	txn, err := store.Begin()
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	for i := 0; i < retry; i++ {
    42  		err := fn(ctx, txn)
    43  		if err != nil {
    44  			if IsRetryable(err) {
    45  				continue
    46  			}
    47  			return err
    48  		}
    49  		err = txn.Commit(ctx)
    50  		if err == nil {
    51  			return nil
    52  		}
    53  		if !IsRetryable(err) {
    54  			return err
    55  		}
    56  	}
    57  
    58  	return nil
    59  }
    60  
    61  // Txn creates a new transaction and call the user-define transaction callback.
    62  func Txn(store Storage, fn func(txn Transaction) error) error {
    63  	return TxnContext(context.Background(), store, func(ctx context.Context, txn Transaction) error {
    64  		return fn(txn)
    65  	})
    66  }
    67  
    68  // IsRetryable reports whether an error retryable.
    69  func IsRetryable(err error) bool {
    70  	err = errors.Cause(err)
    71  	if err == nil {
    72  		return false
    73  	}
    74  	return err == ErrTxnConflicts
    75  }