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) {
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
config Config
nowFn func() time.Time
}
func init() {
@ -280,6 +282,7 @@ func NewService(log *zap.Logger, store DB, restKeys RESTKeys, projectAccounting
satelliteAddress: satelliteAddress,
satelliteName: satelliteName,
config: config,
nowFn: time.Now,
}, nil
}
@ -2731,7 +2734,7 @@ func (s *Service) GetProjectUsageLimits(ctx context.Context, projectID uuid.UUID
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 {
return nil, Error.Wrap(err)
}
@ -2773,7 +2776,7 @@ func (s *Service) GetTotalUsageLimits(ctx context.Context) (_ *ProjectUsageLimit
var totalBandwidthUsed int64
for _, pr := range projects {
prUsageLimits, err := s.getProjectUsageLimits(ctx, pr.ID, false)
prUsageLimits, err := s.getProjectUsageLimits(ctx, pr.ID, true)
if err != nil {
return nil, Error.Wrap(err)
}
@ -2792,7 +2795,7 @@ func (s *Service) GetTotalUsageLimits(ctx context.Context) (_ *ProjectUsageLimit
}, 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)
storageLimit, err := s.projectUsage.GetProjectStorageLimit(ctx, projectID)
@ -2814,10 +2817,11 @@ func (s *Service) getProjectUsageLimits(ctx context.Context, projectID uuid.UUID
}
var bandwidthUsed int64
if onlySettledBandwidth {
bandwidthUsed, err = s.projectUsage.GetProjectSettledBandwidth(ctx, projectID)
} else {
if getBandwidthTotals {
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 {
return nil, err
@ -3819,3 +3823,8 @@ func (s *Service) ParseInviteToken(ctx context.Context, token string) (publicID
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)
now := time.Now().UTC()
allocatedAmount := int64(1000)
settledAmount := int64(2000)
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)
sat.API.Accounting.ProjectUsage.TestSetAsOfSystemInterval(0)
// at this point only allocated traffic is expected.
limits2, err = service.GetProjectUsageLimits(userCtx2, up2Proj.PublicID)
require.NoError(t, err)
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) {