github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/storage/tsdb/tenant_deletion_mark.go (about) 1 package tsdb 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "path" 8 "time" 9 10 "github.com/go-kit/log/level" 11 "github.com/pkg/errors" 12 "github.com/thanos-io/thanos/pkg/objstore" 13 14 "github.com/cortexproject/cortex/pkg/storage/bucket" 15 util_log "github.com/cortexproject/cortex/pkg/util/log" 16 ) 17 18 // Relative to user-specific prefix. 19 const TenantDeletionMarkPath = "markers/tenant-deletion-mark.json" 20 21 type TenantDeletionMark struct { 22 // Unix timestamp when deletion marker was created. 23 DeletionTime int64 `json:"deletion_time"` 24 25 // Unix timestamp when cleanup was finished. 26 FinishedTime int64 `json:"finished_time,omitempty"` 27 } 28 29 func NewTenantDeletionMark(deletionTime time.Time) *TenantDeletionMark { 30 return &TenantDeletionMark{DeletionTime: deletionTime.Unix()} 31 } 32 33 // Checks for deletion mark for tenant. Errors other than "object not found" are returned. 34 func TenantDeletionMarkExists(ctx context.Context, bkt objstore.BucketReader, userID string) (bool, error) { 35 markerFile := path.Join(userID, TenantDeletionMarkPath) 36 37 return bkt.Exists(ctx, markerFile) 38 } 39 40 // Uploads deletion mark to the tenant location in the bucket. 41 func WriteTenantDeletionMark(ctx context.Context, bkt objstore.Bucket, userID string, cfgProvider bucket.TenantConfigProvider, mark *TenantDeletionMark) error { 42 bkt = bucket.NewUserBucketClient(userID, bkt, cfgProvider) 43 44 data, err := json.Marshal(mark) 45 if err != nil { 46 return errors.Wrap(err, "serialize tenant deletion mark") 47 } 48 49 return errors.Wrap(bkt.Upload(ctx, TenantDeletionMarkPath, bytes.NewReader(data)), "upload tenant deletion mark") 50 } 51 52 // Returns tenant deletion mark for given user, if it exists. If it doesn't exist, returns nil mark, and no error. 53 func ReadTenantDeletionMark(ctx context.Context, bkt objstore.BucketReader, userID string) (*TenantDeletionMark, error) { 54 markerFile := path.Join(userID, TenantDeletionMarkPath) 55 56 r, err := bkt.Get(ctx, markerFile) 57 if err != nil { 58 if bkt.IsObjNotFoundErr(err) { 59 return nil, nil 60 } 61 62 return nil, errors.Wrapf(err, "failed to read deletion mark object: %s", markerFile) 63 } 64 65 mark := &TenantDeletionMark{} 66 err = json.NewDecoder(r).Decode(mark) 67 68 // Close reader before dealing with decode error. 69 if closeErr := r.Close(); closeErr != nil { 70 level.Warn(util_log.Logger).Log("msg", "failed to close bucket reader", "err", closeErr) 71 } 72 73 if err != nil { 74 return nil, errors.Wrapf(err, "failed to decode deletion mark object: %s", markerFile) 75 } 76 77 return mark, nil 78 }