Files
ttstd-infinite-canvas/backend/internal/service/resource_deletion_worker.go

60 lines
1.6 KiB
Go

package service
import (
"log"
"math"
"time"
"infinite-canvas/backend/internal/model"
)
const resourceDeletionLease = 2 * time.Minute
func (s *Service) startResourceDeletionWorker() {
go func() {
s.drainResourceDeletionJobs(32)
ticker := time.NewTicker(15 * time.Second)
defer ticker.Stop()
for range ticker.C {
s.drainResourceDeletionJobs(32)
}
}()
}
func (s *Service) drainResourceDeletionJobs(limit int) {
owner := s.workerID
if owner == "" {
owner = newID()
}
for index := 0; index < limit; index++ {
job, err := s.repo.ClaimNextResourceDeletionJob(owner, resourceDeletionLease)
if err != nil {
log.Printf("resource deletion worker claim failed: %v", err)
return
}
if job == nil {
return
}
resource := &model.Resource{
ID: job.ResourceID, UserID: job.UserID, Provider: job.Provider,
Endpoint: job.Endpoint, Bucket: job.Bucket, StorageSettingID: job.StorageSettingID,
ObjectKey: job.ObjectKey,
}
if err := s.deleteStoredResourceObject(job.UserID, resource); err != nil {
delay := resourceDeletionRetryDelay(job.Attempts)
if retryErr := s.repo.RetryResourceDeletionJob(job.ID, owner, err.Error(), time.Now().Add(delay)); retryErr != nil {
log.Printf("resource deletion worker retry update failed for %s: %v", job.ID, retryErr)
}
continue
}
if err := s.repo.CompleteResourceDeletionJob(job.ID, owner); err != nil {
log.Printf("resource deletion worker completion failed for %s: %v", job.ID, err)
}
}
}
func resourceDeletionRetryDelay(attempts int) time.Duration {
exponent := math.Min(float64(max(attempts-1, 0)), 8)
return time.Duration(math.Pow(2, exponent)) * 15 * time.Second
}