diff --git a/lib/rep/replicator.go b/lib/rep/replicator.go index 43bda0b..93c76ca 100644 --- a/lib/rep/replicator.go +++ b/lib/rep/replicator.go @@ -2,6 +2,7 @@ package rep import ( "io" + "log" "net" "os" "sync" @@ -94,41 +95,49 @@ func Open(app App, conf Config) (*Replicator, error) { rep.client = newClient(rep.conf.PrimaryEndpoint, rep.conf.ReplicationPSK, rep.conf.NetTimeout) if err := rep.initDirectories(); err != nil { + log.Printf("Failed to init directories: %v", err) return nil, err } if err := rep.acquireLock(); err != nil { rep.Close() + log.Printf("Failed to acquire lock: %v", err) return nil, err } if err := rep.loadLocalState(); err != nil { rep.Close() + log.Printf("Failed to load local state: %v", err) return nil, err } if err := rep.openWAL(); err != nil { rep.Close() + log.Printf("Failed to open WAL: %v", err) return nil, err } if err := rep.recvStateIfNecessary(); err != nil { rep.Close() + log.Printf("Failed to recv state: %v", err) return nil, err } if err := rep.app.InitStorage(); err != nil { rep.Close() + log.Printf("Failed to init storage: %v", err) return nil, err } if err := rep.replay(); err != nil { rep.Close() + log.Printf("Failed to replay: %v", err) return nil, err } if err := rep.app.LoadFromStorage(); err != nil { rep.Close() + log.Printf("Failed to load from storage: %v", err) return nil, err } diff --git a/mdb/collection.go b/mdb/collection.go index d044286..3a15fb1 100644 --- a/mdb/collection.go +++ b/mdb/collection.go @@ -275,6 +275,9 @@ func (c *Collection[T]) delete(tx *Snapshot, itemID uint64) error { } func (c *Collection[T]) Count(tx *Snapshot) int { + if tx == nil { + tx = c.db.Snapshot() + } return c.ByID.Count(tx) } diff --git a/mdb/db-testlist_test.go b/mdb/db-testlist_test.go deleted file mode 100644 index 80626fd..0000000 --- a/mdb/db-testlist_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package mdb - -import ( - "fmt" - "reflect" - "testing" -) - -func TestDBList(t *testing.T) { - db := NewTestDBPrimary(t, t.TempDir()) - - var ( - user1 = User{ - ID: NewID(), - Name: "User1", - Email: "user1@gmail.com", - } - - user2 = User{ - ID: NewID(), - Name: "User2", - Email: "user2@gmail.com", - } - - user3 = User{ - ID: NewID(), - Name: "User3", - Email: "user3@gmail.com", - } - user1Data = make([]UserDataItem, 10) - user2Data = make([]UserDataItem, 4) - user3Data = make([]UserDataItem, 8) - ) - - err := db.Update(func(tx *Snapshot) error { - if err := db.Users.Insert(tx, &user1); err != nil { - return err - } - - if err := db.Users.Insert(tx, &user2); err != nil { - return err - } - - for i := range user1Data { - user1Data[i] = UserDataItem{ - ID: NewID(), - UserID: user1.ID, - Name: fmt.Sprintf("Name1: %d", i), - Data: fmt.Sprintf("Data: %d", i), - } - - if err := db.UserData.Insert(tx, &user1Data[i]); err != nil { - return err - } - } - - for i := range user2Data { - user2Data[i] = UserDataItem{ - ID: NewID(), - UserID: user2.ID, - Name: fmt.Sprintf("Name2: %d", i), - Data: fmt.Sprintf("Data: %d", i), - } - - if err := db.UserData.Insert(tx, &user2Data[i]); err != nil { - return err - } - } - - for i := range user3Data { - user3Data[i] = UserDataItem{ - ID: NewID(), - UserID: user3.ID, - Name: fmt.Sprintf("Name3: %d", i), - Data: fmt.Sprintf("Data: %d", i), - } - - if err := db.UserData.Insert(tx, &user3Data[i]); err != nil { - return err - } - } - - return nil - }) - - if err != nil { - t.Fatal(err) - } - - type TestCase struct { - Name string - Args ListArgs[UserDataItem] - Expected []UserDataItem - } - - cases := []TestCase{ - { - Name: "User1 all", - Args: ListArgs[UserDataItem]{ - After: &UserDataItem{ - UserID: user1.ID, - }, - While: func(item *UserDataItem) bool { - return item.UserID == user1.ID - }, - }, - Expected: user1Data, - }, { - Name: "User1 limited", - Args: ListArgs[UserDataItem]{ - After: &UserDataItem{ - UserID: user1.ID, - }, - While: func(item *UserDataItem) bool { - return item.UserID == user1.ID - }, - Limit: 4, - }, - Expected: user1Data[:4], - }, - } - - for _, tc := range cases { - t.Run(tc.Name, func(t *testing.T) { - tx := db.Snapshot() - l := db.UserData.ByName.List(tx, &tc.Args, nil) - if len(l) != len(tc.Expected) { - t.Fatal(tc.Name, l) - } - - for i := range l { - if !reflect.DeepEqual(*l[i], tc.Expected[i]) { - t.Fatal(tc.Name, l) - } - } - }) - } -} diff --git a/mdb/index.go b/mdb/index.go index f28ac7a..431af93 100644 --- a/mdb/index.go +++ b/mdb/index.go @@ -139,59 +139,6 @@ func (i *Index[T]) DescendAfter(tx *Snapshot, after *T, each func(*T) bool) { }) } -type ListArgs[T any] struct { - Desc bool // True for descending order, otherwise ascending. - After *T // If after is given, iterate after (and including) the value. - While func(*T) bool // Continue iterating until While is false. - Limit int // Maximum number of items to return. 0 => All. -} - -func (i *Index[T]) List(tx *Snapshot, args *ListArgs[T], out []*T) []*T { - tx = i.ensureSnapshot(tx) - if args == nil { - args = &ListArgs[T]{} - } - - if args.Limit < 0 { - return nil - } - - if args.While == nil { - args.While = func(*T) bool { return true } - } - - size := args.Limit - if size == 0 { - size = 32 // Why not? - } - - items := out[:0] - - each := func(item *T) bool { - if !args.While(item) { - return false - } - items = append(items, item) - return args.Limit == 0 || len(items) < args.Limit - } - - if args.Desc { - if args.After != nil { - i.DescendAfter(tx, args.After, each) - } else { - i.Descend(tx, each) - } - } else { - if args.After != nil { - i.AscendAfter(tx, args.After, each) - } else { - i.Ascend(tx, each) - } - } - - return items -} - func (i *Index[T]) Count(tx *Snapshot) int { tx = i.ensureSnapshot(tx) return i.btree(tx).Len()