From 7de6b0fc18ee6934a10619a1abbd2934f98d6b84 Mon Sep 17 00:00:00 2001 From: Shizun Ge Date: Mon, 27 Nov 2023 23:00:18 -0800 Subject: [PATCH 1/2] use named return value localizedError in handler.go --- internal/reader/handler/handler.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/internal/reader/handler/handler.go b/internal/reader/handler/handler.go index 4de76315..88fd491d 100644 --- a/internal/reader/handler/handler.go +++ b/internal/reader/handler/handler.go @@ -194,12 +194,13 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model } // RefreshFeed refreshes a feed. -func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool) *locale.LocalizedErrorWrapper { +func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool) (localizedError *locale.LocalizedErrorWrapper) { slog.Debug("Begin feed refresh process", slog.Int64("user_id", userID), slog.Int64("feed_id", feedID), slog.Bool("force_refresh", forceRefresh), ) + localizedError = nil user, storeErr := store.UserByID(userID) if storeErr != nil { @@ -242,7 +243,7 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(originalFeed.FeedURL)) defer responseHandler.Close() - if localizedError := responseHandler.LocalizedError(); localizedError != nil { + if localizedError = responseHandler.LocalizedError(); localizedError != nil { slog.Warn("Unable to fetch feed", slog.String("feed_url", originalFeed.FeedURL), slog.Any("error", localizedError.Error())) originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) @@ -250,7 +251,7 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool } if store.AnotherFeedURLExists(userID, originalFeed.ID, responseHandler.EffectiveURL()) { - localizedError := locale.NewLocalizedErrorWrapper(ErrDuplicatedFeed, "error.duplicated_feed") + localizedError = locale.NewLocalizedErrorWrapper(ErrDuplicatedFeed, "error.duplicated_feed") originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) return localizedError @@ -299,7 +300,7 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool updateExistingEntries := forceRefresh || !originalFeed.Crawler newEntries, storeErr := store.RefreshFeedEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, updateExistingEntries) if storeErr != nil { - localizedError := locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) + localizedError = locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) return localizedError @@ -338,13 +339,13 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool originalFeed.ResetErrorCounter() if storeErr := store.UpdateFeed(originalFeed); storeErr != nil { - localizedError := locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) + localizedError = locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) return localizedError } - return nil + return localizedError } func checkFeedIcon(store *storage.Storage, requestBuilder *fetcher.RequestBuilder, feedID int64, websiteURL, feedIconURL string) { From dc3426319d762466b81003214037ebe6db6e4dca Mon Sep 17 00:00:00 2001 From: Shizun Ge Date: Mon, 27 Nov 2023 23:07:46 -0800 Subject: [PATCH 2/2] calling store.UpdateFeed and store.UpdateFeedError in a defer function --- internal/reader/handler/handler.go | 55 ++++++++++++++---------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/internal/reader/handler/handler.go b/internal/reader/handler/handler.go index 88fd491d..842ee2f6 100644 --- a/internal/reader/handler/handler.go +++ b/internal/reader/handler/handler.go @@ -227,7 +227,30 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool } originalFeed.CheckedNow() - originalFeed.ScheduleNextCheck(weeklyEntryCount, newTTL) + // Commit the result to the database at the end of this function. + // If we met an error before entering the defer function, localizedError would not be nil. + defer func() { + originalFeed.ScheduleNextCheck(weeklyEntryCount, newTTL) + slog.Debug("Updated next check date", + slog.Int64("user_id", userID), + slog.Int64("feed_id", feedID), + slog.Int("weeklyEntryCount", weeklyEntryCount), + slog.Int("ttl", newTTL), + slog.Time("new_next_check_at", originalFeed.NextCheckAt), + ) + if localizedError == nil { + // We have not encountered any error before entering this delay function. + originalFeed.ResetErrorCounter() + if storeErr := store.UpdateFeed(originalFeed); storeErr != nil { + // Update the return value when there is an error. + localizedError = locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) + } + } + if localizedError != nil { + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) + store.UpdateFeedError(originalFeed) + } + }() requestBuilder := fetcher.NewRequestBuilder() requestBuilder.WithUsernameAndPassword(originalFeed.Username, originalFeed.Password) @@ -245,15 +268,11 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool if localizedError = responseHandler.LocalizedError(); localizedError != nil { slog.Warn("Unable to fetch feed", slog.String("feed_url", originalFeed.FeedURL), slog.Any("error", localizedError.Error())) - originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) - store.UpdateFeedError(originalFeed) return localizedError } if store.AnotherFeedURLExists(userID, originalFeed.ID, responseHandler.EffectiveURL()) { localizedError = locale.NewLocalizedErrorWrapper(ErrDuplicatedFeed, "error.duplicated_feed") - originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) - store.UpdateFeedError(originalFeed) return localizedError } @@ -271,27 +290,16 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool updatedFeed, parseErr := parser.ParseFeed(responseHandler.EffectiveURL(), bytes.NewReader(responseBody)) if parseErr != nil { - localizedError := locale.NewLocalizedErrorWrapper(parseErr, "error.unable_to_parse_feed", parseErr) - if errors.Is(parseErr, parser.ErrFeedFormatNotDetected) { localizedError = locale.NewLocalizedErrorWrapper(parseErr, "error.feed_format_not_detected", parseErr) + } else { + localizedError = locale.NewLocalizedErrorWrapper(parseErr, "error.unable_to_parse_feed", parseErr) } - - originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) - store.UpdateFeedError(originalFeed) return localizedError } // If the feed has a TTL defined, we use it to make sure we don't check it too often. newTTL = updatedFeed.TTL - // Set the next check at with updated arguments. - originalFeed.ScheduleNextCheck(weeklyEntryCount, newTTL) - slog.Debug("Updated next check date", - slog.Int64("user_id", userID), - slog.Int64("feed_id", feedID), - slog.Int("ttl", newTTL), - slog.Time("new_next_check_at", originalFeed.NextCheckAt), - ) originalFeed.Entries = updatedFeed.Entries processor.ProcessFeedEntries(store, originalFeed, user, forceRefresh) @@ -301,8 +309,6 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool newEntries, storeErr := store.RefreshFeedEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, updateExistingEntries) if storeErr != nil { localizedError = locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) - originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) - store.UpdateFeedError(originalFeed) return localizedError } @@ -336,15 +342,6 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool ) } - originalFeed.ResetErrorCounter() - - if storeErr := store.UpdateFeed(originalFeed); storeErr != nil { - localizedError = locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) - originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) - store.UpdateFeedError(originalFeed) - return localizedError - } - return localizedError }