github.com/aychain/blockbook@v0.1.1-0.20181121092459-6d1fc7e07c5b/db/txcache.go (about)

     1  package db
     2  
     3  import (
     4  	"blockbook/bchain"
     5  	"blockbook/common"
     6  
     7  	"github.com/golang/glog"
     8  )
     9  
    10  // TxCache is handle to TxCacheServer
    11  type TxCache struct {
    12  	db      *RocksDB
    13  	chain   bchain.BlockChain
    14  	metrics *common.Metrics
    15  	is      *common.InternalState
    16  	enabled bool
    17  }
    18  
    19  // NewTxCache creates new TxCache interface and returns its handle
    20  func NewTxCache(db *RocksDB, chain bchain.BlockChain, metrics *common.Metrics, is *common.InternalState, enabled bool) (*TxCache, error) {
    21  	if !enabled {
    22  		glog.Info("txcache: disabled")
    23  	}
    24  	return &TxCache{
    25  		db:      db,
    26  		chain:   chain,
    27  		metrics: metrics,
    28  		is:      is,
    29  		enabled: enabled,
    30  	}, nil
    31  }
    32  
    33  // GetTransaction returns transaction either from RocksDB or if not present from blockchain
    34  // it the transaction is confirmed, it is stored in the RocksDB
    35  func (c *TxCache) GetTransaction(txid string) (*bchain.Tx, uint32, error) {
    36  	var tx *bchain.Tx
    37  	var h uint32
    38  	var err error
    39  	if c.enabled {
    40  		tx, h, err = c.db.GetTx(txid)
    41  		if err != nil {
    42  			return nil, 0, err
    43  		}
    44  		if tx != nil {
    45  			// number of confirmations is not stored in cache, they change all the time
    46  			_, bestheight, _ := c.is.GetSyncState()
    47  			tx.Confirmations = bestheight - h + 1
    48  			c.metrics.TxCacheEfficiency.With(common.Labels{"status": "hit"}).Inc()
    49  			return tx, h, nil
    50  		}
    51  	}
    52  	tx, err = c.chain.GetTransaction(txid)
    53  	if err != nil {
    54  		return nil, 0, err
    55  	}
    56  	c.metrics.TxCacheEfficiency.With(common.Labels{"status": "miss"}).Inc()
    57  	// cache only confirmed transactions
    58  	if tx.Confirmations > 0 {
    59  		ta, err := c.db.GetTxAddresses(txid)
    60  		if err != nil {
    61  			return nil, 0, err
    62  		}
    63  		// the transaction may me not yet indexed, in that case get the height from the backend
    64  		if ta == nil {
    65  			h, err = c.chain.GetBestBlockHeight()
    66  			if err != nil {
    67  				return nil, 0, err
    68  			}
    69  		} else {
    70  			h = ta.Height
    71  		}
    72  		if c.enabled {
    73  			err = c.db.PutTx(tx, h, tx.Blocktime)
    74  			// do not return caching error, only log it
    75  			if err != nil {
    76  				glog.Error("PutTx error ", err)
    77  			}
    78  		}
    79  	} else {
    80  		h = 0
    81  	}
    82  	return tx, h, nil
    83  }