diff --git a/caching/aggregates_cache.go b/caching/aggregates_cache.go index 5bffc1ae9..d217df106 100644 --- a/caching/aggregates_cache.go +++ b/caching/aggregates_cache.go @@ -30,7 +30,7 @@ type AggregatesCache interface { InitCacheStorage(cfg.Chains) GetAggregatesFeesAndUpdate(map[string]cfg.Chain, *utils.Connections, string, time.Time, time.Time, string) error GetAggregatesAndUpdate(map[string]cfg.Chain, *utils.Connections, string, time.Time, time.Time, string) error - UpdateStatistics(*utils.Connections) error + UpdateStatistics(*utils.Connections, map[string]cfg.Chain) error } type aggregatesCache struct { @@ -454,7 +454,7 @@ func (ac *aggregatesCache) GetAggregatesFeesAndUpdate(chains map[string]cfg.Chai return nil } -func (ac *aggregatesCache) UpdateStatistics(conn *utils.Connections) error { +func (ac *aggregatesCache) UpdateStatistics(conn *utils.Connections, chains map[string]cfg.Chain) error { dbRunner, err := conn.DB().NewSession("update_statistics", cfg.RequestTimeout) if err != nil { return err @@ -462,12 +462,12 @@ func (ac *aggregatesCache) UpdateStatistics(conn *utils.Connections) error { var latestResults []models.StatisticsCache // Get the max Date from table statistics to use it in Latest Transactions querys maxDate := getMaxCacheDate(dbRunner) - latestResults = getLatestTransactionsInfo(dbRunner, maxDate) + latestResults = getLatestTransactionsInfo(dbRunner, maxDate, chains) updateStatisticsCacheInfo(dbRunner, latestResults) return nil } -func getLatestTransactionsInfo(dbRunner *dbr.Session, maxDate time.Time) []models.StatisticsCache { +func getLatestTransactionsInfo(dbRunner *dbr.Session, maxDate time.Time, chains map[string]cfg.Chain) []models.StatisticsCache { var transactionsCache []models.StatisticsCache // Get statistics values from cvm transactions txData: total number of transactions, total token transfer @@ -476,12 +476,15 @@ func getLatestTransactionsInfo(dbRunner *dbr.Session, maxDate time.Time) []model cvmTransactions := getLatestCvmTransactions(dbRunner, maxDate) // Get statistics values from avm transactions: total number of transactions - avmTransactions := getLatestAvmTransactions(dbRunner, maxDate) + avmTransactions := getLatestAvmTransactions(dbRunner, maxDate, chains) // Get statistics values from cvm blocks: avg block size cvmBlocks := getLatestCvmBlocks(dbRunner, maxDate) - transactionsCache = utils.UnionStatistics(cvmTransactions, cvmBlocks, avmTransactions) + // Get address from and address to cache from cvm_transactions_txdata + addressesFrom, addressesTo := getLatestAddressActive(dbRunner, maxDate) + + transactionsCache = utils.UnionStatistics(cvmTransactions, cvmBlocks, avmTransactions, addressesFrom, addressesTo) return transactionsCache } @@ -566,13 +569,21 @@ func getLatestCvmTransactions(dbRunner *dbr.Session, maxDate time.Time) []*model return cvmLatestTransactions } -func getLatestAvmTransactions(dbRunner *dbr.Session, maxDate time.Time) []*models.AvmStatisticsCache { +func getLatestAvmTransactions(dbRunner *dbr.Session, maxDate time.Time, chains map[string]cfg.Chain) []*models.AvmStatisticsCache { avmLatestTransactions := []*models.AvmStatisticsCache{} + chainIds := []string{} + + for _, test := range chains { + if test.VMType != "cvm" { + chainIds = append(chainIds, test.ID) + } + } _, err := dbRunner. Select("DATE(created_at) as date_at", "COUNT(*) as avm_tx"). From("avm_transactions"). Where("DATE(created_at) >= ?", maxDate.Format(time.RFC3339)). + Where("avm_transactions.chain_id IN ?", chainIds). GroupBy("DATE(created_at)"). Load(&avmLatestTransactions) @@ -597,6 +608,28 @@ func getLatestCvmBlocks(dbRunner *dbr.Session, maxDate time.Time) []*models.CvmB return cvmLatestBlocks } +func getLatestAddressActive(dbRunner *dbr.Session, maxDate time.Time) ([]*models.AddressesCache, []*models.AddressesCache) { + addressFrom := []*models.AddressesCache{} + addressTo := []*models.AddressesCache{} + _, _ = dbRunner.Select("distinct(id_from_addr) as address", "date(created_at) as date_at"). + From("cvm_transactions_txdata"). + Where("DATE(created_at) >= ?", maxDate.Format(time.RFC3339)). + OrderBy("date_at ASC"). + Load(&addressFrom) + + _, err := dbRunner.Select("distinct(id_to_addr) as address", "date(created_at) as date_at"). + From("cvm_transactions_txdata"). + Where("DATE(created_at) >= ?", maxDate.Format(time.RFC3339)). + OrderBy("date_at ASC"). + Load(&addressTo) + + if err != nil { + return []*models.AddressesCache{}, []*models.AddressesCache{} + } + + return addressFrom, addressTo +} + func getFirstTransactionTime(conns *utils.Connections, chainIDs []string) (time.Time, error) { dbRunner, err := conns.DB().NewSession("get_first_transaction_time", cfg.RequestTimeout) if err != nil { diff --git a/models/collections.go b/models/collections.go index d508ab32a..9fa716190 100644 --- a/models/collections.go +++ b/models/collections.go @@ -388,6 +388,11 @@ type CvmBlocksStatisticsCache struct { AvgBlockSize float32 `json:"avgBlockSize"` } +type AddressesCache struct { + Address string `json:"address"` + DateAt string `json:"dateAt"` +} + /******************* Merging ***********************/ type AggregateMerge interface { diff --git a/servicesctrl/services_control.go b/servicesctrl/services_control.go index 6576f9ef5..90f459e39 100644 --- a/servicesctrl/services_control.go +++ b/servicesctrl/services_control.go @@ -158,7 +158,7 @@ func (s *Control) StartStatisticsScheduler(config *cfg.Config) error { for range MyTimer.C { MyTimer.Stop() - _ = s.AggregatesCache.UpdateStatistics(connections) + _ = s.AggregatesCache.UpdateStatistics(connections, config.Chains) MyTimer.Reset(time.Duration(config.CacheStatisticsInterval) * time.Hour) } return nil diff --git a/utils/blockchain_statistics.go b/utils/blockchain_statistics.go index e145c34c2..cdc8d39a8 100644 --- a/utils/blockchain_statistics.go +++ b/utils/blockchain_statistics.go @@ -9,12 +9,15 @@ import ( func UnionStatistics( cvmLatestTx []*models.CvmStatisticsCache, cvmLatestBlocks []*models.CvmBlocksStatisticsCache, - avmLatestTx []*models.AvmStatisticsCache) []models.StatisticsCache { + avmLatestTx []*models.AvmStatisticsCache, + addressesFrom []*models.AddressesCache, + addressesTo []*models.AddressesCache) []models.StatisticsCache { statisticsCache := []models.StatisticsCache{} // set all the information from cvmTx in statisticsCache variable setCvmTxStatistics(&statisticsCache, cvmLatestTx) setCvmBlockStatistics(&statisticsCache, cvmLatestBlocks) setAvmTxStatistics(&statisticsCache, avmLatestTx) + setActiveAddressStatistics(&statisticsCache, addressesFrom, addressesTo) return statisticsCache } @@ -23,15 +26,14 @@ func setCvmTxStatistics(statistics *[]models.StatisticsCache, cvmLatestTx []*mod dateAt := strings.Split(cvmTx.DateAt, "T")[0] *statistics = append(*statistics, models.StatisticsCache{ - DateAt: dateAt, - CvmTx: cvmTx.CvmTx, - ReceiveCount: cvmTx.ReceiveCount, - SendCount: cvmTx.SendCount, - ActiveAccounts: cvmTx.ActiveAccounts, - Blocks: cvmTx.Blocks, - GasPrice: cvmTx.GasPrice, - GasUsed: cvmTx.GasUsed, - TokenTransfer: cvmTx.TokenTransfer, + DateAt: dateAt, + CvmTx: cvmTx.CvmTx, + ReceiveCount: cvmTx.ReceiveCount, + SendCount: cvmTx.SendCount, + Blocks: cvmTx.Blocks, + GasPrice: cvmTx.GasPrice, + GasUsed: cvmTx.GasUsed, + TokenTransfer: cvmTx.TokenTransfer, }) } } @@ -76,3 +78,32 @@ func getLatestTxIndex(statistics *[]models.StatisticsCache, date string) int { } return -1 } + +func getActiveAddresses(addressesFrom []*models.AddressesCache, addressesTo []*models.AddressesCache) []*models.AddressesCache { + unionActive := addressesFrom + for _, address := range addressesTo { + if getLatestAddrIndex(unionActive, address.Address, address.DateAt) < 0 { + unionActive = append(unionActive, address) + } + } + return unionActive +} + +func setActiveAddressStatistics(statistics *[]models.StatisticsCache, addressesFrom []*models.AddressesCache, addressesTo []*models.AddressesCache) { + union := getActiveAddresses(addressesFrom, addressesTo) + for _, Addr := range union { + idx := getLatestTxIndex(statistics, strings.Split(Addr.DateAt, "T")[0]) + if idx > 0 { + (*statistics)[idx].ActiveAccounts++ + } + } +} + +func getLatestAddrIndex(addresses []*models.AddressesCache, addressTo string, date string) int { + for idx, address := range addresses { + if address.DateAt == date && address.Address == addressTo { + return idx + } + } + return -1 +}