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  }