mirror of
https://github.com/miniflux/v2.git
synced 2025-07-02 16:38:37 +00:00
perf: cache the format of feeds
Detecting the format of a feed accounts for up to 30% of the time spent in `parser.ParseFeed`. Cache the value once detected, as it'll never change.
This commit is contained in:
parent
e342a4f143
commit
c4a2afb7b7
12 changed files with 58 additions and 11 deletions
|
@ -25,6 +25,9 @@ func NewAtom03Adapter(atomFeed *Atom03Feed) *Atom03Adapter {
|
|||
func (a *Atom03Adapter) BuildFeed(baseURL string) *model.Feed {
|
||||
feed := new(model.Feed)
|
||||
|
||||
feed.Format = "atom"
|
||||
feed.FormatVersion = "0.3"
|
||||
|
||||
// Populate the feed URL.
|
||||
feedURL := a.atomFeed.Links.firstLinkWithRelation("self")
|
||||
if feedURL != "" {
|
||||
|
|
|
@ -29,6 +29,9 @@ func NewAtom10Adapter(atomFeed *Atom10Feed) *Atom10Adapter {
|
|||
func (a *Atom10Adapter) BuildFeed(baseURL string) *model.Feed {
|
||||
feed := new(model.Feed)
|
||||
|
||||
feed.Format = "atom"
|
||||
feed.FormatVersion = "10"
|
||||
|
||||
// Populate the feed URL.
|
||||
feedURL := a.atomFeed.Links.firstLinkWithRelation("self")
|
||||
if feedURL != "" {
|
||||
|
|
|
@ -275,7 +275,18 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool
|
|||
return localizedError
|
||||
}
|
||||
|
||||
updatedFeed, parseErr := parser.ParseFeed(responseHandler.EffectiveURL(), bytes.NewReader(responseBody))
|
||||
var updatedFeed *model.Feed
|
||||
var parseErr error
|
||||
if originalFeed.Format != "" {
|
||||
format, version := originalFeed.Format, originalFeed.FormatVersion
|
||||
updatedFeed, parseErr = parser.ParseFeedWithFormat(responseHandler.EffectiveURL(), bytes.NewReader(responseBody), format, version)
|
||||
if parseErr != nil { // Maybe the feed changed its format.
|
||||
slog.Warn("Unable to parse feed with the given format", slog.String("feed_url", originalFeed.FeedURL), slog.String("format", format), slog.Any("error", parseErr))
|
||||
updatedFeed, parseErr = parser.ParseFeed(responseHandler.EffectiveURL(), bytes.NewReader(responseBody))
|
||||
}
|
||||
} else {
|
||||
updatedFeed, parseErr = parser.ParseFeed(responseHandler.EffectiveURL(), bytes.NewReader(responseBody))
|
||||
}
|
||||
if parseErr != nil {
|
||||
localizedError := locale.NewLocalizedErrorWrapper(parseErr, "error.unable_to_parse_feed", parseErr)
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ func (j *JSONAdapter) BuildFeed(baseURL string) *model.Feed {
|
|||
Title: strings.TrimSpace(j.jsonFeed.Title),
|
||||
FeedURL: strings.TrimSpace(j.jsonFeed.FeedURL),
|
||||
SiteURL: strings.TrimSpace(j.jsonFeed.HomePageURL),
|
||||
Format: "json",
|
||||
}
|
||||
|
||||
if feed.FeedURL == "" {
|
||||
|
|
|
@ -16,10 +16,8 @@ import (
|
|||
|
||||
var ErrFeedFormatNotDetected = errors.New("parser: unable to detect feed format")
|
||||
|
||||
// ParseFeed analyzes the input data and returns a normalized feed object.
|
||||
func ParseFeed(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
||||
r.Seek(0, io.SeekStart)
|
||||
format, version := DetectFeedFormat(r)
|
||||
// ParseFeedWithFormat returns a normalized feed object.
|
||||
func ParseFeedWithFormat(baseURL string, r io.ReadSeeker, format, version string) (*model.Feed, error) {
|
||||
switch format {
|
||||
case FormatAtom:
|
||||
r.Seek(0, io.SeekStart)
|
||||
|
@ -37,3 +35,10 @@ func ParseFeed(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
|||
return nil, ErrFeedFormatNotDetected
|
||||
}
|
||||
}
|
||||
|
||||
// ParseFeed analyzes the input data and returns a normalized feed object.
|
||||
func ParseFeed(baseURL string, r io.ReadSeeker) (*model.Feed, error) {
|
||||
r.Seek(0, io.SeekStart)
|
||||
format, version := DetectFeedFormat(r)
|
||||
return ParseFeedWithFormat(baseURL, r, format, version)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ func (r *RDFAdapter) BuildFeed(baseURL string) *model.Feed {
|
|||
Title: stripTags(r.rdf.Channel.Title),
|
||||
FeedURL: strings.TrimSpace(baseURL),
|
||||
SiteURL: strings.TrimSpace(r.rdf.Channel.Link),
|
||||
Format: "rdf",
|
||||
}
|
||||
|
||||
if feed.Title == "" {
|
||||
|
|
|
@ -31,6 +31,7 @@ func (r *RSSAdapter) BuildFeed(baseURL string) *model.Feed {
|
|||
Title: html.UnescapeString(strings.TrimSpace(r.rss.Channel.Title)),
|
||||
FeedURL: strings.TrimSpace(baseURL),
|
||||
SiteURL: strings.TrimSpace(r.rss.Channel.Link),
|
||||
Format: "rss",
|
||||
}
|
||||
|
||||
// Ensure the Site URL is absolute.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue