diff --git a/cmd/nom/main.go b/cmd/nom/main.go index b534073..a765439 100755 --- a/cmd/nom/main.go +++ b/cmd/nom/main.go @@ -123,8 +123,12 @@ func getCmds() (*commands.Commands, error) { if err = cfg.Load(); err != nil { return nil, err } - - s, err := store.NewSQLiteStore(cfg.ConfigDir, cfg.Database) + var s store.Store + if cfg.IsPreviewMode() { + s, err = store.NewInMemorySQLiteStore() + } else { + s, err = store.NewSQLiteStore(cfg.ConfigDir, cfg.Database) + } if err != nil { return nil, fmt.Errorf("main.go: %w", err) } diff --git a/internal/commands/commands.go b/internal/commands/commands.go index 0d9638e..3ee6887 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -248,13 +248,10 @@ func (c Commands) fetchAllFeeds() ([]store.Item, []ErrorItem, error) { Title: r.Title, } - // only store if non-preview feed - if !includes(c.config.PreviewFeeds, config.Feed{URL: result.url}) { - err := c.store.UpsertItem(i) - if err != nil { - log.Fatalf("[commands.go] fetchAllFeeds: %e", err) - continue - } + err := c.store.UpsertItem(&i) + if err != nil { + log.Fatalf("[commands.go] fetchAllFeeds: %e", err) + continue } items = append(items, i) diff --git a/internal/commands/feeds.go b/internal/commands/feeds.go index 1c700af..120bea4 100644 --- a/internal/commands/feeds.go +++ b/internal/commands/feeds.go @@ -17,9 +17,16 @@ func (c Commands) CleanFeeds() error { var urlsToRemove []string + var feeds []config.Feed + if c.config.IsPreviewMode() { + feeds = c.config.PreviewFeeds + } else { + feeds = c.config.Feeds + } + for _, u := range urls { inFeeds := false - for _, f := range c.config.Feeds { + for _, f := range feeds { if f.URL == u { inFeeds = true } @@ -29,7 +36,6 @@ func (c Commands) CleanFeeds() error { urlsToRemove = append(urlsToRemove, u) } } - for _, url := range urlsToRemove { err := c.store.DeleteByFeedURL(url, false) if err != nil { @@ -100,7 +106,6 @@ func fetchFeed(ch chan FetchResultError, wg *sync.WaitGroup, feed config.Feed, h defer wg.Done() r, err := rss.Fetch(feed, httpOpts, version) - if err != nil { ch <- FetchResultError{res: rss.RSS{}, err: err, url: feed.URL} return diff --git a/internal/commands/tui.go b/internal/commands/tui.go index a68f9ac..50a8823 100644 --- a/internal/commands/tui.go +++ b/internal/commands/tui.go @@ -191,13 +191,7 @@ func (c *Commands) TUI() error { var errorItems []ErrorItem // if no feeds in store, fetchAllFeeds, which will return previews - if len(c.config.PreviewFeeds) > 0 { - its, errorItems, err = c.fetchAllFeeds() - if err != nil { - return fmt.Errorf("[commands.go] TUI: %w", err) - } - // if no items, fetchAllFeeds and GetAllFeeds - } else if len(its) == 0 { + if len(c.config.PreviewFeeds) > 0 || len(its) == 0 { _, errorItems, err = c.fetchAllFeeds() if err != nil { return fmt.Errorf("[commands.go] TUI: %w", err) @@ -217,7 +211,6 @@ func (c *Commands) TUI() error { } prog, err := Render(items, c, es, c.config) - if err != nil { return fmt.Errorf("commands.TUI: %w", err) } diff --git a/internal/store/store.go b/internal/store/store.go index f164ac3..4a968d6 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -33,7 +33,7 @@ func (i Item) Read() bool { } type Store interface { - UpsertItem(item Item) error + UpsertItem(item *Item) error BeginBatch() error EndBatch() error GetAllItems(ordering string) ([]Item, error) @@ -52,6 +52,27 @@ type SQLiteStore struct { batch *sql.Tx } +func NewInMemorySQLiteStore() (*SQLiteStore, error) { + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + return nil, fmt.Errorf("NewInMemorySQLiteStore: %w", err) + } + + err = dbSetup(db) + if err != nil { + return nil, fmt.Errorf("NewInMemorySQLiteStore: %w", err) + } + + err = runMigrations(db) + if err != nil { + return nil, fmt.Errorf("NewInMemorySQLiteStore: %w", err) + } + + return &SQLiteStore{ + db: db, + }, nil +} + func NewSQLiteStore(basePath string, dbName string) (*SQLiteStore, error) { dbpath := filepath.Join(basePath, dbName) @@ -59,7 +80,7 @@ func NewSQLiteStore(basePath string, dbName string) (*SQLiteStore, error) { db, err := sql.Open("sqlite3", dbpath) if err != nil { - return nil, fmt.Errorf("NewSQLiteCache: %w", err) + return nil, fmt.Errorf("NewSQLiteStore: %w", err) } // if there was no db file before we create the connection then we want to run @@ -67,13 +88,13 @@ func NewSQLiteStore(basePath string, dbName string) (*SQLiteStore, error) { if info == nil { err = dbSetup(db) if err != nil { - return nil, fmt.Errorf("NewSQLiteCache: %w", err) + return nil, fmt.Errorf("NewSQLiteStore: %w", err) } } err = runMigrations(db) if err != nil { - return nil, fmt.Errorf("NewSQLiteCache: %w", err) + return nil, fmt.Errorf("NewSQLiteStore: %w", err) } return &SQLiteStore{ @@ -177,7 +198,7 @@ func (sls *SQLiteStore) EndBatch() error { return nil } -func (sls *SQLiteStore) UpsertItem(item Item) error { +func (sls *SQLiteStore) UpsertItem(item *Item) error { if sls.batch != nil { return sls.upsertItem(sls.batch, item) } @@ -189,7 +210,7 @@ type statementPreparer interface { Prepare(query string) (*sql.Stmt, error) } -func (sls *SQLiteStore) upsertItem(db statementPreparer, item Item) error { +func (sls *SQLiteStore) upsertItem(db statementPreparer, item *Item) error { stmt, err := db.Prepare(`select count(id), id from items where feedurl = ? and title = ?;`) if err != nil { return fmt.Errorf("sqlite.go: could not prepare query: %w", err) @@ -201,17 +222,21 @@ func (sls *SQLiteStore) upsertItem(db statementPreparer, item Item) error { if err != nil && !errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("store.go: write %w", err) } - if count == 0 { stmt, err = db.Prepare(`insert into items (feedurl, link, title, content, author, publishedat, createdat, updatedat) values (?, ?, ?, ?, ?, ?, ?, ?)`) if err != nil { return fmt.Errorf("sqlite.go: could not prepare query: %w", err) } - _, err = stmt.Exec(item.FeedURL, item.Link, item.Title, item.Content, item.Author, item.PublishedAt, time.Now(), time.Now()) + result, err := stmt.Exec(item.FeedURL, item.Link, item.Title, item.Content, item.Author, item.PublishedAt, time.Now(), time.Now()) if err != nil { return fmt.Errorf("sqlite.go: Upsert failed: %w", err) } + lastID, err := result.LastInsertId() + if err != nil { + return fmt.Errorf("sqlite.go: No inserted ID: %w", err) + } + item.ID = int(lastID) } else { stmt, err = db.Prepare(`update items set content = ?, updatedat = ? where id = ?`) if err != nil { @@ -223,7 +248,6 @@ func (sls *SQLiteStore) upsertItem(db statementPreparer, item Item) error { return fmt.Errorf("sqlite.go: Upsert failed: %w", err) } } - return nil } @@ -327,7 +351,6 @@ func (sls SQLiteStore) GetAllFeedURLs() ([]string, error) { } func (sls SQLiteStore) DeleteByFeedURL(feedurl string, incFavourites bool) error { - var stmt *sql.Stmt if incFavourites { stmt, _ = sls.db.Prepare(`delete from items where feedurl = ?;`)