nlink/nomad/db.go

126 lines
2.2 KiB
Go

package nomad
import (
"database/sql"
"fmt"
"git.wntrmute.dev/kyle/goutils/log"
_ "github.com/glebarez/go-sqlite"
)
type Executor interface {
Exec(stmt string, args ...interface{}) (sql.Result, error)
Query(stmt string, args ...interface{}) (*sql.Rows, error)
}
func buildArgs(n int) string {
s := ""
for i := 0; i < n; i++ {
s += "?,"
}
return s[:len(s)-1]
}
type DB struct {
path string
db *sql.DB
}
func NewDB(path string) *DB {
return &DB{path: path}
}
func (db *DB) Connect() (err error) {
if db.db != nil {
return nil
}
db.db, err = sql.Open("sqlite", db.path)
return err
}
func (db *DB) Close() error {
if db.db == nil {
return nil
}
err := db.db.Close()
db.db = nil
return err
}
func (db *DB) Create() (err error) {
err = db.Connect()
if err != nil {
return err
}
_, err = db.db.Exec(createSQL)
return err
}
func (db *DB) Begin() (tx *sql.Tx, err error) {
err = db.Connect()
if err != nil {
return tx, err
}
return db.db.Begin()
}
func (db *DB) executor(tx *sql.Tx) Executor {
if tx != nil {
return tx
}
return db.db
}
func (db *DB) Mark(tx *sql.Tx, item Item) (err error) {
log.Debugf("marking item %s", item.Title)
_, err = db.executor(tx).Exec(markSQL, item.URL.ID(), item.Title, item.PubDate)
if err != nil {
log.Debugf("failed to mark item %s: %s", item.Title, err)
return err
}
return nil
}
func (db *DB) Filter(tx *sql.Tx, items []Item) (newItems []Item, err error) {
seen := map[string]bool{}
args := buildArgs(len(items))
stmt := fmt.Sprintf(filterSQLTpl, args)
urls := make([]interface{}, 0, len(items))
for _, item := range items {
urls = append(urls, item.URL.ID())
}
rows, err := db.executor(tx).Query(stmt, urls...)
if err != nil {
return nil, err
}
for rows.Next() {
var url string
err = rows.Scan(&url)
if err != nil {
return nil, err
}
seen[url] = true
}
for _, item := range items {
if seen[item.URL.ID()] {
continue
}
newItems = append(newItems, item)
}
// Reverse the list of items so that they are in reverse chronological order.
nitems := len(items) - 1
for i := range items {
j := nitems - i
items[i], items[j] = items[j], items[i]
}
return newItems, nil
}