satellite/{console, accounting}: fix project bandwidth calculation which is shown on project dashboard

Another try to fix calculation of used bandwidth which is displayed on Project Dashboard.
This change sums up allocated-dead traffic for the last 3 days and settled traffic for the period which is earlier than 3 days ago.

Issue:
https://github.com/storj/storj-private/issues/293

Change-Id: I91e652eba69f81bd21e0d053ac170e2b926b3cb4
This commit is contained in:
Vitalii 2023-07-19 18:47:00 +03:00 committed by Storj Robot
parent 5db0fd8846
commit 6d94d6a681
3 changed files with 69 additions and 8 deletions

View File

@ -330,3 +330,8 @@ func (usage *Service) AddProjectStorageUsage(ctx context.Context, projectID uuid
func (usage *Service) SetNow(now func() time.Time) { func (usage *Service) SetNow(now func() time.Time) {
usage.nowFn = now usage.nowFn = now
} }
// TestSetAsOfSystemInterval allows tests to set Service asOfSystemInterval value.
func (usage *Service) TestSetAsOfSystemInterval(asOfSystemInterval time.Duration) {
usage.asOfSystemInterval = asOfSystemInterval
}

View File

@ -171,6 +171,8 @@ type Service struct {
satelliteName string satelliteName string
config Config config Config
nowFn func() time.Time
} }
func init() { func init() {
@ -280,6 +282,7 @@ func NewService(log *zap.Logger, store DB, restKeys RESTKeys, projectAccounting
satelliteAddress: satelliteAddress, satelliteAddress: satelliteAddress,
satelliteName: satelliteName, satelliteName: satelliteName,
config: config, config: config,
nowFn: time.Now,
}, nil }, nil
} }
@ -2731,7 +2734,7 @@ func (s *Service) GetProjectUsageLimits(ctx context.Context, projectID uuid.UUID
return nil, Error.Wrap(err) return nil, Error.Wrap(err)
} }
prUsageLimits, err := s.getProjectUsageLimits(ctx, isMember.project.ID, true) prUsageLimits, err := s.getProjectUsageLimits(ctx, isMember.project.ID, false)
if err != nil { if err != nil {
return nil, Error.Wrap(err) return nil, Error.Wrap(err)
} }
@ -2773,7 +2776,7 @@ func (s *Service) GetTotalUsageLimits(ctx context.Context) (_ *ProjectUsageLimit
var totalBandwidthUsed int64 var totalBandwidthUsed int64
for _, pr := range projects { for _, pr := range projects {
prUsageLimits, err := s.getProjectUsageLimits(ctx, pr.ID, false) prUsageLimits, err := s.getProjectUsageLimits(ctx, pr.ID, true)
if err != nil { if err != nil {
return nil, Error.Wrap(err) return nil, Error.Wrap(err)
} }
@ -2792,7 +2795,7 @@ func (s *Service) GetTotalUsageLimits(ctx context.Context) (_ *ProjectUsageLimit
}, nil }, nil
} }
func (s *Service) getProjectUsageLimits(ctx context.Context, projectID uuid.UUID, onlySettledBandwidth bool) (_ *ProjectUsageLimits, err error) { func (s *Service) getProjectUsageLimits(ctx context.Context, projectID uuid.UUID, getBandwidthTotals bool) (_ *ProjectUsageLimits, err error) {
defer mon.Task()(&ctx)(&err) defer mon.Task()(&ctx)(&err)
storageLimit, err := s.projectUsage.GetProjectStorageLimit(ctx, projectID) storageLimit, err := s.projectUsage.GetProjectStorageLimit(ctx, projectID)
@ -2814,10 +2817,11 @@ func (s *Service) getProjectUsageLimits(ctx context.Context, projectID uuid.UUID
} }
var bandwidthUsed int64 var bandwidthUsed int64
if onlySettledBandwidth { if getBandwidthTotals {
bandwidthUsed, err = s.projectUsage.GetProjectSettledBandwidth(ctx, projectID)
} else {
bandwidthUsed, err = s.projectUsage.GetProjectBandwidthTotals(ctx, projectID) bandwidthUsed, err = s.projectUsage.GetProjectBandwidthTotals(ctx, projectID)
} else {
now := s.nowFn()
bandwidthUsed, err = s.projectUsage.GetProjectBandwidth(ctx, projectID, now.Year(), now.Month(), now.Day())
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -3819,3 +3823,8 @@ func (s *Service) ParseInviteToken(ctx context.Context, token string) (publicID
return claims.ID, claims.Email, nil return claims.ID, claims.Email, nil
} }
// TestSetNow allows tests to have the Service act as if the current time is whatever they want.
func (s *Service) TestSetNow(now func() time.Time) {
s.nowFn = now
}

View File

@ -441,14 +441,61 @@ func TestService(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
now := time.Now().UTC() now := time.Now().UTC()
allocatedAmount := int64(1000)
settledAmount := int64(2000)
startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC) startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC)
err = sat.DB.Orders().UpdateBucketBandwidthAllocation(ctx, up2Proj.ID, []byte(bucket), pb.PieceAction_GET, 1000, startOfMonth) thirdDayOfMonth := time.Date(now.Year(), now.Month(), 3, 0, 0, 0, 0, time.UTC)
// set now as third day of the month.
service.TestSetNow(func() time.Time {
return thirdDayOfMonth
})
// add allocated and settled bandwidth for the beginning of the month.
err = sat.DB.Orders().UpdateBucketBandwidthAllocation(ctx, up2Proj.ID, []byte(bucket), pb.PieceAction_GET, allocatedAmount, startOfMonth)
require.NoError(t, err)
err = sat.DB.Orders().UpdateBucketBandwidthSettle(ctx, up2Proj.ID, []byte(bucket), pb.PieceAction_GET, settledAmount, 0, startOfMonth)
require.NoError(t, err) require.NoError(t, err)
sat.API.Accounting.ProjectUsage.TestSetAsOfSystemInterval(0)
// at this point only allocated traffic is expected.
limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID) limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, limits2) require.NotNil(t, limits2)
require.Equal(t, int64(0), limits2.BandwidthUsed) require.Equal(t, allocatedAmount, limits2.BandwidthUsed)
// set now as fourth day of the month.
service.TestSetNow(func() time.Time {
return time.Date(now.Year(), now.Month(), 4, 0, 0, 0, 0, time.UTC)
})
// at this point only settled traffic for the first day is expected.
limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID)
require.NoError(t, err)
require.NotNil(t, limits2)
require.Equal(t, settledAmount, limits2.BandwidthUsed)
// add settled traffic for the third day of the month.
err = sat.DB.Orders().UpdateBucketBandwidthSettle(ctx, up2Proj.ID, []byte(bucket), pb.PieceAction_GET, settledAmount, 0, thirdDayOfMonth)
require.NoError(t, err)
// at this point only settled traffic for the first day is expected because now is still set to fourth day.
limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID)
require.NoError(t, err)
require.NotNil(t, limits2)
require.Equal(t, settledAmount, limits2.BandwidthUsed)
// set now as sixth day of the month.
service.TestSetNow(func() time.Time {
return time.Date(now.Year(), now.Month(), 6, 0, 0, 0, 0, time.UTC)
})
// at this point only settled traffic for the first and third days is expected.
limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID)
require.NoError(t, err)
require.NotNil(t, limits2)
require.Equal(t, settledAmount+settledAmount, limits2.BandwidthUsed)
}) })
t.Run("ChangeEmail", func(t *testing.T) { t.Run("ChangeEmail", func(t *testing.T) {