github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/storage/cleanup.go (about)

     1  package storage
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/dgraph-io/badger/v2"
     8  
     9  	"github.com/pyroscope-io/pyroscope/pkg/storage/segment"
    10  )
    11  
    12  // Cleanup removes malformed data from the storage.
    13  func (s *Storage) Cleanup(ctx context.Context) error {
    14  	select {
    15  	case <-s.stop:
    16  		return nil
    17  	default:
    18  		// This means than s.tasksWG.Wait has not been called yet
    19  		// and it is safe to start the cleanup. There is a negligible
    20  		// chance that tasksWG.Wait is called concurrently before we
    21  		// continue.
    22  	}
    23  	s.tasksWG.Add(1)
    24  	defer s.tasksWG.Done()
    25  	start := time.Now()
    26  	s.logger.Debug("cleanup started")
    27  	defer func() {
    28  		s.logger.WithField("duration", time.Since(start)).Debug("cleanup finished")
    29  	}()
    30  	return s.cleanupTreesDB(ctx)
    31  }
    32  
    33  func (s *Storage) cleanupTreesDB(ctx context.Context) (err error) {
    34  	batch := s.trees.NewWriteBatch()
    35  	defer func() {
    36  		err = batch.Flush()
    37  	}()
    38  	return s.trees.Update(func(txn *badger.Txn) error {
    39  		it := txn.NewIterator(badger.IteratorOptions{Prefix: treePrefix.bytes()})
    40  		defer it.Close()
    41  		var c int64
    42  		for it.Rewind(); it.Valid(); it.Next() {
    43  			select {
    44  			default:
    45  			case <-ctx.Done():
    46  				return nil
    47  			case <-s.stop:
    48  				return nil
    49  			}
    50  			item := it.Item()
    51  			if k, ok := treePrefix.trim(item.Key()); ok {
    52  				if _, _, err = segment.ParseTreeKey(string(k)); err == nil {
    53  					continue
    54  				}
    55  			}
    56  			if c == s.trees.MaxBatchCount()+1 {
    57  				if err = batch.Flush(); err != nil {
    58  					return err
    59  				}
    60  				batch = s.trees.NewWriteBatch()
    61  				c = 0
    62  			}
    63  			if err = batch.Delete(item.KeyCopy(nil)); err != nil {
    64  				return err
    65  			}
    66  			c++
    67  		}
    68  		return nil
    69  	})
    70  }