ytui/db/db.go

126 lines
2.2 KiB
Go
Raw Permalink Normal View History

2022-06-14 15:33:34 -04:00
package db
import (
"encoding/json"
"errors"
"fmt"
"os"
"sync"
2022-06-28 15:26:16 -04:00
"gitlab.com/balki/ytui/pubsub"
2022-06-14 15:33:34 -04:00
)
type DownloadStatus string
var (
NotStarted DownloadStatus = "NotStarted"
InProgress DownloadStatus = "InProgress"
Done DownloadStatus = "Done"
Error DownloadStatus = "Error"
)
type Item struct {
2022-06-29 17:50:31 -04:00
Id int `json:"id"`
Date string `json:"date"`
URL string `json:"url"`
Title string `json:"title"`
Status DownloadStatus `json:"status"`
FileName string `json:"file_name"`
Pt pubsub.ProgressTracker `json:"-"`
TitleChan <-chan struct{} `json:"-"`
2022-06-14 15:33:34 -04:00
}
type Jdb struct {
Items []Item `json:"items"`
}
type Db struct {
items []Item
mutex sync.Mutex
lastId int
path string
2022-06-28 15:26:16 -04:00
index map[string]int
2022-06-14 15:33:34 -04:00
}
2022-06-28 15:26:16 -04:00
func (d *Db) Add(i Item) (int, bool) {
2022-06-14 15:33:34 -04:00
d.mutex.Lock()
defer d.mutex.Unlock()
2022-06-28 15:26:16 -04:00
if id, ok := d.index[i.URL]; ok {
return id, false
}
2022-06-14 15:33:34 -04:00
i.Id = d.lastId
d.lastId++
d.items = append(d.items, i)
d.save()
2022-06-28 15:26:16 -04:00
d.index[i.URL] = i.Id
return i.Id, true
2022-06-14 15:33:34 -04:00
}
2022-06-30 12:49:15 -04:00
func (d *Db) Transact(id int, persist bool, f func(*Item)) error {
2022-06-14 15:33:34 -04:00
d.mutex.Lock()
defer d.mutex.Unlock()
2022-10-25 14:39:17 -04:00
for i := range d.items {
2022-06-14 15:33:34 -04:00
if d.items[i].Id == id {
f(&d.items[i])
if persist {
d.save()
}
return nil
}
}
2022-10-25 14:39:17 -04:00
return fmt.Errorf("invalid id: %d", id)
2022-06-14 15:33:34 -04:00
}
func (d *Db) save() error {
2022-07-14 16:13:27 -04:00
data, err := json.Marshal(Jdb{d.items})
2022-06-14 15:33:34 -04:00
if err != nil {
return err
}
return os.WriteFile(d.path, data, 0644)
}
func (d *Db) Run(f func(*Jdb)) {
d.mutex.Lock()
defer d.mutex.Unlock()
2022-07-14 16:13:27 -04:00
f(&Jdb{d.items})
2022-06-14 15:33:34 -04:00
}
func (d *Db) Save() error {
d.mutex.Lock()
defer d.mutex.Unlock()
return d.save()
}
func Load(path string) (*Db, error) {
data, err := os.ReadFile(path)
2022-10-25 14:39:17 -04:00
indexMap := map[string]int{}
2022-06-14 15:33:34 -04:00
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return &Db{
path: path,
lastId: 0,
2022-10-25 14:39:17 -04:00
index: indexMap,
2022-06-14 15:33:34 -04:00
}, nil
}
return nil, err
}
var jd Jdb
err = json.Unmarshal(data, &jd)
if err != nil {
return nil, err
}
m := 0
for _, item := range jd.Items {
if item.Id > m {
m = item.Id
}
2022-06-28 15:26:16 -04:00
indexMap[item.URL] = item.Id
2022-06-14 15:33:34 -04:00
}
return &Db{
items: jd.Items,
path: path,
lastId: m + 1,
2022-06-28 15:26:16 -04:00
index: indexMap,
2022-06-14 15:33:34 -04:00
}, nil
}