Skip to content

Commit b95ae4d

Browse files
committed
Use batch insert when loading OPML
This is many many times faster (very noticeably) than using one query per feed as it was before.
1 parent 83a0816 commit b95ae4d

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
### Changed
99
* When no feed items are stored in the database for a particular feed, fall back to using the old time-based detection method
1010
* Do not index feed items at addition time
11-
* Do not update feed item index when sending a test email to prevent items being missed from the main scheduled emails
11+
* Do not update feed item index when sending a test email to prevent items being missed from the main scheduled emails
12+
* Use batch inserts when importing from OPML
1213

1314
## 0.4.2 - 2025-02-09
1415
### Fixed

walrss/internal/core/feeds.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ func NewFeed(st *state.State, userID, name, url string) (*db.Feed, error) {
3333
return feed, nil
3434
}
3535

36+
func NewFeeds(st *state.State, userID string, fs []*db.Feed) error {
37+
if len(fs) == 0 {
38+
return nil
39+
}
40+
41+
for i, f := range fs {
42+
f.ID = shortuuid.New()
43+
f.UserID = userID
44+
if err := validateFeedName(f.Name); err != nil {
45+
return NewUserErrorWithStatus(400, "validate feed %d: %w", i, err)
46+
}
47+
if err := validateURL(f.URL); err != nil {
48+
return NewUserErrorWithStatus(400, "validate feed %d: %w", i, err)
49+
}
50+
}
51+
52+
_, err := st.Data.NewInsert().Model(&fs).Exec(context.Background())
53+
return err
54+
}
55+
3656
func GetFeedsForUser(st *state.State, userID string) (res []*db.Feed, err error) {
3757
err = st.Data.NewSelect().
3858
Model(&res).
@@ -110,14 +130,17 @@ func ImportFeedsForUser(st *state.State, userID string, opmlXML []byte) error {
110130
}
111131
}
112132

113-
for _, feed := range o.ToFeeds() {
114-
if _, found := existingURLs[feed.URL]; found {
115-
continue
116-
}
117-
if _, err := NewFeed(st, userID, feed.Name, feed.URL); err != nil {
118-
return err
133+
var (
134+
fs = o.ToFeeds()
135+
n int
136+
)
137+
for _, feed := range fs {
138+
if _, found := existingURLs[feed.URL]; !found {
139+
fs[n] = feed
140+
n += 1
119141
}
120142
}
143+
fs = fs[:n]
121144

122-
return nil
145+
return NewFeeds(st, userID, fs)
123146
}

0 commit comments

Comments
 (0)