github.com/okex/exchain@v1.8.0/libs/tendermint/delta/redis-cgi/cgi.go (about)

     1  package redis_cgi
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/go-redis/redis/v8"
     7  	"github.com/okex/exchain/libs/tendermint/libs/log"
     8  	"github.com/okex/exchain/libs/tendermint/types"
     9  	"sync"
    10  	"time"
    11  )
    12  
    13  const (
    14  	lockerExpire = 4 * time.Second
    15  )
    16  
    17  var (
    18  	mostRecentHeightKey string
    19  	deltaLockerKey      string
    20  )
    21  
    22  var once sync.Once
    23  
    24  // init initialize the mostRecentHeightKey and deltaLockerKey
    25  // the keys are based types.DeltaVersion, which can specified by user.
    26  func (r *RedisClient) init() {
    27  	const (
    28  		mostRecentHeight = "MostRecentHeight"
    29  		deltaLocker      = "DeltaLocker"
    30  	)
    31  	once.Do(func() {
    32  		mostRecentHeightKey = fmt.Sprintf("dds:%d:%s", types.DeltaVersion, mostRecentHeight)
    33  		deltaLockerKey = fmt.Sprintf("dds:%d:%s", types.DeltaVersion, deltaLocker)
    34  	})
    35  }
    36  
    37  type RedisClient struct {
    38  	rdb    *redis.Client
    39  	ttl    time.Duration
    40  	logger log.Logger
    41  }
    42  
    43  func NewRedisClient(url, auth string, ttl time.Duration, db int, l log.Logger) *RedisClient {
    44  	rdb := redis.NewClient(&redis.Options{
    45  		Addr:     url,
    46  		Password: auth, // no password set
    47  		DB:       db,   // use select DB
    48  	})
    49  	redisClient := RedisClient{rdb, ttl, l}
    50  	redisClient.init()
    51  
    52  	return &redisClient
    53  }
    54  
    55  func (r *RedisClient) GetLocker() bool {
    56  	res, err := r.rdb.SetNX(context.Background(), deltaLockerKey, true, lockerExpire).Result()
    57  	if err != nil {
    58  		r.logger.Error("GetLocker err", err)
    59  		return false
    60  	}
    61  	return res
    62  }
    63  
    64  func (r *RedisClient) ReleaseLocker() {
    65  	_, err := r.rdb.Del(context.Background(), deltaLockerKey).Result()
    66  	if err != nil {
    67  		r.logger.Error("Failed to Release Locker", "err", err)
    68  	}
    69  }
    70  
    71  // return bool: if change the value of latest_height, need to upload
    72  func (r *RedisClient) ResetMostRecentHeightAfterUpload(targetHeight int64, upload func(int64) bool) (bool, int64, error) {
    73  	var res bool
    74  	mrh, err := r.rdb.Get(context.Background(), mostRecentHeightKey).Int64()
    75  	if err != nil && err != redis.Nil {
    76  		return res, mrh, err
    77  	}
    78  
    79  	if mrh < targetHeight && upload(mrh) {
    80  		err = r.rdb.Set(context.Background(), mostRecentHeightKey, targetHeight, 0).Err()
    81  		if err == nil {
    82  			res = true
    83  			r.logger.Info("Reset most recent height", "new-mrh", targetHeight, "old-mrh", mrh)
    84  		} else {
    85  			r.logger.Error("Failed to reset most recent height",
    86  				"target-mrh", targetHeight,
    87  				"existing-mrh", mrh, "err", err)
    88  		}
    89  	}
    90  	return res, mrh, err
    91  }
    92  
    93  func (r *RedisClient) SetBlock(height int64, bytes []byte) error {
    94  	if len(bytes) == 0 {
    95  		return fmt.Errorf("block is empty")
    96  	}
    97  	req := r.rdb.SetNX(context.Background(), genBlockKey(height), bytes, r.ttl)
    98  	return req.Err()
    99  }
   100  
   101  func (r *RedisClient) SetDeltas(height int64, bytes []byte) error {
   102  	if len(bytes) == 0 {
   103  		return fmt.Errorf("delta is empty")
   104  	}
   105  	req := r.rdb.SetNX(context.Background(), genDeltaKey(height), bytes, r.ttl)
   106  	return req.Err()
   107  }
   108  
   109  func (r *RedisClient) GetBlock(height int64) ([]byte, error) {
   110  	bytes, err := r.rdb.Get(context.Background(), genBlockKey(height)).Bytes()
   111  	if err == redis.Nil {
   112  		return nil, fmt.Errorf("get empty block")
   113  	}
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	return bytes, nil
   118  }
   119  
   120  func (r *RedisClient) GetDeltas(height int64) ([]byte, error, int64) {
   121  	mrh := r.getMostRecentHeight()
   122  	bytes, err := r.rdb.Get(context.Background(), genDeltaKey(height)).Bytes()
   123  	if err == redis.Nil {
   124  		return nil, fmt.Errorf("get empty delta"), mrh
   125  	}
   126  	return bytes, err, mrh
   127  }
   128  
   129  func (r *RedisClient) getMostRecentHeight() (mrh int64) {
   130  	mrh = -1
   131  	h, err := r.rdb.Get(context.Background(), mostRecentHeightKey).Int64()
   132  	if err == nil {
   133  		mrh = h
   134  	} else if err == redis.Nil {
   135  		mrh = 0
   136  	}
   137  	return
   138  }
   139  
   140  func genBlockKey(height int64) string {
   141  	return fmt.Sprintf("BH:%d", height)
   142  }
   143  
   144  func genDeltaKey(height int64) string {
   145  	return fmt.Sprintf("DH-%d:%d", types.DeltaVersion, height)
   146  }