From aadbd5adf3193ee20b9a995d71c4c1572633b5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Guillot?= Date: Sat, 24 Jun 2023 12:56:53 -0700 Subject: [PATCH] Improve entry existance check to make better use of index --- storage/entry.go | 32 ++++++++++++++++++++++---------- storage/feed.go | 14 ++++++++++++-- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/storage/entry.go b/storage/entry.go index 47151579..5dbb9c04 100644 --- a/storage/entry.go +++ b/storage/entry.go @@ -219,15 +219,17 @@ func (s *Storage) updateEntry(tx *sql.Tx, entry *model.Entry) error { } // entryExists checks if an entry already exists based on its hash when refreshing a feed. -func (s *Storage) entryExists(tx *sql.Tx, entry *model.Entry) bool { +func (s *Storage) entryExists(tx *sql.Tx, entry *model.Entry) (bool, error) { var result bool - tx.QueryRow( - `SELECT true FROM entries WHERE user_id=$1 AND feed_id=$2 AND hash=$3`, - entry.UserID, - entry.FeedID, - entry.Hash, - ).Scan(&result) - return result + + // Note: This query uses entries_feed_id_hash_key index (filtering on user_id is not necessary). + err := tx.QueryRow(`SELECT true FROM entries WHERE feed_id=$1 AND hash=$2`, entry.FeedID, entry.Hash).Scan(&result) + + if err != nil && err != sql.ErrNoRows { + return result, fmt.Errorf(`store: unable to check if entry exists: %v`, err) + } + + return result, nil } // GetReadTime fetches the read time of an entry based on its hash, and the feed id and user id from the feed. @@ -274,7 +276,15 @@ func (s *Storage) RefreshFeedEntries(userID, feedID int64, entries model.Entries return fmt.Errorf(`store: unable to start transaction: %v`, err) } - if s.entryExists(tx, entry) { + entryExists, err := s.entryExists(tx, entry) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf(`store: unable to rollback transaction: %v (rolled back due to: %v)`, rollbackErr, err) + } + return err + } + + if entryExists { if updateExistingEntries { err = s.updateEntry(tx, entry) } @@ -283,7 +293,9 @@ func (s *Storage) RefreshFeedEntries(userID, feedID int64, entries model.Entries } if err != nil { - tx.Rollback() + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf(`store: unable to rollback transaction: %v (rolled back due to: %v)`, rollbackErr, err) + } return err } diff --git a/storage/feed.go b/storage/feed.go index 62be0009..df36bdec 100644 --- a/storage/feed.go +++ b/storage/feed.go @@ -286,9 +286,19 @@ func (s *Storage) CreateFeed(feed *model.Feed) error { return fmt.Errorf(`store: unable to start transaction: %v`, err) } - if !s.entryExists(tx, feed.Entries[i]) { + entryExists, err := s.entryExists(tx, feed.Entries[i]) + if err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf(`store: unable to rollback transaction: %v (rolled back due to: %v)`, rollbackErr, err) + } + return err + } + + if !entryExists { if err := s.createEntry(tx, feed.Entries[i]); err != nil { - tx.Rollback() + if rollbackErr := tx.Rollback(); rollbackErr != nil { + return fmt.Errorf(`store: unable to rollback transaction: %v (rolled back due to: %v)`, rollbackErr, err) + } return err } }