eventstore: QueryEvents() to take a maxLimit param now so everything is clearer.
This commit is contained in:
@@ -108,15 +108,15 @@ func main() {
|
||||
|
||||
### But I don't want to write my own database!
|
||||
|
||||
Fear no more. Using the https://fiatjaf.com/nostr/eventstore module you get a bunch of compatible databases out of the box and you can just plug them into your relay. For example, [sqlite](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/sqlite3):
|
||||
Fear no more. Using the https://fiatjaf.com/nostr/eventstore module you get a bunch of compatible databases out of the box and you can just plug them into your relay. For example, [sqlite](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/lmdb):
|
||||
|
||||
```go
|
||||
db := sqlite3.SQLite3Backend{DatabaseURL: "/tmp/khatru-sqlite-tmp"}
|
||||
db := lmdb.LMDBackend{Path: "/tmp/khatru-lmdb-tmp"}
|
||||
if err := db.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 500)
|
||||
```
|
||||
|
||||
### But I don't want to write a bunch of custom policies!
|
||||
|
||||
@@ -18,7 +18,7 @@ type EventStoreBlobIndexWrapper struct {
|
||||
|
||||
func (es EventStoreBlobIndexWrapper) Keep(ctx context.Context, blob BlobDescriptor, pubkey nostr.PubKey) error {
|
||||
next, stop := iter.Pull(
|
||||
es.Store.QueryEvents(nostr.Filter{Authors: []nostr.PubKey{pubkey}, Kinds: []nostr.Kind{24242}, Tags: nostr.TagMap{"x": []string{blob.SHA256}}}),
|
||||
es.Store.QueryEvents(nostr.Filter{Authors: []nostr.PubKey{pubkey}, Kinds: []nostr.Kind{24242}, Tags: nostr.TagMap{"x": []string{blob.SHA256}}}, 1),
|
||||
)
|
||||
defer stop()
|
||||
|
||||
@@ -46,7 +46,7 @@ func (es EventStoreBlobIndexWrapper) List(ctx context.Context, pubkey nostr.PubK
|
||||
for evt := range es.Store.QueryEvents(nostr.Filter{
|
||||
Authors: []nostr.PubKey{pubkey},
|
||||
Kinds: []nostr.Kind{24242},
|
||||
}) {
|
||||
}, 1000) {
|
||||
yield(es.parseEvent(evt))
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func (es EventStoreBlobIndexWrapper) List(ctx context.Context, pubkey nostr.PubK
|
||||
|
||||
func (es EventStoreBlobIndexWrapper) Get(ctx context.Context, sha256 string) (*BlobDescriptor, error) {
|
||||
next, stop := iter.Pull(
|
||||
es.Store.QueryEvents(nostr.Filter{Tags: nostr.TagMap{"x": []string{sha256}}, Kinds: []nostr.Kind{24242}, Limit: 1}),
|
||||
es.Store.QueryEvents(nostr.Filter{Tags: nostr.TagMap{"x": []string{sha256}}, Kinds: []nostr.Kind{24242}, Limit: 1}, 1),
|
||||
)
|
||||
|
||||
defer stop()
|
||||
@@ -74,8 +74,7 @@ func (es EventStoreBlobIndexWrapper) Delete(ctx context.Context, sha256 string,
|
||||
Tags: nostr.TagMap{"x": []string{sha256}},
|
||||
Kinds: []nostr.Kind{24242},
|
||||
Limit: 1,
|
||||
},
|
||||
),
|
||||
}, 1),
|
||||
)
|
||||
|
||||
defer stop()
|
||||
|
||||
@@ -34,18 +34,3 @@ func main () {
|
||||
```
|
||||
|
||||
Note that in this case we're using the [LMDB](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/lmdb) adapter for normal queries and it explicitly rejects any filter that contains a `Search` field, while [Bluge](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/bluge) rejects any filter _without_ a `Search` value, which make them pair well together.
|
||||
|
||||
Other adapters, like [SQLite](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/sqlite3), implement search functionality on their own, so if you don't want to use that you would have to have a middleware between, like:
|
||||
|
||||
```go
|
||||
relay.StoreEvent = policies.SeqStore(db.SaveEvent, search.SaveEvent)
|
||||
relay.QueryStored = func (ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] {
|
||||
if len(filter.Search) > 0 {
|
||||
return search.QueryEvents(ctx, filter)
|
||||
} else {
|
||||
filterNoSearch := filter
|
||||
filterNoSearch.Search = ""
|
||||
return normal.QueryEvents(ctx, filterNoSearch)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 500)
|
||||
|
||||
fmt.Println("running on :3334")
|
||||
http.ListenAndServe(":3334", relay)
|
||||
@@ -44,10 +44,6 @@ func main() {
|
||||
|
||||
[LMDB](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/lmdb) works the same way.
|
||||
|
||||
[SQLite](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/sqlite3) also stores things locally so it only needs a `Path`.
|
||||
|
||||
[PostgreSQL](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/postgresql) and [MySQL](https://pkg.go.dev/fiatjaf.com/nostr/eventstore/mysql) use remote connections to database servers, so they take a `DatabaseURL` parameter, but after that it's the same.
|
||||
|
||||
## Using two at a time
|
||||
|
||||
If you want to use two different adapters at the same time that's easy. Just use the `policies.Seq*` functions:
|
||||
|
||||
@@ -21,7 +21,7 @@ groupsRelay, _ := khatru29.Init(relay29.Options{Domain: "example.com", DB: group
|
||||
publicStore := slicestore.SliceStore{}
|
||||
publicStore.Init()
|
||||
publicRelay := khatru.NewRelay()
|
||||
publicRelay.UseEventStore(publicStore)
|
||||
publicRelay.UseEventStore(publicStore, 1000)
|
||||
// ...
|
||||
|
||||
// a higher-level relay that just routes between the two above
|
||||
|
||||
@@ -31,15 +31,15 @@ relay.Info.Description = "this is my custom relay"
|
||||
relay.Info.Icon = "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fliquipedia.net%2Fcommons%2Fimages%2F3%2F35%2FSCProbe.jpg&f=1&nofb=1&ipt=0cbbfef25bce41da63d910e86c3c343e6c3b9d63194ca9755351bb7c2efa3359&ipo=images"
|
||||
```
|
||||
|
||||
Now we must set up the basic functions for accepting events and answering queries. We could make our own querying engine from scratch, but we can also use [eventstore](https://fiatjaf.com/nostr/eventstore). In this example we'll use the SQLite adapter:
|
||||
Now we must set up the basic functions for accepting events and answering queries. We could make our own querying engine from scratch, but we can also use [eventstore](https://pkg.go.dev/fiatjaf.com/nostr/eventstore). In this example we'll use the Badger adapter:
|
||||
|
||||
```go
|
||||
db := sqlite3.SQLite3Backend{DatabaseURL: "/tmp/khatru-sqlite-tmp"}
|
||||
db := badger.BadgerBackend{Path: "/tmp/khatru-badger-tmp"}
|
||||
if err := db.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 500)
|
||||
```
|
||||
|
||||
These are lists of functions that will be called in order every time an `EVENT` is received, or a `REQ` query is received. You can add more than one handler there, you can have a function that reads from some other server, but just in some cases, you can do anything.
|
||||
|
||||
@@ -24,7 +24,7 @@ features:
|
||||
- title: It plugs into event stores easily
|
||||
icon: 📦
|
||||
link: /core/eventstore
|
||||
details: khatru's companion, the `eventstore` library, provides all methods for storing and querying events efficiently from SQLite, LMDB, Postgres, Badger and others.
|
||||
details: khatru's companion, the `eventstore` library, provides all methods for storing and querying events efficiently from LMDB, Badger and others.
|
||||
- title: It supports NIP-42 AUTH
|
||||
icon: 🪪
|
||||
link: /core/auth
|
||||
@@ -48,7 +48,7 @@ func main() {
|
||||
relay := khatru.NewRelay()
|
||||
db := badger.BadgerBackend{Path: "/tmp/khatru-badgern-tmp"}
|
||||
db.Init()
|
||||
relay.UseEventStore(db)
|
||||
relay.UseEventStore(db, 400)
|
||||
http.ListenAndServe(":3334", relay)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 400)
|
||||
|
||||
relay.Negentropy = true
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 400)
|
||||
|
||||
fmt.Println("running on :3334")
|
||||
http.ListenAndServe(":3334", relay)
|
||||
|
||||
@@ -20,7 +20,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 400)
|
||||
|
||||
bdb := &badger.BadgerBackend{Path: "/tmp/khatru-badger-blossom-tmp"}
|
||||
if err := bdb.Init(); err != nil {
|
||||
|
||||
@@ -21,7 +21,7 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
relay.UseEventstore(db)
|
||||
relay.UseEventstore(db, 400)
|
||||
|
||||
relay.OnEvent = policies.PreventTooManyIndexableTags(10, nil, nil)
|
||||
relay.OnRequest = policies.NoComplexFilters
|
||||
|
||||
@@ -15,17 +15,17 @@ func main() {
|
||||
db1 := &slicestore.SliceStore{}
|
||||
db1.Init()
|
||||
r1 := khatru.NewRelay()
|
||||
r1.UseEventstore(db1)
|
||||
r1.UseEventstore(db1, 400)
|
||||
|
||||
db2 := &badger.BadgerBackend{Path: "/tmp/t"}
|
||||
db2.Init()
|
||||
r2 := khatru.NewRelay()
|
||||
r2.UseEventstore(db2)
|
||||
r2.UseEventstore(db2, 400)
|
||||
|
||||
db3 := &slicestore.SliceStore{}
|
||||
db3.Init()
|
||||
r3 := khatru.NewRelay()
|
||||
r3.UseEventstore(db3)
|
||||
r3.UseEventstore(db3, 400)
|
||||
|
||||
router := khatru.NewRouter()
|
||||
|
||||
|
||||
@@ -117,9 +117,14 @@ type Relay struct {
|
||||
expirationManager *expirationManager
|
||||
}
|
||||
|
||||
func (rl *Relay) UseEventstore(store eventstore.Store) {
|
||||
// UseEventstore hooks up an eventstore.Store into the relay in the default way.
|
||||
// It should be used in 85% of the cases, when you don't want to do any complicated scheme with your event storage.
|
||||
//
|
||||
// maxQueryLimit is the default max limit to be enforced when querying events, to prevent users for downloading way
|
||||
// too much, setting it to something like 500 or 1000 should be ok in most cases.
|
||||
func (rl *Relay) UseEventstore(store eventstore.Store, maxQueryLimit int) {
|
||||
rl.QueryStored = func(ctx context.Context, filter nostr.Filter) iter.Seq[nostr.Event] {
|
||||
return store.QueryEvents(filter)
|
||||
return store.QueryEvents(filter, maxQueryLimit)
|
||||
}
|
||||
rl.Count = func(ctx context.Context, filter nostr.Filter) (uint32, error) {
|
||||
return store.CountEvents(filter)
|
||||
|
||||
@@ -24,7 +24,7 @@ func FuzzReplaceableEvents(f *testing.F) {
|
||||
relay := NewRelay()
|
||||
store := &lmdb.LMDBBackend{Path: "/tmp/fuzz"}
|
||||
store.Init()
|
||||
relay.UseEventstore(store)
|
||||
relay.UseEventstore(store, 4000)
|
||||
|
||||
defer store.Close()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
|
||||
store := &slicestore.SliceStore{}
|
||||
store.Init()
|
||||
|
||||
relay.UseEventstore(store)
|
||||
relay.UseEventstore(store, 400)
|
||||
|
||||
// start test server
|
||||
server := httptest.NewServer(relay)
|
||||
@@ -239,7 +239,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
|
||||
relay.expirationManager.interval = 3 * time.Second // check every 3 seconds
|
||||
store := &slicestore.SliceStore{}
|
||||
store.Init()
|
||||
relay.UseEventstore(store)
|
||||
relay.UseEventstore(store, 400)
|
||||
|
||||
// start test server
|
||||
server := httptest.NewServer(relay)
|
||||
|
||||
Reference in New Issue
Block a user