136 lines
4.1 KiB
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
|
|
// }
|