|
|
@@ -7,7 +7,6 @@ import (
|
|
|
"database/sql"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
- "log/slog"
|
|
|
"sort"
|
|
|
"time"
|
|
|
|
|
|
@@ -33,24 +32,17 @@ func (l byStateAndName) Less(i, j int) bool {
|
|
|
return l.f[i].Title < l.f[j].Title
|
|
|
}
|
|
|
|
|
|
-// FeedExists checks if the given feed exists.
|
|
|
-func (s *Storage) FeedExists(userID, feedID int64) bool {
|
|
|
+// FeedExists checks if the given feed exists. The returned error is
|
|
|
+// non-nil only for a genuine query/connection failure; a feed that doesn't
|
|
|
+// exist is reported as (false, nil), matching the underlying sql.ErrNoRows
|
|
|
+// case.
|
|
|
+func (s *Storage) FeedExists(userID, feedID int64) (bool, error) {
|
|
|
var result bool
|
|
|
query := `SELECT true FROM feeds WHERE user_id=$1 AND id=$2 LIMIT 1`
|
|
|
if err := s.db.QueryRow(query, userID, feedID).Scan(&result); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
|
- // A real query/connection error is not the same thing as "this feed
|
|
|
- // doesn't exist" -- callers treat a false return as a 404, so a
|
|
|
- // swallowed error here would silently misreport a genuine
|
|
|
- // infrastructure failure as a missing resource. Logging at least
|
|
|
- // makes it observable in server logs, matching the pattern already
|
|
|
- // used by CountWebAuthnCredentialsByUserID in webauthn.go.
|
|
|
- slog.Error("store: unable to check if feed exists",
|
|
|
- slog.Int64("user_id", userID),
|
|
|
- slog.Int64("feed_id", feedID),
|
|
|
- slog.Any("error", err),
|
|
|
- )
|
|
|
+ return false, fmt.Errorf(`store: unable to check if feed exists: %w`, err)
|
|
|
}
|
|
|
- return result
|
|
|
+ return result, nil
|
|
|
}
|
|
|
|
|
|
// CheckedAt returns when the feed was last checked.
|
|
|
@@ -64,19 +56,16 @@ func (s *Storage) CheckedAt(userID, feedID int64) (time.Time, error) {
|
|
|
return result, nil
|
|
|
}
|
|
|
|
|
|
-// CategoryFeedExists returns true if the given feed exists and belongs to the given category.
|
|
|
-func (s *Storage) CategoryFeedExists(userID, categoryID, feedID int64) bool {
|
|
|
+// CategoryFeedExists returns true if the given feed exists and belongs to
|
|
|
+// the given category. The returned error is non-nil only for a genuine
|
|
|
+// query/connection failure; see FeedExists above for the same convention.
|
|
|
+func (s *Storage) CategoryFeedExists(userID, categoryID, feedID int64) (bool, error) {
|
|
|
var result bool
|
|
|
query := `SELECT true FROM feeds WHERE user_id=$1 AND category_id=$2 AND id=$3 LIMIT 1`
|
|
|
if err := s.db.QueryRow(query, userID, categoryID, feedID).Scan(&result); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
|
|
- slog.Error("store: unable to check if feed exists in category",
|
|
|
- slog.Int64("user_id", userID),
|
|
|
- slog.Int64("category_id", categoryID),
|
|
|
- slog.Int64("feed_id", feedID),
|
|
|
- slog.Any("error", err),
|
|
|
- )
|
|
|
+ return false, fmt.Errorf(`store: unable to check if feed exists in category: %w`, err)
|
|
|
}
|
|
|
- return result
|
|
|
+ return result, nil
|
|
|
}
|
|
|
|
|
|
// FeedURLExists returns true if the given feed URL already exists for the user.
|