2020-09-08 16:15:08 +01:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
package estimatedpayouts
|
2020-09-08 16:15:08 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
"github.com/jinzhu/now"
|
2020-09-08 16:15:08 +01:00
|
|
|
"github.com/spacemonkeygo/monkit/v3"
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
|
|
|
|
"storj.io/common/storj"
|
|
|
|
"storj.io/storj/private/date"
|
|
|
|
"storj.io/storj/storagenode/bandwidth"
|
2021-01-14 16:41:36 +00:00
|
|
|
"storj.io/storj/storagenode/payouts"
|
2020-09-08 16:15:08 +01:00
|
|
|
"storj.io/storj/storagenode/pricing"
|
|
|
|
"storj.io/storj/storagenode/reputation"
|
|
|
|
"storj.io/storj/storagenode/satellites"
|
|
|
|
"storj.io/storj/storagenode/storageusage"
|
|
|
|
"storj.io/storj/storagenode/trust"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// EstimationServiceErr defines sno service error.
|
2021-01-14 16:41:36 +00:00
|
|
|
EstimationServiceErr = errs.Class("storage node estimation payouts service error")
|
2020-09-08 16:15:08 +01:00
|
|
|
|
|
|
|
mon = monkit.Package()
|
|
|
|
)
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
// Service is handling storage node estimation payouts logic.
|
2020-09-08 16:15:08 +01:00
|
|
|
//
|
|
|
|
// architecture: Service
|
|
|
|
type Service struct {
|
|
|
|
bandwidthDB bandwidth.DB
|
|
|
|
reputationDB reputation.DB
|
|
|
|
storageUsageDB storageusage.DB
|
|
|
|
pricingDB pricing.DB
|
|
|
|
satelliteDB satellites.DB
|
|
|
|
trust *trust.Pool
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewService returns new instance of Service.
|
|
|
|
func NewService(bandwidthDB bandwidth.DB, reputationDB reputation.DB, storageUsageDB storageusage.DB, pricingDB pricing.DB, satelliteDB satellites.DB, trust *trust.Pool) *Service {
|
|
|
|
return &Service{
|
|
|
|
bandwidthDB: bandwidthDB,
|
|
|
|
reputationDB: reputationDB,
|
|
|
|
storageUsageDB: storageUsageDB,
|
|
|
|
pricingDB: pricingDB,
|
|
|
|
satelliteDB: satelliteDB,
|
|
|
|
trust: trust,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
// GetSatelliteEstimatedPayout returns estimated payouts for current and previous months from specific satellite with current level of load.
|
2020-09-08 16:15:08 +01:00
|
|
|
func (s *Service) GetSatelliteEstimatedPayout(ctx context.Context, satelliteID storj.NodeID) (payout EstimatedPayout, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
currentMonthPayout, previousMonthPayout, err := s.estimatedPayout(ctx, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return EstimatedPayout{}, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
payout.CurrentMonth = currentMonthPayout
|
|
|
|
payout.PreviousMonth = previousMonthPayout
|
2021-01-14 16:41:36 +00:00
|
|
|
payout.setExpectations(ctx)
|
2020-09-08 16:15:08 +01:00
|
|
|
|
|
|
|
return payout, nil
|
|
|
|
}
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
// GetAllSatellitesEstimatedPayout returns estimated payouts for current and previous months from all satellites with current level of load.
|
2020-09-08 16:15:08 +01:00
|
|
|
func (s *Service) GetAllSatellitesEstimatedPayout(ctx context.Context) (payout EstimatedPayout, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
satelliteIDs := s.trust.GetSatellites(ctx)
|
|
|
|
for i := 0; i < len(satelliteIDs); i++ {
|
|
|
|
current, previous, err := s.estimatedPayout(ctx, satelliteIDs[i])
|
|
|
|
if err != nil {
|
|
|
|
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
|
|
|
|
}
|
2021-01-14 16:41:36 +00:00
|
|
|
payout.setExpectations(ctx)
|
2020-09-08 16:15:08 +01:00
|
|
|
|
|
|
|
return payout, nil
|
|
|
|
}
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
// 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.
|
2020-09-08 16:15:08 +01:00
|
|
|
func (s *Service) estimatedPayout(ctx context.Context, satelliteID storj.NodeID) (currentMonthPayout PayoutMonthly, previousMonthPayout PayoutMonthly, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
priceModel, err := s.pricingDB.Get(ctx, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return PayoutMonthly{}, PayoutMonthly{}, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stats, err := s.reputationDB.Get(ctx, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return PayoutMonthly{}, PayoutMonthly{}, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
currentMonthPayout, err = s.estimationUsagePeriod(ctx, time.Now().UTC(), stats.JoinedAt, priceModel)
|
|
|
|
previousMonthPayout, err = s.estimationUsagePeriod(ctx, time.Now().UTC().AddDate(0, -1, 0), stats.JoinedAt, priceModel)
|
|
|
|
|
|
|
|
return currentMonthPayout, previousMonthPayout, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// estimationUsagePeriod returns PayoutMonthly for current satellite and current or previous month.
|
|
|
|
func (s *Service) estimationUsagePeriod(ctx context.Context, period time.Time, joinedAt time.Time, priceModel *pricing.Pricing) (payout PayoutMonthly, err error) {
|
|
|
|
var from, to time.Time
|
|
|
|
|
2021-01-14 16:41:36 +00:00
|
|
|
heldRate := payouts.GetHeldRate(joinedAt, period)
|
2020-09-08 16:15:08 +01:00
|
|
|
payout.HeldRate = heldRate
|
|
|
|
|
|
|
|
from, to = date.MonthBoundary(period)
|
|
|
|
|
|
|
|
bandwidthDaily, err := s.bandwidthDB.GetDailySatelliteRollups(ctx, priceModel.SatelliteID, from, to)
|
|
|
|
if err != nil {
|
|
|
|
return PayoutMonthly{}, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(bandwidthDaily); i++ {
|
|
|
|
payout.EgressBandwidth += bandwidthDaily[i].Egress.Usage
|
|
|
|
payout.EgressRepairAudit += bandwidthDaily[i].Egress.Audit + bandwidthDaily[i].Egress.Repair
|
|
|
|
}
|
|
|
|
payout.SetEgressBandwidthPayout(priceModel.EgressBandwidth)
|
|
|
|
payout.SetEgressRepairAuditPayout(priceModel.AuditBandwidth)
|
|
|
|
|
|
|
|
storageDaily, err := s.storageUsageDB.GetDaily(ctx, priceModel.SatelliteID, from, to)
|
|
|
|
if err != nil {
|
|
|
|
return PayoutMonthly{}, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for j := 0; j < len(storageDaily); j++ {
|
|
|
|
payout.DiskSpace += storageDaily[j].AtRestTotal
|
|
|
|
}
|
|
|
|
// dividing by 720 to show tbm instead of tbh.
|
|
|
|
payout.DiskSpace /= 720
|
|
|
|
payout.SetDiskSpacePayout(priceModel.DiskSpace)
|
|
|
|
payout.SetHeldAmount()
|
|
|
|
payout.SetPayout()
|
|
|
|
|
|
|
|
return payout, EstimationServiceErr.Wrap(err)
|
|
|
|
}
|