···1313}
14141515func Open(path string) (*DB, error) {
1616- db, err := sql.Open("sqlite3", path+"?_foreign_keys=on")
1616+ db, err := sql.Open("sqlite3", path+"?_foreign_keys=on&_journal_mode=WAL&_busy_timeout=5000")
1717 if err != nil {
1818 return nil, fmt.Errorf("open database: %w", err)
1919 }
2020+2121+ // SQLite works best with single writer for WAL mode
2222+ db.SetMaxOpenConns(1)
2323+ db.SetMaxIdleConns(1)
20242125 if err := db.Ping(); err != nil {
2226 return nil, fmt.Errorf("ping database: %w", err)
···9094 );
91959296 CREATE INDEX IF NOT EXISTS idx_configs_user_id ON configs(user_id);
9393- CREATE INDEX IF NOT EXISTS idx_configs_next_run ON configs(next_run);
9797+ CREATE INDEX IF NOT EXISTS idx_configs_active_next_run ON configs(next_run) WHERE next_run IS NOT NULL;
9498 CREATE INDEX IF NOT EXISTS idx_feeds_config_id ON feeds(config_id);
9599 CREATE INDEX IF NOT EXISTS idx_seen_items_feed_id ON seen_items(feed_id);
96100 CREATE INDEX IF NOT EXISTS idx_logs_config_id ON logs(config_id);