Skip to content

Commit 2e28cc8

Browse files
committed
sdk/hints: HintsDB.GetDetailedScores()
1 parent 05e2018 commit 2e28cc8

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

sdk/hints/badgerh/db.go

+53
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,59 @@ func (bh *BadgerHints) TopN(pubkey string, n int) []string {
112112
return result
113113
}
114114

115+
func (bh *BadgerHints) GetDetailedScores(pubkey string, n int) []hints.RelayScores {
116+
type relayScore struct {
117+
relay string
118+
tss timestamps
119+
score int64
120+
}
121+
122+
scores := make([]relayScore, 0, n)
123+
err := bh.db.View(func(txn *badger.Txn) error {
124+
prefix, _ := hex.DecodeString(pubkey)
125+
it := txn.NewIterator(badger.DefaultIteratorOptions)
126+
defer it.Close()
127+
128+
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
129+
item := it.Item()
130+
k := item.Key()
131+
relay := string(k[32:])
132+
133+
var tss timestamps
134+
err := item.Value(func(v []byte) error {
135+
tss = parseValue(v)
136+
return nil
137+
})
138+
if err != nil {
139+
return err
140+
}
141+
142+
scores = append(scores, relayScore{relay, tss, tss.sum()})
143+
}
144+
return nil
145+
})
146+
if err != nil {
147+
return nil
148+
}
149+
150+
slices.SortFunc(scores, func(a, b relayScore) int {
151+
return int(b.score - a.score)
152+
})
153+
154+
result := make([]hints.RelayScores, 0, n)
155+
for i, rs := range scores {
156+
if i >= n {
157+
break
158+
}
159+
result = append(result, hints.RelayScores{
160+
Relay: rs.relay,
161+
Scores: rs.tss,
162+
Sum: rs.score,
163+
})
164+
}
165+
return result
166+
}
167+
115168
func (bh *BadgerHints) PrintScores() {
116169
fmt.Println("= print scores")
117170

sdk/hints/interface.go

+7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@ package hints
22

33
import "github.com/nbd-wtf/go-nostr"
44

5+
type RelayScores struct {
6+
Relay string
7+
Scores [4]nostr.Timestamp
8+
Sum int64
9+
}
10+
511
type HintsDB interface {
612
TopN(pubkey string, n int) []string
713
Save(pubkey string, relay string, key HintKey, score nostr.Timestamp)
814
PrintScores()
15+
GetDetailedScores(pubkey string, n int) []RelayScores
916
}

sdk/hints/lmdbh/db.go

+56
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,62 @@ func (lh *LMDBHints) PrintScores() {
182182
}
183183
}
184184

185+
func (lh *LMDBHints) GetDetailedScores(pubkey string, n int) []hints.RelayScores {
186+
type relayScore struct {
187+
relay string
188+
tss timestamps
189+
score int64
190+
}
191+
192+
scores := make([]relayScore, 0, n)
193+
err := lh.env.View(func(txn *lmdb.Txn) error {
194+
txn.RawRead = true
195+
196+
cursor, err := txn.OpenCursor(lh.dbi)
197+
if err != nil {
198+
return err
199+
}
200+
defer cursor.Close()
201+
202+
prefix, _ := hex.DecodeString(pubkey)
203+
k, v, err := cursor.Get(prefix, nil, lmdb.SetRange)
204+
for ; err == nil; k, v, err = cursor.Get(nil, nil, lmdb.Next) {
205+
// check if we're still in the prefix range
206+
if len(k) < 32 || !bytes.Equal(k[:32], prefix) {
207+
break
208+
}
209+
210+
relay := string(k[32:])
211+
tss := parseValue(v)
212+
scores = append(scores, relayScore{relay, tss, tss.sum()})
213+
}
214+
if err != nil && !lmdb.IsNotFound(err) {
215+
return err
216+
}
217+
return nil
218+
})
219+
if err != nil {
220+
return nil
221+
}
222+
223+
slices.SortFunc(scores, func(a, b relayScore) int {
224+
return int(b.score - a.score)
225+
})
226+
227+
result := make([]hints.RelayScores, 0, n)
228+
for i, rs := range scores {
229+
if i >= n {
230+
break
231+
}
232+
result = append(result, hints.RelayScores{
233+
Relay: rs.relay,
234+
Scores: rs.tss,
235+
Sum: rs.score,
236+
})
237+
}
238+
return result
239+
}
240+
185241
type timestamps [4]nostr.Timestamp
186242

187243
func (tss timestamps) sum() int64 {

sdk/hints/memoryh/db.go

+25
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,31 @@ func (db *HintDB) PrintScores() {
108108
}
109109
}
110110

111+
func (db *HintDB) GetDetailedScores(pubkey string, n int) []hints.RelayScores {
112+
db.Lock()
113+
defer db.Unlock()
114+
115+
result := make([]hints.RelayScores, 0, n)
116+
if rfpk, ok := db.OrderedRelaysByPubKey[pubkey]; ok {
117+
// sort everything from scratch
118+
slices.SortFunc(rfpk.Entries, func(a, b RelayEntry) int {
119+
return int(b.Sum() - a.Sum())
120+
})
121+
122+
for i, re := range rfpk.Entries {
123+
if i >= n {
124+
break
125+
}
126+
result = append(result, hints.RelayScores{
127+
Relay: db.RelayBySerial[re.Relay],
128+
Scores: re.Timestamps,
129+
Sum: re.Sum(),
130+
})
131+
}
132+
}
133+
return result
134+
}
135+
111136
type RelaysForPubKey struct {
112137
Entries []RelayEntry
113138
}

sdk/hints/sqlh/db.go

+34
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,40 @@ func (sh SQLHints) PrintScores() {
209209
}
210210
}
211211

212+
func (sh SQLHints) GetDetailedScores(pubkey string, n int) []hints.RelayScores {
213+
result := make([]hints.RelayScores, 0, n)
214+
215+
rows, err := sh.Queryx(
216+
`SELECT relay, last_fetch_attempt, most_recent_event_fetched, last_in_relay_list, last_in_hint,
217+
coalesce(`+sh.scorePartialQuery()+`, 0) AS score
218+
FROM nostr_sdk_pubkey_relays
219+
WHERE pubkey = `+sh.interop.generateBindingSpots(0, 1)+`
220+
ORDER BY score DESC
221+
LIMIT `+sh.interop.generateBindingSpots(1, 1),
222+
pubkey, n)
223+
if err != nil {
224+
return nil
225+
}
226+
defer rows.Close()
227+
228+
for rows.Next() {
229+
var rs hints.RelayScores
230+
var scores [4]sql.NullInt64
231+
err := rows.Scan(&rs.Relay, &scores[0], &scores[1], &scores[2], &scores[3], &rs.Sum)
232+
if err != nil {
233+
continue
234+
}
235+
for i, s := range scores {
236+
if s.Valid {
237+
rs.Scores[i] = nostr.Timestamp(s.Int64)
238+
}
239+
}
240+
result = append(result, rs)
241+
}
242+
243+
return result
244+
}
245+
212246
func (sh SQLHints) scorePartialQuery() string {
213247
calc := strings.Builder{}
214248
calc.Grow(len(hints.KeyBasePoints) * (11 + 25 + 32 + 4 + 4 + 9 + 12 + 25 + 12 + 25 + 19 + 3))

0 commit comments

Comments
 (0)