satellite/accounting: don't expire segments usage key

Initialy we wanted to put segment usage into cache values retrieved
directly from metabase but it cause performance issues. Now we
will be collecting segment usage from tally object loop and those
values will be put into a cache but becuse we cannot get those values
on demand we shouldn't expire cache value at all because objects
loop requires sustencial amount of time to be executed.

Part of solution for https://github.com/storj/storj/issues/4744

Change-Id: I3b37e23badeecebed0c95064156e85b38038bfe2
This commit is contained in:
Michał Niewrzał 2022-05-12 15:53:08 +02:00 committed by Michal Niewrzal
parent 747f2a09f7
commit 277f8d2ae0
4 changed files with 8 additions and 25 deletions

View File

@ -284,7 +284,7 @@ type Cache interface {
// UpdateProjectSegmentUsage updates the project's segment usage increasing
// it. The projectID is inserted to the increment when it doesn't exists,
// hence this method will never return ErrKeyNotFound error's class.
UpdateProjectSegmentUsage(ctx context.Context, projectID uuid.UUID, increment int64, ttl time.Duration) error
UpdateProjectSegmentUsage(ctx context.Context, projectID uuid.UUID, increment int64) error
// AddProjectStorageUsage adds to the projects storage usage the spacedUsed.
// The projectID is inserted to the spaceUsed when it doesn't exists, hence
// this method will never return ErrKeyNotFound.

View File

@ -132,7 +132,7 @@ func TestGetAllProjectTotals(t *testing.T) {
projectIDs[i] = testrand.UUID()
err := cache.AddProjectStorageUsage(ctx, projectIDs[i], int64(i))
require.NoError(t, err)
err = cache.UpdateProjectSegmentUsage(ctx, projectIDs[i], int64(i), time.Hour)
err = cache.UpdateProjectSegmentUsage(ctx, projectIDs[i], int64(i))
require.NoError(t, err)
}

View File

@ -122,30 +122,14 @@ func (cache *redisLiveAccounting) GetProjectSegmentUsage(ctx context.Context, pr
}
// UpdateProjectSegmentUsage increment the segment cache key value.
func (cache *redisLiveAccounting) UpdateProjectSegmentUsage(ctx context.Context, projectID uuid.UUID, increment int64, ttl time.Duration) (err error) {
mon.Task()(&ctx, projectID, increment, ttl)(&err)
// The following script will increment the cache key
// by a specific value. If the key does not exist, it is
// set to 0 before performing the operation.
// The key expiration will be set only in the first iteration.
// To achieve this we compare the increment and key value,
// if they are equal its the first iteration.
// More details on rate limiter section: https://redis.io/commands/incr
script := fmt.Sprintf(`local current
current = redis.call("incrby", KEYS[1], "%d")
if tonumber(current) == %d then
redis.call("expire",KEYS[1], %d)
end
return current
`, increment, increment, int(ttl.Seconds()))
func (cache *redisLiveAccounting) UpdateProjectSegmentUsage(ctx context.Context, projectID uuid.UUID, increment int64) (err error) {
mon.Task()(&ctx, projectID, increment)(&err)
key := createSegmentProjectIDKey(projectID)
err = cache.client.Eval(ctx, script, []string{key}).Err()
_, err = cache.client.IncrBy(ctx, key, increment).Result()
if err != nil {
return accounting.ErrSystemOrNetError.New("Redis eval failed: %w", err)
return accounting.ErrSystemOrNetError.New("Redis incrby failed: %w", err)
}
return nil
}

View File

@ -141,7 +141,7 @@ func (usage *Service) ExceedsUploadLimits(ctx context.Context, projectID uuid.UU
}
// Create cache key with database value.
if err := usage.liveAccounting.UpdateProjectSegmentUsage(ctx, projectID, segmentGetTotal, usage.bandwidthCacheTTL); err != nil {
if err := usage.liveAccounting.UpdateProjectSegmentUsage(ctx, projectID, segmentGetTotal); err != nil {
return err
}
@ -283,8 +283,7 @@ func (usage *Service) GetProjectSegmentUsage(ctx context.Context, projectID uuid
// It can return one of the following errors returned by
// storj.io/storj/satellite/accounting.Cache.UpdatProjectSegmentUsage.
func (usage *Service) UpdateProjectSegmentUsage(ctx context.Context, projectID uuid.UUID, increment int64) (err error) {
// TODO rename bandwidthCacheTTL to cacheTTL
return usage.liveAccounting.UpdateProjectSegmentUsage(ctx, projectID, increment, usage.bandwidthCacheTTL)
return usage.liveAccounting.UpdateProjectSegmentUsage(ctx, projectID, increment)
}
// AddProjectStorageUsage lets the live accounting know that the given