Files
realy/ratel/countevents.go

136 lines
4.1 KiB
Go

package ratel
// func (r *T) CountEvents(c context.T, f *filter.T) (count int, approx bool, err error) {
// log.T.ToSliceOfBytes("QueryEvents,%s", f.Serialize())
// var queries []query
// var extraFilter *filter.T
// var since uint64
// if queries, extraFilter, since, err = PrepareQueries(f); chk.E(err) {
// return
// }
// var delEvs [][]byte
// defer func() {
// // after the count delete any events that are expired as per NIP-40
// for _, d := range delEvs {
// chk.E(r.DeleteEvent(r.Ctx, eventid.NewWith(d)))
// }
// }()
// // search for the keys generated from the filter
// for _, q := range queries {
// select {
// case <-c.Done():
// return
// default:
// }
// var eventKey []byte
// err = r.View(func(txn *badger.Txn) (err error) {
// // iterate only through keys and in reverse order
// opts := badger.IteratorOptions{
// Reverse: true,
// }
// it := txn.NewIterator(opts)
// defer it.Close()
// for it.Seek(q.start); it.ValidForPrefix(q.searchPrefix); it.Next() {
// select {
// case <-r.Ctx.Done():
// return
// case <-c.Done():
// return
// default:
// }
// item := it.Item()
// k := item.KeyCopy(nil)
// if !q.skipTS {
// if len(k) < createdat.Len+serial.Len {
// continue
// }
// createdAt := createdat.FromKey(k)
// if createdAt.Val.U64() < since {
// break
// }
// }
// // todo: here we should get the kind field from the key and and collate the
// // todo: matches that are replaceable/parameterized replaceable ones to decode
// // todo: to check for replacements so we can actually not set the approx flag.
// ser := serial.FromKey(k)
// eventKey = prefixes.Event.Key(ser)
// // eventKeys = append(eventKeys, idx)
// }
// return
// })
// if chk.E(err) {
// // this means shutdown, probably
// if errors.Is(err, badger.ErrDBClosed) {
// return
// }
// }
// // todo: here we should decode replaceable events and discard the outdated versions
// if extraFilter != nil {
// // if there is an extra filter we need to fetch and decode the event to determine a
// // match.
// err = r.View(func(txn *badger.Txn) (err error) {
// opts := badger.IteratorOptions{Reverse: true}
// it := txn.NewIterator(opts)
// defer it.Close()
// for it.Seek(eventKey); it.ValidForPrefix(eventKey); it.Next() {
// item := it.Item()
// if r.HasL2 && item.ValueSize() == sha256.Size {
// // we will count this though it may not match in fact. for general,
// // simple filters there isn't likely to be an extrafilter anyway. the
// // count result can have an "approximate" flag so we flip this now.
// approx = true
// return
// }
// ev := &event.T{}
// var appr bool
// if err = item.Value(func(eventValue []byte) (err error) {
// var rem []byte
// if rem, err = r.Unmarshal(ev, eventValue); chk.E(err) {
// return
// }
// if len(rem) > 0 {
// log.T.S(rem)
// }
// if et := ev.Tags.GetFirst(tag.New("expiration")); et != nil {
// var exp uint64
// if exp, err = strconv.ParseUint(string(et.Value()), 10, 64); chk.E(err) {
// return
// }
// if int64(exp) > time.Now().Unix() {
// // this needs to be deleted
// delEvs = append(delEvs, ev.Id)
// return
// }
// }
// if ev.Kind.IsReplaceable() ||
// (ev.Kind.IsParameterizedReplaceable() &&
// ev.Tags.GetFirst(tag.New("d")) != nil) {
// // we aren't going to spend this extra time so this just flips the
// // approximate flag. generally clients are asking for counts to get
// // an outside estimate anyway, to avoid exceeding MaxLimit
// appr = true
// }
// return
// }); chk.E(err) {
// continue
// }
// if ev == nil {
// continue
// }
// if extraFilter.Matches(ev) {
// count++
// if appr {
// approx = true
// }
// return
// }
// }
// return
// })
// } else {
// count++
// }
// }
// return
// }