Просмотр исходного кода

refactor(storage): use query builder as builder

As query builders declared as such embrace this to the full extent.
gudvinr 3 дней назад
Родитель
Сommit
95f5f1e77d

+ 8 - 9
internal/api/category_handlers.go

@@ -163,15 +163,14 @@ func (h *handler) refreshCategoryHandler(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	batchBuilder := h.store.NewBatchBuilder()
-	batchBuilder.WithErrorLimit(config.Opts.PollingParsingErrorLimit())
-	batchBuilder.WithoutDisabledFeeds()
-	batchBuilder.WithUserID(userID)
-	batchBuilder.WithCategoryID(categoryID)
-	batchBuilder.WithNextCheckExpired()
-	batchBuilder.WithLimitPerHost(config.Opts.PollingLimitPerHost())
-
-	jobs, err := batchBuilder.FetchJobs()
+	jobs, err := h.store.NewBatchBuilder().
+		WithErrorLimit(config.Opts.PollingParsingErrorLimit()).
+		WithoutDisabledFeeds().
+		WithUserID(userID).
+		WithCategoryID(categoryID).
+		WithNextCheckExpired().
+		WithLimitPerHost(config.Opts.PollingLimitPerHost()).
+		FetchJobs()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 29 - 31
internal/api/entry_handlers.go

@@ -55,9 +55,9 @@ func (h *handler) getFeedEntryHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(request.UserID(r))
-	builder.WithFeedID(feedID)
-	builder.WithEntryID(entryID)
+	builder := h.store.NewEntryQueryBuilder(request.UserID(r)).
+		WithFeedID(feedID).
+		WithEntryID(entryID)
 
 	h.getEntryFromBuilder(w, r, builder)
 }
@@ -75,9 +75,9 @@ func (h *handler) getCategoryEntryHandler(w http.ResponseWriter, r *http.Request
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(request.UserID(r))
-	builder.WithCategoryID(categoryID)
-	builder.WithEntryID(entryID)
+	builder := h.store.NewEntryQueryBuilder(request.UserID(r)).
+		WithCategoryID(categoryID).
+		WithEntryID(entryID)
 
 	h.getEntryFromBuilder(w, r, builder)
 }
@@ -89,8 +89,8 @@ func (h *handler) getEntryHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(request.UserID(r))
-	builder.WithEntryID(entryID)
+	builder := h.store.NewEntryQueryBuilder(request.UserID(r)).
+		WithEntryID(entryID)
 
 	h.getEntryFromBuilder(w, r, builder)
 }
