Add noVerify flag to SaveEvent to prevent duplicate events and enhance test reliability
- pkg/database/save-event.go - Added `noVerify` parameter to `SaveEvent` function - Added check for existing event using `GetSerialById` when `noVerify` is false - Modified logic to handle event verification based on `noVerify` flag - pkg/app/relay/server-publish.go - Added `false` as third argument to `SaveEvent` calls - pkg/database/export_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-for-tags_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-for-kinds-authors_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-for-kinds-tags_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-for-serials_test.go - Added `false` as third argument to `SaveEvent` call - main.go - Modified pprof handling to support different profiling types (cpu, memory, allocation) - Changed `Pprof` configuration from boolean to string with enum values - pkg/app/config/config.go - Changed `Pprof` field type from `bool` to `string` with enum values - pkg/database/query-for-kinds-authors-tags_test.go - Added `false` as third argument to `SaveEvent` call - pkg/version/version - Bumped version from v0.2.12 to v0.2.13 - pkg/database/fetch-event-by-serial_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-for-kinds_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/get-serials-by-range_test.go - Added `false` as third argument to `SaveEvent` call - pkg/database/query-events-multiple-param-replaceable_test.go - Added `false` as third argument to `SaveEvent` calls - pkg/database/query-events_test.go - Added `false` as third argument to `SaveEvent` calls - pkg/interfaces/store/store_interface.go - Updated `Saver` interface to include `noVerify` parameter in `SaveEvent` method - Added `SerialByIder` interface with `GetSerialById` method - pkg/database/save-event_test.go - Added `false` as third argument to `SaveEvent` calls - Added new test case for saving existing event - pkg/database/query-for-ids_test.go - Added `false` as third argument to `SaveEvent` call - pkg/protocol/ws/client.go - Changed comment about context cancellation from "context is canceled" to "context is cancelled" - pkg/app/relay/spider-fetch.go - Added signature checker for WebSocket connections - Modified logic to check for existing events before saving - Added logging and memory optimization improvements
This commit is contained in:
29
main.go
29
main.go
@@ -1,28 +1,26 @@
|
||||
// Package main is a nostr relay with a simple follow/mute list authentication
|
||||
// scheme and the new HTTP REST based protocol. Configuration is via environment
|
||||
// scheme and the new HTTP REST-based protocol. Configuration is via environment
|
||||
// variables or an optional .env file.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"orly.dev/pkg/protocol/openapi"
|
||||
"orly.dev/pkg/protocol/servemux"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/profile"
|
||||
_ "net/http/pprof"
|
||||
app2 "orly.dev/pkg/app"
|
||||
"orly.dev/pkg/app/config"
|
||||
"orly.dev/pkg/app/relay"
|
||||
"orly.dev/pkg/app/relay/options"
|
||||
"orly.dev/pkg/database"
|
||||
"orly.dev/pkg/protocol/openapi"
|
||||
"orly.dev/pkg/protocol/servemux"
|
||||
"orly.dev/pkg/utils/chk"
|
||||
"orly.dev/pkg/utils/context"
|
||||
"orly.dev/pkg/utils/interrupt"
|
||||
"orly.dev/pkg/utils/log"
|
||||
"orly.dev/pkg/utils/lol"
|
||||
"orly.dev/pkg/version"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -45,11 +43,18 @@ func main() {
|
||||
os.Exit(0)
|
||||
}
|
||||
lol.SetLogLevel(cfg.LogLevel)
|
||||
if cfg.Pprof {
|
||||
defer profile.Start(profile.MemProfile).Stop()
|
||||
go func() {
|
||||
chk.E(http.ListenAndServe("127.0.0.1:6060", nil))
|
||||
}()
|
||||
if cfg.Pprof != "" {
|
||||
switch cfg.Pprof {
|
||||
case "cpu":
|
||||
prof := profile.Start(profile.CPUProfile)
|
||||
defer prof.Stop()
|
||||
case "memory":
|
||||
prof := profile.Start(profile.MemProfile)
|
||||
defer prof.Stop()
|
||||
case "allocation":
|
||||
prof := profile.Start(profile.MemProfileAllocs)
|
||||
defer prof.Stop()
|
||||
}
|
||||
}
|
||||
c, cancel := context.Cancel(context.Bg())
|
||||
var storage *database.D
|
||||
|
||||
@@ -34,7 +34,7 @@ type C struct {
|
||||
Port int `env:"ORLY_PORT" default:"3334" usage:"port to listen on"`
|
||||
LogLevel string `env:"ORLY_LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"`
|
||||
DbLogLevel string `env:"ORLY_DB_LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"`
|
||||
Pprof bool `env:"ORLY_PPROF" default:"false" usage:"enable pprof on 127.0.0.1:6060"`
|
||||
Pprof string `env:"ORLY_PPROF" usage:"enable pprof on 127.0.0.1:6060" enum:"cpu,memory,allocation"`
|
||||
AuthRequired bool `env:"ORLY_AUTH_REQUIRED" default:"false" usage:"require authentication for all requests"`
|
||||
PublicReadable bool `env:"ORLY_PUBLIC_READABLE" default:"true" usage:"allow public read access to regardless of whether the client is authed"`
|
||||
SpiderSeeds []string `env:"ORLY_SPIDER_SEEDS" usage:"seeds to use for the spider (relays that are looked up initially to find owner relay lists) (comma separated)" default:"wss://relay.nostr.band/,wss://relay.damus.io/,wss://nostr.wine/,wss://nostr.land/,wss://theforest.nostr1.com/"`
|
||||
|
||||
@@ -88,7 +88,7 @@ func (s *Server) Publish(c context.T, evt *event.E) (err error) {
|
||||
}
|
||||
if isFollowed {
|
||||
if _, _, err = sto.SaveEvent(
|
||||
c, evt,
|
||||
c, evt, false,
|
||||
); err != nil && !errors.Is(
|
||||
err, store.ErrDupEvent,
|
||||
) {
|
||||
@@ -110,7 +110,7 @@ func (s *Server) Publish(c context.T, evt *event.E) (err error) {
|
||||
for _, pk := range owners {
|
||||
if bytes.Equal(evt.Pubkey, pk) {
|
||||
if _, _, err = sto.SaveEvent(
|
||||
c, evt,
|
||||
c, evt, false,
|
||||
); err != nil && !errors.Is(
|
||||
err, store.ErrDupEvent,
|
||||
) {
|
||||
@@ -222,7 +222,7 @@ func (s *Server) Publish(c context.T, evt *event.E) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, _, err = sto.SaveEvent(c, evt); err != nil && !errors.Is(
|
||||
if _, _, err = sto.SaveEvent(c, evt, false); err != nil && !errors.Is(
|
||||
err, store.ErrDupEvent,
|
||||
) {
|
||||
return
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"orly.dev/pkg/crypto/ec/schnorr"
|
||||
"orly.dev/pkg/database/indexes/types"
|
||||
"orly.dev/pkg/encoders/event"
|
||||
"orly.dev/pkg/encoders/filter"
|
||||
"orly.dev/pkg/encoders/hex"
|
||||
@@ -10,7 +12,9 @@ import (
|
||||
"orly.dev/pkg/protocol/ws"
|
||||
"orly.dev/pkg/utils/chk"
|
||||
"orly.dev/pkg/utils/context"
|
||||
"orly.dev/pkg/utils/errorf"
|
||||
"orly.dev/pkg/utils/log"
|
||||
"orly.dev/pkg/utils/lol"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
@@ -126,7 +130,11 @@ func (s *Server) SpiderFetch(
|
||||
var evss event.S
|
||||
var cli *ws.Client
|
||||
if cli, err = ws.RelayConnect(
|
||||
context.Bg(), seed,
|
||||
context.Bg(), seed, ws.WithSignatureChecker(
|
||||
func(e *event.E) bool {
|
||||
return true
|
||||
},
|
||||
),
|
||||
); chk.E(err) {
|
||||
err = nil
|
||||
return
|
||||
@@ -148,14 +156,37 @@ func (s *Server) SpiderFetch(
|
||||
|
||||
// If it doesn't exist or the new event is newer, store it and save to database
|
||||
if !exists || ev.CreatedAtInt64() > existing.Timestamp {
|
||||
var ser *types.Uint40
|
||||
if ser, err = s.Storage().GetSerialById(ev.Id); err == nil && ser != nil {
|
||||
err = errorf.E("event already exists: %0x", ev.Id)
|
||||
return
|
||||
} else {
|
||||
// verify the signature
|
||||
var valid bool
|
||||
if valid, err = ev.Verify(); chk.E(err) || !valid {
|
||||
continue
|
||||
}
|
||||
log.I.F("event %0x is valid", ev.Id)
|
||||
}
|
||||
|
||||
// Save the event to the database
|
||||
log.I.F("saving event:\n%s", ev.Marshal(nil))
|
||||
if _, _, err = s.Storage().SaveEvent(
|
||||
s.Ctx, ev,
|
||||
s.Ctx, ev, true, // already verified
|
||||
); chk.E(err) {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
if lol.Level.Load() == lol.Trace {
|
||||
log.T.C(
|
||||
func() string {
|
||||
return fmt.Sprintf(
|
||||
"saved event:\n%s", ev.Marshal(nil),
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
log.I.F("saved event: %0x", ev.Id)
|
||||
}
|
||||
|
||||
// Store the essential information
|
||||
pkKindMap[pkKindKey] = &IdPkTs{
|
||||
@@ -186,12 +217,11 @@ func (s *Server) SpiderFetch(
|
||||
// Nil the event in the slice to free memory
|
||||
evss[i] = nil
|
||||
}
|
||||
|
||||
chk.E(s.Storage().Sync())
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
}
|
||||
chk.E(s.Storage().Sync())
|
||||
debug.FreeOSMemory()
|
||||
|
||||
// If we're in noExtract mode, just return
|
||||
if noExtract {
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestExport(t *testing.T) {
|
||||
}
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestFetchEventBySerial(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestGetSerialById(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestGetSerialsByRange(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func (d *D) Import(rr io.Reader) {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, _, err = d.SaveEvent(d.ctx, ev); err != nil {
|
||||
if _, _, err = d.SaveEvent(d.ctx, ev, false); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) {
|
||||
baseEvent.Sign(sign)
|
||||
|
||||
// Save the base parameterized replaceable event
|
||||
if _, _, err := db.SaveEvent(ctx, baseEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, baseEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save base parameterized replaceable event: %v", err)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) {
|
||||
newerEvent.Sign(sign)
|
||||
|
||||
// Save the newer parameterized replaceable event
|
||||
if _, _, err := db.SaveEvent(ctx, newerEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, newerEvent, false); err != nil {
|
||||
t.Fatalf(
|
||||
"Failed to save newer parameterized replaceable event: %v", err,
|
||||
)
|
||||
@@ -83,7 +83,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) {
|
||||
newestEvent.Sign(sign)
|
||||
|
||||
// Save the newest parameterized replaceable event
|
||||
if _, _, err := db.SaveEvent(ctx, newestEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, newestEvent, false); err != nil {
|
||||
t.Fatalf(
|
||||
"Failed to save newest parameterized replaceable event: %v", err,
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ func setupTestDB(t *testing.T) (
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) {
|
||||
replaceableEvent.Tags = tags.New()
|
||||
replaceableEvent.Sign(sign)
|
||||
// Save the replaceable event
|
||||
if _, _, err := db.SaveEvent(ctx, replaceableEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, replaceableEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save replaceable event: %v", err)
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) {
|
||||
newerEvent.Tags = tags.New()
|
||||
newerEvent.Sign(sign)
|
||||
// Save the newer event
|
||||
if _, _, err := db.SaveEvent(ctx, newerEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, newerEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save newer event: %v", err)
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) {
|
||||
)
|
||||
|
||||
// Save the deletion event
|
||||
if _, _, err = db.SaveEvent(ctx, deletionEvent); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, deletionEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save deletion event: %v", err)
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) {
|
||||
paramEvent.Sign(sign)
|
||||
|
||||
// Save the parameterized replaceable event
|
||||
if _, _, err := db.SaveEvent(ctx, paramEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, paramEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save parameterized replaceable event: %v", err)
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) {
|
||||
paramDeletionEvent.Sign(sign)
|
||||
|
||||
// Save the parameterized deletion event
|
||||
if _, _, err := db.SaveEvent(ctx, paramDeletionEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, paramDeletionEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save parameterized deletion event: %v", err)
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) {
|
||||
paramDeletionEvent2.Sign(sign)
|
||||
|
||||
// Save the parameterized deletion event with e-tag
|
||||
if _, _, err := db.SaveEvent(ctx, paramDeletionEvent2); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, paramDeletionEvent2, false); err != nil {
|
||||
t.Fatalf(
|
||||
"Failed to save parameterized deletion event with e-tag: %v", err,
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestQueryForAuthorsTags(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestQueryForCreatedAt(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestQueryForIds(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestQueryForKindsAuthorsTags(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestQueryForKindsAuthors(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestQueryForKindsTags(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestQueryForKinds(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestQueryForSerials(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestQueryForTags(t *testing.T) {
|
||||
events = append(events, ev)
|
||||
|
||||
// Save the event to the database
|
||||
if _, _, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if _, _, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,17 @@ import (
|
||||
)
|
||||
|
||||
// SaveEvent saves an event to the database, generating all the necessary indexes.
|
||||
func (d *D) SaveEvent(c context.T, ev *event.E) (kc, vc int, err error) {
|
||||
// Get a buffer from the pool
|
||||
buf := new(bytes.Buffer)
|
||||
// Marshal the event to binary
|
||||
ev.MarshalBinary(buf)
|
||||
func (d *D) SaveEvent(c context.T, ev *event.E, noVerify bool) (
|
||||
kc, vc int, err error,
|
||||
) {
|
||||
if !noVerify {
|
||||
// check if the event already exists
|
||||
var ser *types.Uint40
|
||||
if ser, err = d.GetSerialById(ev.Id); err == nil && ser != nil {
|
||||
err = errorf.E("event already exists: %0x", ev.Id)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// check if an existing delete event references this event submission
|
||||
if ev.Kind.IsParameterizedReplaceable() {
|
||||
@@ -59,7 +65,7 @@ func (d *D) SaveEvent(c context.T, ev *event.E) (kc, vc int, err error) {
|
||||
// stable value but refers to any event from the author, of the
|
||||
// kind, with the identifier. so we need to fetch the full ID index
|
||||
// to get the timestamp and ensure that the event post-dates it.
|
||||
// otherwise it should be rejected.
|
||||
// otherwise, it should be rejected.
|
||||
var idPkTss []*store.IdPkTs
|
||||
for _, ser := range sers {
|
||||
var fidpk *store.IdPkTs
|
||||
@@ -88,7 +94,6 @@ func (d *D) SaveEvent(c context.T, ev *event.E) (kc, vc int, err error) {
|
||||
}
|
||||
} else {
|
||||
var idxs []Range
|
||||
// log.I.S(ev.Pubkey)
|
||||
if idxs, err = GetIndexesFromFilter(
|
||||
&filter.F{
|
||||
Authors: tag.New(ev.Pubkey),
|
||||
@@ -98,7 +103,6 @@ func (d *D) SaveEvent(c context.T, ev *event.E) (kc, vc int, err error) {
|
||||
); chk.E(err) {
|
||||
return
|
||||
}
|
||||
// log.I.S(idxs)
|
||||
var sers types.Uint40s
|
||||
for _, idx := range idxs {
|
||||
var s types.Uint40s
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestSaveEvents(t *testing.T) {
|
||||
|
||||
// Save the event to the database
|
||||
var k, v int
|
||||
if k, v, err = db.SaveEvent(ctx, ev); err != nil {
|
||||
if k, v, err = db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event #%d: %v", eventCount+1, err)
|
||||
}
|
||||
kc += k
|
||||
@@ -125,7 +125,7 @@ func TestDeletionEventWithETagRejection(t *testing.T) {
|
||||
regularEvent.Sign(sign)
|
||||
|
||||
// Save the regular event
|
||||
if _, _, err := db.SaveEvent(ctx, regularEvent); err != nil {
|
||||
if _, _, err := db.SaveEvent(ctx, regularEvent, false); err != nil {
|
||||
t.Fatalf("Failed to save regular event: %v", err)
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func TestDeletionEventWithETagRejection(t *testing.T) {
|
||||
deletionEvent.Sign(sign)
|
||||
|
||||
// Try to save the deletion event, it should be rejected
|
||||
_, _, err = db.SaveEvent(ctx, deletionEvent)
|
||||
_, _, err = db.SaveEvent(ctx, deletionEvent, false)
|
||||
if err == nil {
|
||||
t.Fatal("Expected deletion event with e-tag to be rejected, but it was accepted")
|
||||
}
|
||||
@@ -154,6 +154,66 @@ func TestDeletionEventWithETagRejection(t *testing.T) {
|
||||
// Verify the error message
|
||||
expectedError := "deletion events referencing other events with 'e' tag are not allowed"
|
||||
if err.Error() != expectedError {
|
||||
t.Fatalf("Expected error message '%s', got '%s'", expectedError, err.Error())
|
||||
t.Fatalf(
|
||||
"Expected error message '%s', got '%s'", expectedError, err.Error(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSaveExistingEvent tests that attempting to save an event that already exists
|
||||
// returns an error.
|
||||
func TestSaveExistingEvent(t *testing.T) {
|
||||
// Create a temporary directory for the database
|
||||
tempDir, err := os.MkdirTemp("", "test-db-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temporary directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir) // Clean up after the test
|
||||
|
||||
// Create a context and cancel function for the database
|
||||
ctx, cancel := context.Cancel(context.Bg())
|
||||
defer cancel()
|
||||
|
||||
// Initialize the database
|
||||
db, err := New(ctx, cancel, tempDir, "info")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create database: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Create a signer
|
||||
sign := new(p256k.Signer)
|
||||
if err := sign.Generate(); chk.E(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create an event
|
||||
ev := event.New()
|
||||
ev.Kind = kind.TextNote // Kind 1 is a text note
|
||||
ev.Pubkey = sign.Pub()
|
||||
ev.CreatedAt = new(timestamp.T)
|
||||
ev.CreatedAt.V = timestamp.Now().V
|
||||
ev.Content = []byte("Test event")
|
||||
ev.Tags = tags.New()
|
||||
ev.Sign(sign)
|
||||
|
||||
// Save the event for the first time
|
||||
if _, _, err := db.SaveEvent(ctx, ev, false); err != nil {
|
||||
t.Fatalf("Failed to save event: %v", err)
|
||||
}
|
||||
|
||||
// Try to save the same event again, it should be rejected
|
||||
_, _, err = db.SaveEvent(ctx, ev, false)
|
||||
if err == nil {
|
||||
t.Fatal("Expected error when saving an existing event, but got nil")
|
||||
}
|
||||
|
||||
// Verify the error message
|
||||
expectedErrorPrefix := "event already exists: "
|
||||
if !bytes.HasPrefix([]byte(err.Error()), []byte(expectedErrorPrefix)) {
|
||||
t.Fatalf(
|
||||
"Expected error message to start with '%s', got '%s'",
|
||||
expectedErrorPrefix, err.Error(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package store
|
||||
import (
|
||||
"io"
|
||||
"orly.dev/pkg/app/config"
|
||||
"orly.dev/pkg/database/indexes/types"
|
||||
"orly.dev/pkg/encoders/event"
|
||||
"orly.dev/pkg/encoders/eventid"
|
||||
"orly.dev/pkg/encoders/eventidserial"
|
||||
@@ -33,6 +34,7 @@ type I interface {
|
||||
LogLeveler
|
||||
EventIdSerialer
|
||||
Initer
|
||||
SerialByIder
|
||||
}
|
||||
|
||||
type Initer interface {
|
||||
@@ -81,7 +83,7 @@ type Deleter interface {
|
||||
|
||||
type Saver interface {
|
||||
// SaveEvent is called once relay.AcceptEvent reports true.
|
||||
SaveEvent(c context.T, ev *event.E) (kc, vc int, err error)
|
||||
SaveEvent(c context.T, ev *event.E, noVerify bool) (kc, vc int, err error)
|
||||
}
|
||||
|
||||
type Importer interface {
|
||||
@@ -129,3 +131,7 @@ type EventIdSerialer interface {
|
||||
err error,
|
||||
)
|
||||
}
|
||||
|
||||
type SerialByIder interface {
|
||||
GetSerialById(id []byte) (ser *types.Uint40, err error)
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ type writeRequest struct {
|
||||
}
|
||||
|
||||
// NewRelay returns a new relay. The relay connection will be closed when the
|
||||
// context is canceled.
|
||||
// context is cancelled.
|
||||
func NewRelay(c context.T, url string, opts ...RelayOption) *Client {
|
||||
ctx, cancel := context.Cancel(c)
|
||||
r := &Client{
|
||||
|
||||
@@ -1 +1 @@
|
||||
v0.2.12
|
||||
v0.2.13
|
||||
Reference in New Issue
Block a user