storagenode/payouts: estimated payouts calculations upgraded
Added recalculations of estimated income in current month in case node joined in current month Change-Id: Iac925fd8bcf2be8f1089e5f001a01448ba7650be
This commit is contained in:
parent
1af9400a23
commit
f2be856864
@ -17,6 +17,7 @@ import (
|
||||
"storj.io/common/pb"
|
||||
"storj.io/common/storj"
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/storj/private/date"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/storagenode/payouts/estimatedpayouts"
|
||||
@ -94,15 +95,19 @@ func TestStorageNodeApi(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
now2 := time.Now().UTC()
|
||||
daysPerMonth := date.UTCEndOfMonth(now2).Day()
|
||||
|
||||
err = reputationdb.Store(ctx, reputation.Stats{
|
||||
SatelliteID: satellite.ID(),
|
||||
JoinedAt: time.Now().UTC(),
|
||||
JoinedAt: now.AddDate(0, 0, -daysPerMonth+3),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("test EstimatedPayout", func(t *testing.T) {
|
||||
// should return estimated payout for both satellites in current month and empty for previous
|
||||
url := fmt.Sprintf("%s/estimated-payout", baseURL)
|
||||
|
||||
res, err := http.Get(url)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
@ -122,7 +127,6 @@ func TestStorageNodeApi(t *testing.T) {
|
||||
PreviousMonth: estimation.PreviousMonth,
|
||||
CurrentMonthExpectations: estimation.CurrentMonthExpectations,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(expected)+"\n", string(body))
|
||||
})
|
||||
|
@ -60,20 +60,49 @@ func (pm *PayoutMonthly) SetPayout() {
|
||||
pm.Payout = RoundFloat(amount)
|
||||
}
|
||||
|
||||
// Add sums payout monthly data.
|
||||
func (pm *PayoutMonthly) Add(monthly PayoutMonthly) {
|
||||
pm.Payout += monthly.Payout
|
||||
pm.EgressRepairAuditPayout += monthly.EgressRepairAuditPayout
|
||||
pm.DiskSpacePayout += monthly.DiskSpacePayout
|
||||
pm.DiskSpace += monthly.DiskSpace
|
||||
pm.EgressBandwidth += monthly.EgressBandwidth
|
||||
pm.EgressBandwidthPayout += monthly.EgressBandwidthPayout
|
||||
pm.EgressRepairAudit += monthly.EgressRepairAudit
|
||||
pm.Held += monthly.Held
|
||||
}
|
||||
|
||||
// RoundFloat rounds float value till 2 signs after dot.
|
||||
func RoundFloat(value float64) float64 {
|
||||
return math.Round(value*100) / 100
|
||||
}
|
||||
|
||||
// SetExpectedMonth set current month expectations.
|
||||
func (estimatedPayout *EstimatedPayout) SetExpectedMonth(now time.Time) {
|
||||
daysPast := float64(now.Day()) - 1
|
||||
if daysPast < 1 {
|
||||
daysPast = 1
|
||||
// Set set's estimated payout with current/previous PayoutMonthly's data and current month expectations.
|
||||
func (estimatedPayout *EstimatedPayout) Set(current, previous PayoutMonthly, now, joinedAt time.Time) {
|
||||
estimatedPayout.CurrentMonth = current
|
||||
estimatedPayout.PreviousMonth = previous
|
||||
|
||||
daysSinceJoined := now.Sub(joinedAt).Hours() / 24
|
||||
daysPerMonth := float64(date.UTCEndOfMonth(now).Day())
|
||||
|
||||
if daysSinceJoined >= float64(now.Day()) {
|
||||
daysPast := float64(now.Day()) - 1
|
||||
if daysPast < 1 {
|
||||
daysPast = 1
|
||||
}
|
||||
|
||||
payoutPerDay := estimatedPayout.CurrentMonth.Payout / daysPast
|
||||
|
||||
estimatedPayout.CurrentMonthExpectations += payoutPerDay * daysPerMonth
|
||||
return
|
||||
}
|
||||
|
||||
daysPerMonth := float64(date.UTCEndOfMonth(now).Day())
|
||||
payoutPerDay := estimatedPayout.CurrentMonth.Payout / daysPast
|
||||
|
||||
estimatedPayout.CurrentMonthExpectations += payoutPerDay * daysPerMonth
|
||||
estimatedPayout.CurrentMonthExpectations += estimatedPayout.CurrentMonth.Payout / daysSinceJoined * daysPerMonth
|
||||
}
|
||||
|
||||
// Add adds estimate into the receiver.
|
||||
func (estimatedPayout *EstimatedPayout) Add(other EstimatedPayout) {
|
||||
estimatedPayout.CurrentMonth.Add(other.CurrentMonth)
|
||||
estimatedPayout.PreviousMonth.Add(other.PreviousMonth)
|
||||
estimatedPayout.CurrentMonthExpectations += other.CurrentMonthExpectations
|
||||
}
|
||||
|
@ -10,41 +10,309 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/storagenode/payouts/estimatedpayouts"
|
||||
)
|
||||
|
||||
func TestCurrentMonthExpectations(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
StorageNodeCount: 1,
|
||||
SatelliteCount: 2,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
const payout = 100.0
|
||||
const payout = 100.0
|
||||
|
||||
type test struct {
|
||||
time time.Time
|
||||
expected float64
|
||||
}
|
||||
tests := []test{
|
||||
// 28 days in month
|
||||
{time.Date(2021, 2, 1, 16, 0, 0, 0, time.UTC), 2800.00},
|
||||
{time.Date(2021, 2, 28, 10, 0, 0, 0, time.UTC), 103.70},
|
||||
// 31 days in month
|
||||
{time.Date(2021, 3, 1, 19, 0, 0, 0, time.UTC), 3100.0},
|
||||
{time.Date(2021, 3, 31, 21, 0, 0, 0, time.UTC), 103.33},
|
||||
}
|
||||
type test struct {
|
||||
time time.Time
|
||||
expected float64
|
||||
joinedAt time.Time
|
||||
payout estimatedpayouts.EstimatedPayout
|
||||
current, previous estimatedpayouts.PayoutMonthly
|
||||
}
|
||||
tests := []test{
|
||||
// 28 days in month
|
||||
{time.Date(2021, 2, 1, 16, 0, 0, 0, time.UTC), 2800.00, time.Date(2021, 1, 1, 12, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
{time.Date(2021, 2, 28, 10, 0, 0, 0, time.UTC), 103.70, time.Date(2021, 1, 26, 10, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
{time.Date(2021, 2, 28, 10, 0, 0, 0, time.UTC), 215.38, time.Date(2021, 2, 15, 10, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
// 31 days in month
|
||||
{time.Date(2021, 3, 1, 19, 0, 0, 0, time.UTC), 3100.0, time.Date(2021, 1, 1, 19, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
{time.Date(2021, 3, 31, 21, 0, 0, 0, time.UTC), 103.33, time.Date(2021, 1, 31, 21, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
{time.Date(2021, 3, 31, 21, 0, 0, 0, time.UTC), 193.75, time.Date(2021, 3, 15, 21, 0, 0, 0, time.UTC),
|
||||
estimatedpayouts.EstimatedPayout{},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
},
|
||||
estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 567,
|
||||
DiskSpacePayout: 678,
|
||||
HeldRate: 789,
|
||||
Payout: payout,
|
||||
Held: 901,
|
||||
}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
estimates := estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
Payout: payout,
|
||||
},
|
||||
}
|
||||
|
||||
estimates.SetExpectedMonth(test.time)
|
||||
require.False(t, math.IsNaN(estimates.CurrentMonthExpectations))
|
||||
require.InDelta(t, test.expected, estimates.CurrentMonthExpectations, 0.01)
|
||||
}
|
||||
})
|
||||
for _, test := range tests {
|
||||
test.payout.Set(test.current, test.previous, test.time, test.joinedAt)
|
||||
require.False(t, math.IsNaN(test.payout.CurrentMonthExpectations))
|
||||
require.InDelta(t, test.expected, test.payout.CurrentMonthExpectations, 0.01)
|
||||
require.Equal(t, test.payout.CurrentMonth, test.current)
|
||||
require.Equal(t, test.payout.PreviousMonth, test.previous)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddEstimationPayout(t *testing.T) {
|
||||
type test struct {
|
||||
basic, addition, result estimatedpayouts.EstimatedPayout
|
||||
}
|
||||
|
||||
tests := []test{
|
||||
{estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 123,
|
||||
EgressRepairAudit: 123,
|
||||
EgressRepairAuditPayout: 123,
|
||||
DiskSpace: 123,
|
||||
DiskSpacePayout: 123,
|
||||
Payout: 123,
|
||||
Held: 123,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 234,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 234,
|
||||
EgressRepairAuditPayout: 234,
|
||||
DiskSpace: 234,
|
||||
DiskSpacePayout: 234,
|
||||
Payout: 234,
|
||||
Held: 234,
|
||||
},
|
||||
CurrentMonthExpectations: 111,
|
||||
},
|
||||
estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 345,
|
||||
EgressBandwidthPayout: 345,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 345,
|
||||
DiskSpace: 345,
|
||||
DiskSpacePayout: 345,
|
||||
Payout: 345,
|
||||
Held: 345,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 456,
|
||||
EgressBandwidthPayout: 456,
|
||||
EgressRepairAudit: 456,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 456,
|
||||
DiskSpacePayout: 456,
|
||||
Payout: 456,
|
||||
Held: 456,
|
||||
},
|
||||
CurrentMonthExpectations: 222,
|
||||
},
|
||||
estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 468,
|
||||
EgressBandwidthPayout: 468,
|
||||
EgressRepairAudit: 468,
|
||||
EgressRepairAuditPayout: 468,
|
||||
DiskSpace: 468,
|
||||
DiskSpacePayout: 468,
|
||||
Payout: 468,
|
||||
Held: 468,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 690,
|
||||
EgressBandwidthPayout: 690,
|
||||
EgressRepairAudit: 690,
|
||||
EgressRepairAuditPayout: 690,
|
||||
DiskSpace: 690,
|
||||
DiskSpacePayout: 690,
|
||||
Payout: 690,
|
||||
Held: 690,
|
||||
},
|
||||
CurrentMonthExpectations: 333,
|
||||
}},
|
||||
{estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
DiskSpace: 123,
|
||||
DiskSpacePayout: 234,
|
||||
Payout: 345,
|
||||
Held: 456,
|
||||
},
|
||||
CurrentMonthExpectations: 111,
|
||||
},
|
||||
estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
DiskSpace: 456,
|
||||
DiskSpacePayout: 345,
|
||||
Payout: 234,
|
||||
Held: 123,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 456,
|
||||
EgressBandwidthPayout: 345,
|
||||
EgressRepairAudit: 234,
|
||||
EgressRepairAuditPayout: 123,
|
||||
},
|
||||
CurrentMonthExpectations: 111,
|
||||
},
|
||||
estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 123,
|
||||
EgressBandwidthPayout: 234,
|
||||
EgressRepairAudit: 345,
|
||||
EgressRepairAuditPayout: 456,
|
||||
DiskSpace: 456,
|
||||
DiskSpacePayout: 345,
|
||||
Payout: 234,
|
||||
Held: 123,
|
||||
},
|
||||
PreviousMonth: estimatedpayouts.PayoutMonthly{
|
||||
EgressBandwidth: 456,
|
||||
EgressBandwidthPayout: 345,
|
||||
EgressRepairAudit: 234,
|
||||
EgressRepairAuditPayout: 123,
|
||||
DiskSpace: 123,
|
||||
DiskSpacePayout: 234,
|
||||
Payout: 345,
|
||||
Held: 456,
|
||||
},
|
||||
CurrentMonthExpectations: 222,
|
||||
}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test.basic.Add(test.addition)
|
||||
require.Equal(t, test.basic, test.result)
|
||||
}
|
||||
}
|
||||
|
@ -61,22 +61,12 @@ func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID s
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
}
|
||||
|
||||
payout.CurrentMonth = currentMonthPayout
|
||||
payout.PreviousMonth = previousMonthPayout
|
||||
|
||||
stats, err := s.reputationDB.Get(ctx, satelliteID)
|
||||
if err != nil {
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
}
|
||||
|
||||
daysSinceJoined := now.Sub(stats.JoinedAt).Hours() / 24
|
||||
if daysSinceJoined >= float64(now.Day()) {
|
||||
payout.SetExpectedMonth(now)
|
||||
|
||||
return payout, nil
|
||||
}
|
||||
|
||||
payout.CurrentMonthExpectations = (payout.CurrentMonth.Payout / daysSinceJoined) * float64(date.UTCEndOfMonth(now).Day())
|
||||
payout.Set(currentMonthPayout, previousMonthPayout, now, stats.JoinedAt)
|
||||
return payout, nil
|
||||
}
|
||||
|
||||
@ -91,25 +81,16 @@ func (s *Service) GetAllSatellitesEstimatedPayout(ctx context.Context, now time.
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
}
|
||||
|
||||
payout.CurrentMonth.Payout += current.Payout
|
||||
payout.CurrentMonth.EgressRepairAuditPayout += current.EgressRepairAuditPayout
|
||||
payout.CurrentMonth.DiskSpacePayout += current.DiskSpacePayout
|
||||
payout.CurrentMonth.DiskSpace += current.DiskSpace
|
||||
payout.CurrentMonth.EgressBandwidth += current.EgressBandwidth
|
||||
payout.CurrentMonth.EgressBandwidthPayout += current.EgressBandwidthPayout
|
||||
payout.CurrentMonth.EgressRepairAudit += current.EgressRepairAudit
|
||||
payout.CurrentMonth.Held += current.Held
|
||||
payout.PreviousMonth.Payout += previous.Payout
|
||||
payout.PreviousMonth.DiskSpacePayout += previous.DiskSpacePayout
|
||||
payout.PreviousMonth.DiskSpace += previous.DiskSpace
|
||||
payout.PreviousMonth.EgressBandwidth += previous.EgressBandwidth
|
||||
payout.PreviousMonth.EgressBandwidthPayout += previous.EgressBandwidthPayout
|
||||
payout.PreviousMonth.EgressRepairAuditPayout += previous.EgressRepairAuditPayout
|
||||
payout.PreviousMonth.EgressRepairAudit += previous.EgressRepairAudit
|
||||
payout.PreviousMonth.Held += previous.Held
|
||||
}
|
||||
var satellitePayout EstimatedPayout
|
||||
|
||||
payout.SetExpectedMonth(now)
|
||||
stats, err := s.reputationDB.Get(ctx, satelliteIDs[i])
|
||||
if err != nil {
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
}
|
||||
|
||||
satellitePayout.Set(current, previous, now, stats.JoinedAt)
|
||||
payout.Add(satellitePayout)
|
||||
}
|
||||
|
||||
return payout, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user