@@ -161,15 +161,15 @@ func (h *handler) findEntries(w http.ResponseWriter, r *http.Request, feedID int
 
 	tags := request.QueryStringParamList(r, "tags")
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithFeedID(feedID)
-	builder.WithCategoryID(categoryID)
-	builder.WithStatuses(statuses)
-	builder.WithSorting(order, direction)
-	builder.WithOffset(offset)
-	builder.WithLimit(limit)
-	builder.WithTags(tags)
-	builder.WithEnclosures()
+	builder := h.store.NewEntryQueryBuilder(userID).
+		WithFeedID(feedID).
+		WithCategoryID(categoryID).
+		WithStatuses(statuses).
+		WithSorting(order, direction).
+		WithOffset(offset).
+		WithLimit(limit).
+		WithTags(tags).
+		WithEnclosures()
 
 	if request.HasQueryParam(r, "globally_visible") {
 		globallyVisible := request.QueryBoolParam(r, "globally_visible", true)
@@ -236,15 +236,14 @@ func (h *handler) saveEntryHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(request.UserID(r))
-	builder.WithEntryID(entryID)
-
 	if !h.store.HasSaveEntry(request.UserID(r)) {
 		response.JSONBadRequest(w, r, errors.New("no third-party integration enabled"))
 		return
 	}
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(request.UserID(r)).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -285,10 +284,10 @@ func (h *handler) updateEntryHandler(w http.ResponseWriter, r *http.Request) {
 	}
 
 	loggedUserID := request.UserID(r)
-	entryBuilder := h.store.NewEntryQueryBuilder(loggedUserID)
-	entryBuilder.WithEntryID(entryID)
 
-	entry, err := entryBuilder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(loggedUserID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -445,10 +444,9 @@ func (h *handler) fetchContentHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	entryBuilder := h.store.NewEntryQueryBuilder(loggedUserID)
-	entryBuilder.WithEntryID(entryID)
-
-	entry, err := entryBuilder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(loggedUserID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -470,9 +468,9 @@ func (h *handler) fetchContentHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	feedBuilder := storage.NewFeedQueryBuilder(h.store, loggedUserID)
-	feedBuilder.WithFeedID(entry.FeedID)
-	feed, err := feedBuilder.GetFeed()
+	feed, err := storage.NewFeedQueryBuilder(h.store, loggedUserID).
+		WithFeedID(entry.FeedID).
+		GetFeed()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 7 - 8
internal/api/feed_handlers.go

@@ -76,14 +76,13 @@ func (h *handler) refreshFeedHandler(w http.ResponseWriter, r *http.Request) {
 func (h *handler) refreshAllFeedsHandler(w http.ResponseWriter, r *http.Request) {
 	userID := request.UserID(r)
 
-	batchBuilder := h.store.NewBatchBuilder()
-	batchBuilder.WithErrorLimit(config.Opts.PollingParsingErrorLimit())
-	batchBuilder.WithoutDisabledFeeds()
-	batchBuilder.WithNextCheckExpired()
-	batchBuilder.WithUserID(userID)
-	batchBuilder.WithLimitPerHost(config.Opts.PollingLimitPerHost())
-
-	jobs, err := batchBuilder.FetchJobs()
+	jobs, err := h.store.NewBatchBuilder().
+		WithErrorLimit(config.Opts.PollingParsingErrorLimit()).
+		WithoutDisabledFeeds().
+		WithNextCheckExpired().
+		WithUserID(userID).
+		WithLimitPerHost(config.Opts.PollingLimitPerHost()).
+		FetchJobs()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 8 - 9
internal/cli/refresh_feeds.go

@@ -20,14 +20,13 @@ func refreshFeeds(store *storage.Storage) {
 	startTime := time.Now()
 
 	// Generate a batch of feeds for any user that has feeds to refresh.
-	batchBuilder := store.NewBatchBuilder()
-	batchBuilder.WithBatchSize(config.Opts.BatchSize())
-	batchBuilder.WithErrorLimit(config.Opts.PollingParsingErrorLimit())
-	batchBuilder.WithoutDisabledFeeds()
-	batchBuilder.WithNextCheckExpired()
-	batchBuilder.WithLimitPerHost(config.Opts.PollingLimitPerHost())
-
-	jobs, err := batchBuilder.FetchJobs()
+	jobs, err := store.NewBatchBuilder().
+		WithBatchSize(config.Opts.BatchSize()).
+		WithErrorLimit(config.Opts.PollingParsingErrorLimit()).
+		WithoutDisabledFeeds().
+		WithNextCheckExpired().
+		WithLimitPerHost(config.Opts.PollingLimitPerHost()).
+		FetchJobs()
 	if err != nil {
 		slog.Error("Unable to fetch jobs from database", slog.Any("error", err))
 		return
@@ -36,7 +35,7 @@ func refreshFeeds(store *storage.Storage) {
 	slog.Debug("Feed URLs in this batch", slog.Any("feed_urls", jobs.FeedURLs()))
 
 	nbJobs := len(jobs)
-	var jobQueue = make(chan model.Job, nbJobs)
+	jobQueue := make(chan model.Job, nbJobs)
 
 	slog.Info("Starting a pool of workers",
 		slog.Int("nb_workers", config.Opts.WorkerPoolSize()),

+ 9 - 8
internal/cli/scheduler.go

@@ -33,14 +33,15 @@ func runScheduler(store *storage.Storage, pool *worker.Pool) {
 func feedScheduler(store *storage.Storage, pool *worker.Pool, frequency time.Duration, batchSize, errorLimit, limitPerHost int) {
 	for range time.Tick(frequency) {
 		// Generate a batch of feeds for any user that has feeds to refresh.
-		batchBuilder := store.NewBatchBuilder()
-		batchBuilder.WithBatchSize(batchSize)
-		batchBuilder.WithErrorLimit(errorLimit)
-		batchBuilder.WithoutDisabledFeeds()
-		batchBuilder.WithNextCheckExpired()
-		batchBuilder.WithLimitPerHost(limitPerHost)
-
-		if jobs, err := batchBuilder.FetchJobs(); err != nil {
+		jobs, err := store.NewBatchBuilder().
+			WithBatchSize(batchSize).
+			WithErrorLimit(errorLimit).
+			WithoutDisabledFeeds().
+			WithNextCheckExpired().
+			WithLimitPerHost(limitPerHost).
+			FetchJobs()
+
+		if err != nil {
 			slog.Error("Unable to fetch jobs from database", slog.Any("error", err))
 		} else if len(jobs) > 0 {
 			slog.Debug("Feed URLs in this batch", slog.Any("feed_urls", jobs.FeedURLs()))

+ 13 - 15
internal/fever/handler.go

@@ -238,8 +238,8 @@ func (h *feverHandler) handleItems(w http.ResponseWriter, r *http.Request) {
 
 	userID := request.UserID(r)
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithLimit(50)
+	builder := h.store.NewEntryQueryBuilder(userID).
+		WithLimit(50)
 
 	switch {
 	case request.HasQueryParam(r, "since_id"):
@@ -292,8 +292,8 @@ func (h *feverHandler) handleItems(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	builder = h.store.NewEntryQueryBuilder(userID)
-	result.Total, err = builder.CountEntries()
+	result.Total, err = h.store.NewEntryQueryBuilder(userID).
+		CountEntries()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -342,9 +342,9 @@ func (h *feverHandler) handleUnreadItems(w http.ResponseWriter, r *http.Request)
 		slog.Int64("user_id", userID),
 	)
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithStatus(model.EntryStatusUnread)
-	rawEntryIDs, err := builder.GetEntryIDs()
+	rawEntryIDs, err := h.store.NewEntryQueryBuilder(userID).
+		WithStatus(model.EntryStatusUnread).
+		GetEntryIDs()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -375,10 +375,9 @@ func (h *feverHandler) handleSavedItems(w http.ResponseWriter, r *http.Request)
 		slog.Int64("user_id", userID),
 	)
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithStarred(true)
-
-	entryIDs, err := builder.GetEntryIDs()
+	entryIDs, err := h.store.NewEntryQueryBuilder(userID).
+		WithStarred(true).
+		GetEntryIDs()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -410,10 +409,9 @@ func (h *feverHandler) handleWriteItems(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(userID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 42 - 35
internal/googlereader/handler.go

@@ -236,10 +236,9 @@ func (h *greaderHandler) editTagHandler(w http.ResponseWriter, r *http.Request)
 		slog.Any("tags", tags),
 	)
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithEntryIDs(itemIDs)
-
-	entries, err := builder.GetEntries()
+	entries, err := h.store.NewEntryQueryBuilder(userID).
+		WithEntryIDs(itemIDs).
+		GetEntries()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -649,12 +648,11 @@ func (h *greaderHandler) streamItemContentsHandler(w http.ResponseWriter, r *htt
 		slog.Any("item_ids", itemIDs),
 	)
 
-	builder := h.store.NewEntryQueryBuilder(userID)
-	builder.WithEnclosures()
-	builder.WithEntryIDs(itemIDs)
-	builder.WithSorting(model.DefaultSortingOrder, requestModifiers.SortDirection)
-
-	entries, err := builder.GetEntries()
+	entries, err := h.store.NewEntryQueryBuilder(userID).
+		WithEnclosures().
+		WithEntryIDs(itemIDs).
+		WithSorting(model.DefaultSortingOrder, requestModifiers.SortDirection).
+		GetEntries()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -1012,7 +1010,11 @@ func (h *greaderHandler) handleReadingListStreamHandler(w http.ResponseWriter, r
 		slog.String("user_agent", r.UserAgent()),
 	)
 
-	builder := h.store.NewEntryQueryBuilder(rm.UserID)
+	builder := h.store.NewEntryQueryBuilder(rm.UserID).
+		WithLimit(rm.Count).
+		WithOffset(rm.Offset).
+		WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+
 	for _, s := range rm.ExcludeTargets {
 		switch s.Type {
 		case ReadStream:
@@ -1027,12 +1029,10 @@ func (h *greaderHandler) handleReadingListStreamHandler(w http.ResponseWriter, r
 		}
 	}
 
-	builder.WithLimit(rm.Count)
-	builder.WithOffset(rm.Offset)
-	builder.WithSorting(model.DefaultSortingOrder, rm.SortDirection)
 	if rm.StartTime > 0 {
 		builder.AfterPublishedDate(time.Unix(rm.StartTime, 0))
 	}
+
 	if rm.StopTime > 0 {
 		builder.BeforePublishedDate(time.Unix(rm.StopTime, 0))
 	}
@@ -1046,34 +1046,40 @@ func (h *greaderHandler) handleReadingListStreamHandler(w http.ResponseWriter, r
 }
 
 func (h *greaderHandler) handleStarredStreamHandler(w http.ResponseWriter, r *http.Request, rm requestModifiers) {
-	builder := h.store.NewEntryQueryBuilder(rm.UserID)
-	builder.WithStarred(true)
-	builder.WithLimit(rm.Count)
-	builder.WithOffset(rm.Offset)
-	builder.WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+	builder := h.store.NewEntryQueryBuilder(rm.UserID).
+		WithStarred(true).
+		WithLimit(rm.Count).
+		WithOffset(rm.Offset).
+		WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+
 	if rm.StartTime > 0 {
 		builder.AfterPublishedDate(time.Unix(rm.StartTime, 0))
 	}
+
 	if rm.StopTime > 0 {
 		builder.BeforePublishedDate(time.Unix(rm.StopTime, 0))
 	}
+
 	itemRefs, continuation, err := getItemRefsAndContinuation(*builder, rm)
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
 	}
+
 	response.JSON(w, r, streamIDResponse{itemRefs, continuation})
 }
 
 func (h *greaderHandler) handleReadStreamHandler(w http.ResponseWriter, r *http.Request, rm requestModifiers) {
-	builder := h.store.NewEntryQueryBuilder(rm.UserID)
-	builder.WithStatus(model.EntryStatusRead)
-	builder.WithLimit(rm.Count)
-	builder.WithOffset(rm.Offset)
-	builder.WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+	builder := h.store.NewEntryQueryBuilder(rm.UserID).
+		WithStatus(model.EntryStatusRead).
+		WithLimit(rm.Count).
+		WithOffset(rm.Offset).
+		WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+
 	if rm.StartTime > 0 {
 		builder.AfterPublishedDate(time.Unix(rm.StartTime, 0))
 	}
+
 	if rm.StopTime > 0 {
 		builder.BeforePublishedDate(time.Unix(rm.StopTime, 0))
 	}
@@ -1083,6 +1089,7 @@ func (h *greaderHandler) handleReadStreamHandler(w http.ResponseWriter, r *http.
 		response.JSONServerError(w, r, err)
 		return
 	}
+
 	response.JSON(w, r, streamIDResponse{itemRefs, continuation})
 }
 
@@ -1091,7 +1098,7 @@ func getItemRefsAndContinuation(builder storage.EntryQueryBuilder, rm requestMod
 	if err != nil {
 		return nil, 0, err
 	}
-	var itemRefs = make([]itemRef, 0, len(rawEntryIDs))
+	itemRefs := make([]itemRef, 0, len(rawEntryIDs))
 	for _, entryID := range rawEntryIDs {
 		formattedID := strconv.FormatInt(entryID, 10)
 		itemRefs = append(itemRefs, itemRef{ID: formattedID})
@@ -1115,11 +1122,11 @@ func (h *greaderHandler) handleFeedStreamHandler(w http.ResponseWriter, r *http.
 		return
 	}
 
-	builder := h.store.NewEntryQueryBuilder(rm.UserID)
-	builder.WithFeedID(feedID)
-	builder.WithLimit(rm.Count)
-	builder.WithOffset(rm.Offset)
-	builder.WithSorting(model.DefaultSortingOrder, rm.SortDirection)
+	builder := h.store.NewEntryQueryBuilder(rm.UserID).
+		WithFeedID(feedID).
+		WithLimit(rm.Count).
+		WithOffset(rm.Offset).
+		WithSorting(model.DefaultSortingOrder, rm.SortDirection)
 
 	if rm.StartTime > 0 {
 		builder.AfterPublishedDate(time.Unix(rm.StartTime, 0))
@@ -1129,18 +1136,18 @@ func (h *greaderHandler) handleFeedStreamHandler(w http.ResponseWriter, r *http.
 		builder.BeforePublishedDate(time.Unix(rm.StopTime, 0))
 	}
 
-	if len(rm.ExcludeTargets) > 0 {
-		for _, s := range rm.ExcludeTargets {
-			if s.Type == ReadStream {
-				builder.WithoutStatus(model.EntryStatusRead)
-			}
+	for _, s := range rm.ExcludeTargets {
+		if s.Type == ReadStream {
+			builder.WithoutStatus(model.EntryStatusRead)
 		}
 	}
+
 	itemRefs, continuation, err := getItemRefsAndContinuation(*builder, rm)
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
 	}
+
 	response.JSON(w, r, streamIDResponse{itemRefs, continuation})
 }
 

+ 17 - 20
internal/storage/feed.go

@@ -126,9 +126,9 @@ func (s *Storage) CountAllFeedsWithErrors() (int, error) {
 
 // Feeds returns all feeds that belong to the given user.
 func (s *Storage) Feeds(userID int64) (model.Feeds, error) {
-	builder := NewFeedQueryBuilder(s, userID)
-	builder.WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection)
-	return builder.GetFeeds()
+	return NewFeedQueryBuilder(s, userID).
+		WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection).
+		GetFeeds()
 }
 
 func getFeedsSorted(builder *feedQueryBuilder) (model.Feeds, error) {
@@ -142,27 +142,26 @@ func getFeedsSorted(builder *feedQueryBuilder) (model.Feeds, error) {
 
 // FeedsWithCounters returns all feeds of the given user with read and unread entry counters.
 func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
-	builder := NewFeedQueryBuilder(s, userID)
-	builder.WithCounters()
-	builder.WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection)
-	return getFeedsSorted(builder)
+	return getFeedsSorted(NewFeedQueryBuilder(s, userID).
+		WithCounters().
+		WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection))
 }
 
 // FetchCounters returns the per-feed read and unread entry counts for the given user.
 func (s *Storage) FetchCounters(userID int64) (model.FeedCounters, error) {
-	builder := NewFeedQueryBuilder(s, userID)
-	builder.WithCounters()
-	reads, unreads, err := builder.fetchFeedCounter()
+	reads, unreads, err := NewFeedQueryBuilder(s, userID).
+		WithCounters().
+		fetchFeedCounter()
+
 	return model.FeedCounters{ReadCounters: reads, UnreadCounters: unreads}, err
 }
 
 // FeedsByCategoryWithCounters returns all feeds in the given category for the given user with read and unread entry counters.
 func (s *Storage) FeedsByCategoryWithCounters(userID, categoryID int64) (model.Feeds, error) {
-	builder := NewFeedQueryBuilder(s, userID)
-	builder.WithCategoryID(categoryID)
-	builder.WithCounters()
-	builder.WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection)
-	return getFeedsSorted(builder)
+	return getFeedsSorted(NewFeedQueryBuilder(s, userID).
+		WithCategoryID(categoryID).
+		WithCounters().
+		WithSorting(model.DefaultFeedSorting, model.DefaultFeedSortingDirection))
 }
 
 // WeeklyFeedEntryCount returns the weekly entry count for a feed.
@@ -199,9 +198,9 @@ func (s *Storage) WeeklyFeedEntryCount(userID, feedID int64) (int, error) {
 
 // FeedByID returns the feed with the given ID.
 func (s *Storage) FeedByID(userID, feedID int64) (*model.Feed, error) {
-	builder := NewFeedQueryBuilder(s, userID)
-	builder.WithFeedID(feedID)
-	feed, err := builder.GetFeed()
+	feed, err := NewFeedQueryBuilder(s, userID).
+		WithFeedID(feedID).
+		GetFeed()
 
 	switch {
 	case errors.Is(err, sql.ErrNoRows):
@@ -417,7 +416,6 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
 		feed.ID,
 		feed.UserID,
 	)
-
 	if err != nil {
 		return fmt.Errorf(`store: unable to update feed #%d (%s): %v`, feed.ID, feed.FeedURL, err)
 	}
@@ -446,7 +444,6 @@ func (s *Storage) UpdateFeedError(feed *model.Feed) (err error) {
 		feed.ID,
 		feed.UserID,
 	)
-
 	if err != nil {
 		return fmt.Errorf(`store: unable to update feed error #%d (%s): %v`, feed.ID, feed.FeedURL, err)
 	}

+ 9 - 9
internal/ui/category_entries.go

@@ -32,16 +32,16 @@ func (h *handler) showCategoryEntriesPage(w http.ResponseWriter, r *http.Request
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(category.ID)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithStatus(model.EntryStatusUnread)
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
 
-	entries, count, err := builder.GetEntriesWithCount()
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(category.ID).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithStatus(model.EntryStatusUnread).
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 9 - 9
internal/ui/category_entries_all.go

@@ -31,15 +31,15 @@ func (h *handler) showCategoryEntriesAllPage(w http.ResponseWriter, r *http.Requ
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(category.ID)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(category.ID).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 10 - 10
internal/ui/category_entries_starred.go

@@ -31,16 +31,16 @@ func (h *handler) showCategoryEntriesStarredPage(w http.ResponseWriter, r *http.
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(category.ID)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithStarred(true)
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(category.ID).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithStarred(true).
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 6 - 7
internal/ui/category_refresh.go

@@ -37,13 +37,12 @@ func (h *handler) refreshCategory(w http.ResponseWriter, r *http.Request) int64
 		userID := request.UserID(r)
 		// We allow the end-user to force refresh all its feeds in this category
 		// without taking into consideration the number of errors.
-		batchBuilder := h.store.NewBatchBuilder()
-		batchBuilder.WithoutDisabledFeeds()
-		batchBuilder.WithUserID(userID)
-		batchBuilder.WithCategoryID(categoryID)
-		batchBuilder.WithLimitPerHost(config.Opts.PollingLimitPerHost())
-
-		jobs, err := batchBuilder.FetchJobs()
+		jobs, err := h.store.NewBatchBuilder().
+			WithoutDisabledFeeds().
+			WithUserID(userID).
+			WithCategoryID(categoryID).
+			WithLimitPerHost(config.Opts.PollingLimitPerHost()).
+			FetchJobs()
 		if err != nil {
 			response.HTMLServerError(w, r, err)
 			return 0

+ 7 - 8
internal/ui/entry_category.go

@@ -23,11 +23,10 @@ func (h *handler) showCategoryEntryPage(w http.ResponseWriter, r *http.Request)
 	categoryID := request.RouteInt64Param(r, "categoryID")
 	entryID := request.RouteInt64Param(r, "entryID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(categoryID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(categoryID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -53,9 +52,9 @@ func (h *handler) showCategoryEntryPage(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithCategoryID(categoryID)
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithCategoryID(categoryID).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 7 - 8
internal/ui/entry_feed.go

@@ -23,11 +23,10 @@ func (h *handler) showFeedEntryPage(w http.ResponseWriter, r *http.Request) {
 	entryID := request.RouteInt64Param(r, "entryID")
 	feedID := request.RouteInt64Param(r, "feedID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithFeedID(feedID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithFeedID(feedID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -53,9 +52,9 @@ func (h *handler) showFeedEntryPage(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithFeedID(feedID)
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithFeedID(feedID).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 6 - 6
internal/ui/entry_read.go

@@ -21,10 +21,10 @@ func (h *handler) showReadEntryPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	entryID := request.RouteInt64Param(r, "entryID")
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithEntryID(entryID)
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -40,9 +40,9 @@ func (h *handler) showReadEntryPage(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, "changed_at", "desc")
-	entryPaginationBuilder.WithStatus(model.EntryStatusRead)
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, "changed_at", "desc").
+		WithStatus(model.EntryStatusRead).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 3 - 3
internal/ui/entry_save.go

@@ -13,10 +13,10 @@ import (
 
 func (h *handler) saveEntry(w http.ResponseWriter, r *http.Request) {
 	entryID := request.RouteInt64Param(r, "entryID")
-	builder := h.store.NewEntryQueryBuilder(request.UserID(r))
-	builder.WithEntryID(entryID)
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(request.UserID(r)).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 6 - 7
internal/ui/entry_scraper.go

@@ -18,10 +18,9 @@ func (h *handler) fetchContent(w http.ResponseWriter, r *http.Request) {
 	loggedUserID := request.UserID(r)
 	entryID := request.RouteInt64Param(r, "entryID")
 
-	entryBuilder := h.store.NewEntryQueryBuilder(loggedUserID)
-	entryBuilder.WithEntryID(entryID)
-
-	entry, err := entryBuilder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(loggedUserID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return
@@ -38,9 +37,9 @@ func (h *handler) fetchContent(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	feedBuilder := storage.NewFeedQueryBuilder(h.store, loggedUserID)
-	feedBuilder.WithFeedID(entry.FeedID)
-	feed, err := feedBuilder.GetFeed()
+	feed, err := storage.NewFeedQueryBuilder(h.store, loggedUserID).
+		WithFeedID(entry.FeedID).
+		GetFeed()
 	if err != nil {
 		response.JSONServerError(w, r, err)
 		return

+ 6 - 6
internal/ui/entry_search.go

@@ -23,11 +23,11 @@ func (h *handler) showSearchEntryPage(w http.ResponseWriter, r *http.Request) {
 	entryID := request.RouteInt64Param(r, "entryID")
 	searchQuery := request.QueryStringParam(r, "q", "")
 	unreadOnly := request.QueryBoolParam(r, "unread", false)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithSearchQuery(searchQuery)
-	builder.WithEntryID(entryID)
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithSearchQuery(searchQuery).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -53,8 +53,8 @@ func (h *handler) showSearchEntryPage(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithSearchQuery(searchQuery)
+	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithSearchQuery(searchQuery)
 	if unreadOnly {
 		if entry.Status == model.EntryStatusRead {
 			entryPaginationBuilder.WithStatusOrEntryID(model.EntryStatusUnread, entry.ID)

+ 6 - 6
internal/ui/entry_starred.go

@@ -21,10 +21,10 @@ func (h *handler) showStarredEntryPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	entryID := request.RouteInt64Param(r, "entryID")
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithEntryID(entryID)
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -50,9 +50,9 @@ func (h *handler) showStarredEntryPage(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithStarred()
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithStarred().
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 7 - 8
internal/ui/entry_tag.go

@@ -28,11 +28,10 @@ func (h *handler) showTagEntryPage(w http.ResponseWriter, r *http.Request) {
 	}
 	entryID := request.RouteInt64Param(r, "entryID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithTags([]string{tagName})
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithTags([]string{tagName}).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -53,9 +52,9 @@ func (h *handler) showTagEntryPage(w http.ResponseWriter, r *http.Request) {
 		entry.Status = model.EntryStatusRead
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithTags([]string{tagName})
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithTags([]string{tagName}).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 7 - 7
internal/ui/entry_unread.go

@@ -21,10 +21,10 @@ func (h *handler) showUnreadEntryPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	entryID := request.RouteInt64Param(r, "entryID")
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithEntryID(entryID)
 
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -44,10 +44,10 @@ func (h *handler) showUnreadEntryPage(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithStatus(model.EntryStatusUnread)
-	entryPaginationBuilder.WithGloballyVisible()
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithStatus(model.EntryStatusUnread).
+		WithGloballyVisible().
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 9 - 9
internal/ui/feed_entries.go

@@ -32,16 +32,16 @@ func (h *handler) showFeedEntriesPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithFeedID(feed.ID)
-	builder.WithStatus(model.EntryStatusUnread)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-	builder.WithoutContent()
 
-	entries, count, err := builder.GetEntriesWithCount()
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithFeedID(feed.ID).
+		WithStatus(model.EntryStatusUnread).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		WithoutContent().
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 9 - 9
internal/ui/feed_entries_all.go

@@ -31,15 +31,15 @@ func (h *handler) showFeedEntriesAllPage(w http.ResponseWriter, r *http.Request)
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithFeedID(feed.ID)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithFeedID(feed.ID).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 5 - 6
internal/ui/feed_refresh.go

@@ -42,12 +42,11 @@ func (h *handler) refreshAllFeeds(w http.ResponseWriter, r *http.Request) {
 		userID := request.UserID(r)
 		// We allow the end-user to force refresh all its feeds
 		// without taking into consideration the number of errors.
-		batchBuilder := h.store.NewBatchBuilder()
-		batchBuilder.WithoutDisabledFeeds()
-		batchBuilder.WithUserID(userID)
-		batchBuilder.WithLimitPerHost(config.Opts.PollingLimitPerHost())
-
-		jobs, err := batchBuilder.FetchJobs()
+		jobs, err := h.store.NewBatchBuilder().
+			WithoutDisabledFeeds().
+			WithUserID(userID).
+			WithLimitPerHost(config.Opts.PollingLimitPerHost()).
+			FetchJobs()
 		if err != nil {
 			response.HTMLServerError(w, r, err)
 			return

+ 9 - 9
internal/ui/history_entries.go

@@ -20,15 +20,15 @@ func (h *handler) showHistoryPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithStatus(model.EntryStatusRead)
-	builder.WithSorting("changed_at", "DESC")
-	builder.WithSorting("published_at", "DESC")
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithStatus(model.EntryStatusRead).
+		WithSorting("changed_at", "DESC").
+		WithSorting("published_at", "DESC").
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 6 - 5
internal/ui/search.go

@@ -27,14 +27,15 @@ func (h *handler) showSearchPage(w http.ResponseWriter, r *http.Request) {
 	var entriesCount int
 
 	if searchQuery != "" {
-		builder := h.store.NewEntryQueryBuilder(user.ID)
-		builder.WithSearchQuery(searchQuery)
+		builder := h.store.NewEntryQueryBuilder(user.ID).
+			WithSearchQuery(searchQuery).
+			WithoutContent().
+			WithOffset(offset).
+			WithLimit(user.EntriesPerPage)
+
 		if unreadOnly {
 			builder.WithStatus(model.EntryStatusUnread)
 		}
-		builder.WithoutContent()
-		builder.WithOffset(offset)
-		builder.WithLimit(user.EntriesPerPage)
 
 		entries, entriesCount, err = builder.GetEntriesWithCount()
 		if err != nil {

+ 3 - 3
internal/ui/share.go

@@ -44,10 +44,10 @@ func (h *handler) sharedEntry(w http.ResponseWriter, r *http.Request) {
 
 	etag := shareCode
 	response.NewBuilder(w, r).WithCaching(etag, 72*time.Hour, func(b *response.Builder) {
-		builder := storage.NewAnonymousQueryBuilder(h.store)
-		builder.WithShareCode(shareCode)
+		entry, err := storage.NewAnonymousQueryBuilder(h.store).
+			WithShareCode(shareCode).
+			GetEntry()
 
-		entry, err := builder.GetEntry()
 		if err != nil || entry == nil {
 			response.HTMLNotFound(w, r)
 			return

+ 9 - 9
internal/ui/shared_entries.go

@@ -19,15 +19,15 @@ func (h *handler) sharedEntries(w http.ResponseWriter, r *http.Request) {
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithShareCodeNotEmpty()
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-	builder.WithoutContent()
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithShareCodeNotEmpty().
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		WithoutContent().
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 9 - 9
internal/ui/starred_entries.go

@@ -19,15 +19,15 @@ func (h *handler) showStarredPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithStarred(true)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-	builder.WithoutContent()
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithStarred(true).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		WithoutContent().
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 8 - 10
internal/ui/starred_entry_category.go

@@ -23,11 +23,10 @@ func (h *handler) showStarredCategoryEntryPage(w http.ResponseWriter, r *http.Re
 	categoryID := request.RouteInt64Param(r, "categoryID")
 	entryID := request.RouteInt64Param(r, "entryID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(categoryID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(categoryID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -53,11 +52,10 @@ func (h *handler) showStarredCategoryEntryPage(w http.ResponseWriter, r *http.Re
 		return
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithCategoryID(categoryID)
-	entryPaginationBuilder.WithStarred()
-
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithCategoryID(categoryID).
+		WithStarred().
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 10 - 10
internal/ui/tag_entries_all.go

@@ -26,16 +26,16 @@ func (h *handler) showTagEntriesAllPage(w http.ResponseWriter, r *http.Request)
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithTags([]string{tagName})
-	builder.WithSorting("status", "asc")
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithoutContent()
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-
-	entries, count, err := builder.GetEntriesWithCount()
+
+	entries, count, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithTags([]string{tagName}).
+		WithSorting("status", "asc").
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithoutContent().
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 17 - 17
internal/ui/unread_entries.go

@@ -20,16 +20,16 @@ func (h *handler) showUnreadPage(w http.ResponseWriter, r *http.Request) {
 	}
 
 	offset := request.QueryIntParam(r, "offset", 0)
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithStatus(model.EntryStatusUnread)
-	builder.WithSorting(user.EntryOrder, user.EntryDirection)
-	builder.WithSorting("id", user.EntryDirection)
-	builder.WithOffset(offset)
-	builder.WithLimit(user.EntriesPerPage)
-	builder.WithGloballyVisible()
-	builder.WithoutContent()
 
-	entries, countUnread, err := builder.GetEntriesWithCount()
+	entries, countUnread, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithStatus(model.EntryStatusUnread).
+		WithSorting(user.EntryOrder, user.EntryDirection).
+		WithSorting("id", user.EntryDirection).
+		WithOffset(offset).
+		WithLimit(user.EntriesPerPage).
+		WithGloballyVisible().
+		WithoutContent().
+		GetEntriesWithCount()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -37,15 +37,15 @@ func (h *handler) showUnreadPage(w http.ResponseWriter, r *http.Request) {
 
 	if offset >= countUnread && countUnread > 0 {
 		offset = 0
-		builder = h.store.NewEntryQueryBuilder(user.ID)
-		builder.WithStatus(model.EntryStatusUnread)
-		builder.WithSorting(user.EntryOrder, user.EntryDirection)
-		builder.WithSorting("id", user.EntryDirection)
-		builder.WithLimit(user.EntriesPerPage)
-		builder.WithGloballyVisible()
-		builder.WithoutContent()
 
-		entries, countUnread, err = builder.GetEntriesWithCount()
+		entries, countUnread, err = h.store.NewEntryQueryBuilder(user.ID).
+			WithStatus(model.EntryStatusUnread).
+			WithSorting(user.EntryOrder, user.EntryDirection).
+			WithSorting("id", user.EntryDirection).
+			WithLimit(user.EntriesPerPage).
+			WithGloballyVisible().
+			WithoutContent().
+			GetEntriesWithCount()
 		if err != nil {
 			response.HTMLServerError(w, r, err)
 			return

+ 8 - 10
internal/ui/unread_entry_category.go

@@ -23,11 +23,10 @@ func (h *handler) showUnreadCategoryEntryPage(w http.ResponseWriter, r *http.Req
 	categoryID := request.RouteInt64Param(r, "categoryID")
 	entryID := request.RouteInt64Param(r, "entryID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithCategoryID(categoryID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithCategoryID(categoryID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -48,10 +47,6 @@ func (h *handler) showUnreadCategoryEntryPage(w http.ResponseWriter, r *http.Req
 		entry.Status = model.EntryStatusRead
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithCategoryID(categoryID)
-	entryPaginationBuilder.WithStatus(model.EntryStatusUnread)
-
 	if entry.Status == model.EntryStatusRead {
 		err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusUnread)
 		if err != nil {
@@ -60,7 +55,10 @@ func (h *handler) showUnreadCategoryEntryPage(w http.ResponseWriter, r *http.Req
 		}
 	}
 
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithCategoryID(categoryID).
+		WithStatus(model.EntryStatusUnread).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return

+ 8 - 10
internal/ui/unread_entry_feed.go

@@ -23,11 +23,10 @@ func (h *handler) showUnreadFeedEntryPage(w http.ResponseWriter, r *http.Request
 	entryID := request.RouteInt64Param(r, "entryID")
 	feedID := request.RouteInt64Param(r, "feedID")
 
-	builder := h.store.NewEntryQueryBuilder(user.ID)
-	builder.WithFeedID(feedID)
-	builder.WithEntryID(entryID)
-
-	entry, err := builder.GetEntry()
+	entry, err := h.store.NewEntryQueryBuilder(user.ID).
+		WithFeedID(feedID).
+		WithEntryID(entryID).
+		GetEntry()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return
@@ -48,10 +47,6 @@ func (h *handler) showUnreadFeedEntryPage(w http.ResponseWriter, r *http.Request
 		entry.Status = model.EntryStatusRead
 	}
 
-	entryPaginationBuilder := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection)
-	entryPaginationBuilder.WithFeedID(feedID)
-	entryPaginationBuilder.WithStatus(model.EntryStatusUnread)
-
 	if entry.Status == model.EntryStatusRead {
 		err = h.store.SetEntriesStatus(user.ID, []int64{entry.ID}, model.EntryStatusUnread)
 		if err != nil {
@@ -60,7 +55,10 @@ func (h *handler) showUnreadFeedEntryPage(w http.ResponseWriter, r *http.Request
 		}
 	}
 
-	prevEntry, nextEntry, err := entryPaginationBuilder.Entries()
+	prevEntry, nextEntry, err := storage.NewEntryPaginationBuilder(h.store, user.ID, entry.ID, user.EntryOrder, user.EntryDirection).
+		WithFeedID(feedID).
+		WithStatus(model.EntryStatusUnread).
+		Entries()
 	if err != nil {
 		response.HTMLServerError(w, r, err)
 		return