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