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 }