delete-expired.go raw

   1  //go:build !(js && wasm)
   2  
   3  package database
   4  
   5  import (
   6  	"bytes"
   7  	"context"
   8  	"time"
   9  
  10  	"github.com/dgraph-io/badger/v4"
  11  	"next.orly.dev/pkg/lol/chk"
  12  	"next.orly.dev/pkg/database/indexes"
  13  	"next.orly.dev/pkg/database/indexes/types"
  14  	"next.orly.dev/pkg/nostr/encoders/event"
  15  )
  16  
  17  func (d *D) DeleteExpired() {
  18  	var err error
  19  	var expiredSerials types.Uint40s
  20  	// make the operation atomic and save on accesses to the system clock by
  21  	// setting the boundary at the current second
  22  	now := time.Now().Unix()
  23  	// search the expiration indexes for expiry timestamps that are now past
  24  	if err = d.View(
  25  		func(txn *badger.Txn) (err error) {
  26  			exp, ser := indexes.ExpirationVars()
  27  			expPrf := new(bytes.Buffer)
  28  			if _, err = indexes.ExpirationPrefix.Write(expPrf); chk.E(err) {
  29  				return
  30  			}
  31  			it := txn.NewIterator(badger.IteratorOptions{Prefix: expPrf.Bytes()})
  32  			defer it.Close()
  33  			for it.Rewind(); it.Valid(); it.Next() {
  34  				item := it.Item()
  35  				key := item.Key()
  36  				buf := bytes.NewBuffer(key)
  37  				if err = indexes.ExpirationDec(
  38  					exp, ser,
  39  				).UnmarshalRead(buf); chk.E(err) {
  40  					continue
  41  				}
  42  				if int64(exp.Get()) > now {
  43  					// not expired yet
  44  					continue
  45  				}
  46  				expiredSerials = append(expiredSerials, ser)
  47  			}
  48  			return
  49  		},
  50  	); chk.E(err) {
  51  	}
  52  	// delete the events and their indexes
  53  	for _, ser := range expiredSerials {
  54  		var ev *event.E
  55  		if ev, err = d.FetchEventBySerial(ser); chk.E(err) {
  56  			continue
  57  		}
  58  		if err = d.DeleteEventBySerial(
  59  			context.Background(), ser, ev,
  60  		); chk.E(err) {
  61  			continue
  62  		}
  63  	}
  64  }
  65