Skip to content

Commit

Permalink
Fixed total coins selection: truncate(parent) values are used for tot…
Browse files Browse the repository at this point in the history
…al 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 committed Jul 9, 2024
1 parent 885340e commit a982bf5
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 a982bf5

Please sign in to comment.