storagenode/payouts: fix CurrentMonthExpectations timezone handling. Estimations based on node's join date.
On servers with non-UTC it would have calculated a different month boundary. If node joined in current month calculations will be related on amount of days node've been working. Change-Id: Ie572b197f50c6cdff5a044a53dfb5b9138f82f24
This commit is contained in:
parent
49c8e94480
commit
c139cbd76b
1
go.mod
1
go.mod
@ -20,7 +20,6 @@ require (
|
||||
github.com/jackc/pgconn v1.7.0
|
||||
github.com/jackc/pgtype v1.5.0
|
||||
github.com/jackc/pgx/v4 v4.9.0
|
||||
github.com/jinzhu/now v1.1.1
|
||||
github.com/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3
|
||||
github.com/lucas-clemente/quic-go v0.19.3
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
|
2
go.sum
2
go.sum
@ -337,8 +337,6 @@ github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv
|
||||
github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
|
@ -51,3 +51,10 @@ func MonthsBetweenDates(from time.Time, to time.Time) int {
|
||||
func TruncateToHourInNano(t time.Time) int64 {
|
||||
return t.Truncate(1 * time.Hour).UnixNano()
|
||||
}
|
||||
|
||||
// UTCEndOfMonth returns utc end of month (f.e. to get last day in month).
|
||||
func UTCEndOfMonth(now time.Time) time.Time {
|
||||
now = now.UTC()
|
||||
y, m, _ := now.Date()
|
||||
return time.Date(y, m+1, 1, 0, 0, 0, 0, &time.Location{}).Add(-time.Nanosecond)
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ package estimatedpayouts
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"storj.io/storj/private/date"
|
||||
)
|
||||
|
||||
// EstimatedPayout contains usage and estimated payouts data for current and previous months.
|
||||
@ -61,3 +64,10 @@ func (pm *PayoutMonthly) SetPayout() {
|
||||
func RoundFloat(value float64) float64 {
|
||||
return math.Round(value*100) / 100
|
||||
}
|
||||
|
||||
// SetExpectedMonth set current month expectations.
|
||||
func (estimatedPayout *EstimatedPayout) SetExpectedMonth(now time.Time) {
|
||||
daysPaste := float64(now.Day() - 1)
|
||||
timeInMonth := date.UTCEndOfMonth(now)
|
||||
estimatedPayout.CurrentMonthExpectations = (estimatedPayout.CurrentMonth.Payout / daysPaste) * float64(timeInMonth.Day())
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2021 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package estimatedpayouts_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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) {
|
||||
estimatedPayout := estimatedpayouts.EstimatedPayout{
|
||||
CurrentMonth: estimatedpayouts.PayoutMonthly{
|
||||
Payout: 100,
|
||||
},
|
||||
}
|
||||
|
||||
currentDay := time.Now().Day() - 1
|
||||
now := time.Now().UTC()
|
||||
y, m, _ := now.Date()
|
||||
daysInMonth := time.Date(y, m+1, 1, 0, 0, 0, -1, &time.Location{}).Day()
|
||||
|
||||
expectations := (estimatedPayout.CurrentMonth.Payout / float64(currentDay)) * float64(daysInMonth)
|
||||
estimatedPayout.SetExpectedMonth(now)
|
||||
require.Equal(t, estimatedPayout.CurrentMonthExpectations, expectations)
|
||||
})
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/now"
|
||||
"github.com/spacemonkeygo/monkit/v3"
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
@ -57,6 +56,7 @@ func NewService(bandwidthDB bandwidth.DB, reputationDB reputation.DB, storageUsa
|
||||
func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID storj.NodeID) (payout EstimatedPayout, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
now := time.Now()
|
||||
currentMonthPayout, previousMonthPayout, err := s.estimatedPayout(ctx, satelliteID)
|
||||
if err != nil {
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
@ -64,14 +64,27 @@ func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID s
|
||||
|
||||
payout.CurrentMonth = currentMonthPayout
|
||||
payout.PreviousMonth = previousMonthPayout
|
||||
payout.setExpectations(ctx)
|
||||
|
||||
stats, err := s.reputationDB.Get(ctx, satelliteID)
|
||||
if err != nil {
|
||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||
}
|
||||
|
||||
daysSinceJoined := time.Since(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())
|
||||
return payout, nil
|
||||
}
|
||||
|
||||
// GetAllSatellitesEstimatedPayout returns estimated payouts for current and previous months from all satellites with current level of load.
|
||||
func (s *Service) GetAllSatellitesEstimatedPayout(ctx context.Context) (payout EstimatedPayout, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
now := time.Now()
|
||||
|
||||
satelliteIDs := s.trust.GetSatellites(ctx)
|
||||
for i := 0; i < len(satelliteIDs); i++ {
|
||||
@ -97,18 +110,12 @@ func (s *Service) GetAllSatellitesEstimatedPayout(ctx context.Context) (payout E
|
||||
payout.PreviousMonth.EgressRepairAudit += previous.EgressRepairAudit
|
||||
payout.PreviousMonth.Held += previous.Held
|
||||
}
|
||||
payout.setExpectations(ctx)
|
||||
|
||||
payout.SetExpectedMonth(now)
|
||||
|
||||
return payout, nil
|
||||
}
|
||||
|
||||
// setExpectations set current month expectations.
|
||||
func (estimatedPayout *EstimatedPayout) setExpectations(ctx context.Context) {
|
||||
daysPaste := float64(time.Now().Day() - 1)
|
||||
DaysInMonth := float64(now.EndOfMonth().Day())
|
||||
estimatedPayout.CurrentMonthExpectations = (estimatedPayout.CurrentMonth.Payout / daysPaste) * DaysInMonth
|
||||
}
|
||||
|
||||
// estimatedPayout returns estimated payouts data for current and previous months from specific satellite.
|
||||
func (s *Service) estimatedPayout(ctx context.Context, satelliteID storj.NodeID) (currentMonthPayout PayoutMonthly, previousMonthPayout PayoutMonthly, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
@ -286,6 +286,7 @@ type Peer struct {
|
||||
Storage *multinode.StorageEndpoint
|
||||
Bandwidth *multinode.BandwidthEndpoint
|
||||
Node *multinode.NodeEndpoint
|
||||
Payout *multinode.PayoutEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,6 +800,11 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
|
||||
peer.DB.Reputation(),
|
||||
peer.Storage2.Trust)
|
||||
|
||||
peer.Multinode.Payout = multinode.NewPayoutEndpoint(
|
||||
peer.Log.Named("multinode:payout-endpoint"),
|
||||
apiKeys,
|
||||
peer.DB.Payout())
|
||||
|
||||
if err = multinodepb.DRPCRegisterStorage(peer.Server.DRPC(), peer.Multinode.Storage); err != nil {
|
||||
return nil, errs.Combine(err, peer.Close())
|
||||
}
|
||||
@ -808,6 +814,9 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
|
||||
if err = multinodepb.DRPCRegisterNode(peer.Server.DRPC(), peer.Multinode.Node); err != nil {
|
||||
return nil, errs.Combine(err, peer.Close())
|
||||
}
|
||||
if err = multinodepb.DRPCRegisterPayout(peer.Server.DRPC(), peer.Multinode.Payout); err != nil {
|
||||
return nil, errs.Combine(err, peer.Close())
|
||||
}
|
||||
}
|
||||
|
||||
return peer, nil
|
||||
|
Loading…
Reference in New Issue
Block a user