Skip to content

Commit

Permalink
Fixed total coins dates generation. Total coins cache update 1 time p…
Browse files Browse the repository at this point in the history
…er day (#193)

Truncate(parent) values are used for total coin dates. Added history
generation delta check for total coins dates generation (if delta wasn't
passed -> get dates without today date, but add 1 extra day for endpoint
results consistency). Update total coins cache 1 time per day instead of
hourly as we have history generation per day format now.
  • Loading branch information
ice-myles authored Jul 9, 2024
1 parent 885340e commit c4ee083
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 20 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/ethereum/go-ethereum v1.14.6
github.com/goccy/go-json v0.10.3
github.com/hashicorp/go-multierror v1.1.1
github.com/ice-blockchain/eskimo v1.365.0
github.com/ice-blockchain/eskimo v1.366.0
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb
github.com/ice-blockchain/wintr v1.144.0
github.com/imroc/req/v3 v3.43.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ice-blockchain/eskimo v1.365.0 h1:0J8z7YX09dM1mrobwsAlC4S170CJriKZkKrl+5VpB+0=
github.com/ice-blockchain/eskimo v1.365.0/go.mod h1:c2Yp7QwFzJvdrcbZSOmM4jY/Li6Wbo1LVnoouJrAe8g=
github.com/ice-blockchain/eskimo v1.366.0 h1:brqw1rVWXhn7vtYUqzb8HguzjenMc9CSeYxbdidrBwk=
github.com/ice-blockchain/eskimo v1.366.0/go.mod h1:c2Yp7QwFzJvdrcbZSOmM4jY/Li6Wbo1LVnoouJrAe8g=
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb h1:8TnFP3mc7O+tc44kv2e0/TpZKnEVUaKH+UstwfBwRkk=
github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb/go.mod h1:ZsQU7i3mxhgBBu43Oev7WPFbIjP4TniN/b1UPNGbrq8=
github.com/ice-blockchain/wintr v1.144.0 h1:YQE0olkPdSI6AOlw7r/j5jGI6uLciZQrvXFIkN4C4l4=
Expand Down
32 changes: 20 additions & 12 deletions tokenomics/balance_total_coins.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (r *repository) GetTotalCoinsSummary(ctx context.Context, days uint64, utcO
break
}
}
child.Date = child.Date.Add(-stdlibtime.Duration(utcOffset.Seconds()) * stdlibtime.Second).In(location).Add(-1 * stdlibtime.Nanosecond)
child.Date = child.Date.Add(-stdlibtime.Duration(utcOffset.Seconds()) * stdlibtime.Second).In(location)
}
details, err := r.loadCachedBlockchainDetails(ctx)
if err != nil {
Expand Down Expand Up @@ -79,16 +79,24 @@ func (r *repository) loadCachedBlockchainDetails(ctx context.Context) (*Blockcha

func (r *repository) totalCoinsDates(now *time.Time, days uint64) ([]stdlibtime.Time, []*TotalCoinsTimeSeriesDataPoint) {
var (
truncationInterval = r.cfg.GlobalAggregationInterval.Child
dates = make([]stdlibtime.Time, 0, days)
timeSeries = make([]*TotalCoinsTimeSeriesDataPoint, 0, days)
dayInterval = r.cfg.GlobalAggregationInterval.Parent
start = now.Add(-1 * truncationInterval).Truncate(truncationInterval)
dates = make([]stdlibtime.Time, 0, days)
timeSeries = make([]*TotalCoinsTimeSeriesDataPoint, 0, days)
dayInterval = r.cfg.GlobalAggregationInterval.Parent
historyGenerationDelta = stdlibtime.Duration(float64(r.cfg.GlobalAggregationInterval.Child) * 0.75) //nolint:gomnd // .
notPassedHistoryGenerationDelta = false
)
dates = append(dates, start)
timeSeries = append(timeSeries, &TotalCoinsTimeSeriesDataPoint{Date: start})
for day := uint64(0); day < days-1; day++ {
for day := uint64(0); day < days; day++ {
date := now.Add(dayInterval * -1 * stdlibtime.Duration(day)).Truncate(dayInterval)
if now.Truncate(dayInterval).Equal(date) && now.Sub(date) < historyGenerationDelta {
notPassedHistoryGenerationDelta = true

continue
}
dates = append(dates, date)
timeSeries = append(timeSeries, &TotalCoinsTimeSeriesDataPoint{Date: date})
}
if notPassedHistoryGenerationDelta {
date := now.Add(dayInterval * -1 * stdlibtime.Duration(days)).Truncate(dayInterval)
dates = append(dates, date)
timeSeries = append(timeSeries, &TotalCoinsTimeSeriesDataPoint{Date: date})
}
Expand Down Expand Up @@ -200,22 +208,22 @@ func (r *repository) keepBlockchainDetailsCacheUpdated(ctx context.Context) {
}
}

func (r *repository) keepTotalCoinsCacheUpdated(ctx context.Context, initialNow *time.Time) {
func (r *repository) keepTotalCoinsCacheUpdated(ctx context.Context) {
ticker := stdlibtime.NewTicker(stdlibtime.Duration(1+rand.Intn(10)) * (r.cfg.GlobalAggregationInterval.Child / 60)) //nolint:gosec,gomnd // Not an issue.
defer ticker.Stop()
for {
select {
case <-ticker.C:
var (
now = time.Now()
newDate = now.Truncate(r.cfg.GlobalAggregationInterval.Child)
newDate = now.Truncate(r.cfg.GlobalAggregationInterval.Parent)
historyGenerationDelta = stdlibtime.Duration(float64(r.cfg.GlobalAggregationInterval.Child) * 0.75) //nolint:gomnd // .
)
lastDateCached, err := r.getLastDateCached(ctx)
if err != nil {
log.Error(errors.Wrapf(err, "failed to get last date cached"))
}
if lastDateCached.IsNil() || (!lastDateCached.Equal(newDate) && now.Sub(newDate) >= historyGenerationDelta) {
if lastDateCached.IsNil() || (!lastDateCached.Truncate(r.cfg.GlobalAggregationInterval.Parent).Equal(newDate) && now.Sub(newDate) >= historyGenerationDelta) {
dwhCtx, cancel := context.WithTimeout(ctx, 1*stdlibtime.Minute)
lock, err := redislock.Obtain(dwhCtx, r.db, totalCoinStatsCacheLockKey, totalCoinStatsCacheLockDuration, &redislock.Options{RetryStrategy: redislock.NoRetry()})
if err != nil && errors.Is(err, redislock.ErrNotObtained) {
Expand Down
112 changes: 109 additions & 3 deletions tokenomics/balance_total_coins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ package tokenomics
import (
"context"
"testing"
"time"
stdlibtime "time"

"github.com/hashicorp/go-multierror"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

appCfg "github.com/ice-blockchain/wintr/config"
"github.com/ice-blockchain/wintr/connectors/storage/v3"
"github.com/ice-blockchain/wintr/time"
)

func helperCreateRepoWithRedisOnly(t *testing.T) *repository {
Expand Down Expand Up @@ -60,10 +62,10 @@ func TestGetCoinStatsBlockchainDetails(t *testing.T) {
})

t.Run("FillFromKeeper", func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ctx, cancel := context.WithTimeout(context.Background(), stdlibtime.Second*2)
defer cancel()

repo.cfg.DetailedCoinMetrics.RefreshInterval = time.Minute
repo.cfg.DetailedCoinMetrics.RefreshInterval = stdlibtime.Minute
repo.keepBlockchainDetailsCacheUpdated(ctx)
})

Expand All @@ -83,3 +85,107 @@ func TestGetCoinStatsBlockchainDetails(t *testing.T) {

require.NoError(t, repo.Close())
}

func TestTotalCoinsDates_HistoryGenerationDeltaPassed(t *testing.T) {
t.Parallel()

var cfg Config
appCfg.MustLoadFromKey(applicationYamlKey, &cfg)
cfg.GlobalAggregationInterval.Parent = 24 * stdlibtime.Hour
cfg.GlobalAggregationInterval.Child = 1 * stdlibtime.Hour
repo := &repository{cfg: &cfg}

now := time.New(stdlibtime.Date(2023, 7, 9, 5, 15, 10, 1, stdlibtime.UTC))
dates, timeSeries := repo.totalCoinsDates(now, 7)
assert.Equal(t, []stdlibtime.Time{
now.Truncate(cfg.GlobalAggregationInterval.Parent),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-1 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-2 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-3 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-4 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-5 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-6 * 24 * stdlibtime.Hour),
}, dates)
assert.Equal(t, []*TotalCoinsTimeSeriesDataPoint{
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-1 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-2 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-3 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-4 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-5 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-6 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
}, timeSeries)
}

func TestTotalCoinsDates_HistoryGenerationDeltaNotPassed(t *testing.T) {
t.Parallel()

var cfg Config
appCfg.MustLoadFromKey(applicationYamlKey, &cfg)
cfg.GlobalAggregationInterval.Parent = 24 * stdlibtime.Hour
cfg.GlobalAggregationInterval.Child = 1 * stdlibtime.Hour
repo := &repository{cfg: &cfg}

now := time.New(stdlibtime.Date(2023, 7, 9, 0, 15, 10, 1, stdlibtime.UTC))
dates, timeSeries := repo.totalCoinsDates(now, 7)
assert.Equal(t, []stdlibtime.Time{
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-1 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-2 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-3 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-4 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-5 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-6 * 24 * stdlibtime.Hour),
now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-7 * 24 * stdlibtime.Hour),
}, dates)
assert.Equal(t, []*TotalCoinsTimeSeriesDataPoint{
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-1 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-2 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-3 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-4 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-5 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-6 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
{
Date: now.Truncate(cfg.GlobalAggregationInterval.Parent).Add(-7 * 24 * stdlibtime.Hour),
TotalCoins: TotalCoins{Total: 0., Blockchain: 0., Standard: 0., PreStaking: 0.},
},
}, timeSeries)
}
4 changes: 2 additions & 2 deletions tokenomics/tokenomics.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func New(ctx context.Context, _ context.CancelFunc) Repository {
now := time.Now()
repo.mustInitTotalCoinsCache(ctx, now)

go repo.keepTotalCoinsCacheUpdated(ctx, now)
go repo.keepTotalCoinsCacheUpdated(ctx)
go repo.keepBlockchainDetailsCacheUpdated(ctx)

return repo
Expand Down Expand Up @@ -88,7 +88,7 @@ func StartProcessor(ctx context.Context, cancel context.CancelFunc) Processor {
now := time.Now()
prc.mustInitTotalCoinsCache(ctx, now)

go prc.keepTotalCoinsCacheUpdated(ctx, now)
go prc.keepTotalCoinsCacheUpdated(ctx)
go prc.keepBlockchainDetailsCacheUpdated(ctx)
prc.extraBonusStartDate = extrabonusnotifier.MustGetExtraBonusStartDate(ctx, prc.db)
prc.extraBonusIndicesDistribution = extrabonusnotifier.MustGetExtraBonusIndicesDistribution(ctx, prc.db)
Expand Down

0 comments on commit c4ee083

Please sign in to comment.