interface.go raw
1 package nostr
2
3 import (
4 "context"
5 "errors"
6 "slices"
7 )
8
9 type RelayStore interface {
10 Publish(context.Context, Event) error
11 QueryEvents(context.Context, Filter) (chan *Event, error)
12 QuerySync(context.Context, Filter) ([]*Event, error)
13 }
14
15 var (
16 _ RelayStore = (*Relay)(nil)
17 _ RelayStore = (*MultiStore)(nil)
18 )
19
20 type MultiStore []RelayStore
21
22 func (multi MultiStore) Publish(ctx context.Context, event Event) error {
23 errs := make([]error, len(multi))
24 for i, s := range multi {
25 errs[i] = s.Publish(ctx, event)
26 }
27 return errors.Join(errs...)
28 }
29
30 func (multi MultiStore) QueryEvents(ctx context.Context, filter Filter) (chan *Event, error) {
31 multich := make(chan *Event)
32
33 errs := make([]error, len(multi))
34 var good bool
35 for i, s := range multi {
36 ch, err := s.QueryEvents(ctx, filter)
37 errs[i] = err
38 if err == nil {
39 good = true
40 go func(ch chan *Event) {
41 for evt := range ch {
42 multich <- evt
43 }
44 }(ch)
45 }
46 }
47
48 if good {
49 return multich, nil
50 } else {
51 return nil, errors.Join(errs...)
52 }
53 }
54
55 func (multi MultiStore) QuerySync(ctx context.Context, filter Filter) ([]*Event, error) {
56 errs := make([]error, len(multi))
57 events := make([]*Event, 0, max(filter.Limit, 250))
58 for i, s := range multi {
59 res, err := s.QuerySync(ctx, filter)
60 errs[i] = err
61 events = append(events, res...)
62 }
63 slices.SortFunc(events, func(a, b *Event) int {
64 if b.CreatedAt > a.CreatedAt {
65 return 1
66 } else if b.CreatedAt < a.CreatedAt {
67 return -1
68 }
69 return 0
70 })
71 return events, errors.Join(errs...)
72 }
73