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/pgconn v1.7.0
|
||||||
github.com/jackc/pgtype v1.5.0
|
github.com/jackc/pgtype v1.5.0
|
||||||
github.com/jackc/pgx/v4 v4.9.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/jtolds/monkit-hw/v2 v2.0.0-20191108235325-141a0da276b3
|
||||||
github.com/lucas-clemente/quic-go v0.19.3
|
github.com/lucas-clemente/quic-go v0.19.3
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
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/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/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/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/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/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
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 {
|
func TruncateToHourInNano(t time.Time) int64 {
|
||||||
return t.Truncate(1 * time.Hour).UnixNano()
|
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 (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"storj.io/storj/private/date"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EstimatedPayout contains usage and estimated payouts data for current and previous months.
|
// 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 {
|
func RoundFloat(value float64) float64 {
|
||||||
return math.Round(value*100) / 100
|
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"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jinzhu/now"
|
|
||||||
"github.com/spacemonkeygo/monkit/v3"
|
"github.com/spacemonkeygo/monkit/v3"
|
||||||
"github.com/zeebo/errs"
|
"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) {
|
func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID storj.NodeID) (payout EstimatedPayout, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
currentMonthPayout, previousMonthPayout, err := s.estimatedPayout(ctx, satelliteID)
|
currentMonthPayout, previousMonthPayout, err := s.estimatedPayout(ctx, satelliteID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
||||||
@ -64,14 +64,27 @@ func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID s
|
|||||||
|
|
||||||
payout.CurrentMonth = currentMonthPayout
|
payout.CurrentMonth = currentMonthPayout
|
||||||
payout.PreviousMonth = previousMonthPayout
|
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
|
return payout, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllSatellitesEstimatedPayout returns estimated payouts for current and previous months from all satellites with current level of load.
|
// 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) {
|
func (s *Service) GetAllSatellitesEstimatedPayout(ctx context.Context) (payout EstimatedPayout, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
satelliteIDs := s.trust.GetSatellites(ctx)
|
satelliteIDs := s.trust.GetSatellites(ctx)
|
||||||
for i := 0; i < len(satelliteIDs); i++ {
|
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.EgressRepairAudit += previous.EgressRepairAudit
|
||||||
payout.PreviousMonth.Held += previous.Held
|
payout.PreviousMonth.Held += previous.Held
|
||||||
}
|
}
|
||||||
payout.setExpectations(ctx)
|
|
||||||
|
payout.SetExpectedMonth(now)
|
||||||
|
|
||||||
return payout, nil
|
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.
|
// 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) {
|
func (s *Service) estimatedPayout(ctx context.Context, satelliteID storj.NodeID) (currentMonthPayout PayoutMonthly, previousMonthPayout PayoutMonthly, err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
@ -286,6 +286,7 @@ type Peer struct {
|
|||||||
Storage *multinode.StorageEndpoint
|
Storage *multinode.StorageEndpoint
|
||||||
Bandwidth *multinode.BandwidthEndpoint
|
Bandwidth *multinode.BandwidthEndpoint
|
||||||
Node *multinode.NodeEndpoint
|
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.DB.Reputation(),
|
||||||
peer.Storage2.Trust)
|
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 {
|
if err = multinodepb.DRPCRegisterStorage(peer.Server.DRPC(), peer.Multinode.Storage); err != nil {
|
||||||
return nil, errs.Combine(err, peer.Close())
|
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 {
|
if err = multinodepb.DRPCRegisterNode(peer.Server.DRPC(), peer.Multinode.Node); err != nil {
|
||||||
return nil, errs.Combine(err, peer.Close())
|
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
|
return peer, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user