197 lines
3.5 KiB
Go
197 lines
3.5 KiB
Go
package data
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Article struct {
|
|
Title string
|
|
Author string
|
|
Created time.Time
|
|
Desc string
|
|
Content string
|
|
Tags []string
|
|
UUID uuid.UUID
|
|
AuthorID int64
|
|
}
|
|
|
|
type ArticleList struct {
|
|
addCh chan *Article
|
|
delCh chan uuid.UUID
|
|
retCh chan *Article
|
|
getCh chan []Article
|
|
articles []*Article
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
type TagList struct {
|
|
addCh chan string
|
|
getCh chan []string
|
|
tags []string
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
func initArticleList() *ArticleList {
|
|
return &ArticleList{
|
|
addCh: make(chan *Article),
|
|
delCh: make(chan uuid.UUID),
|
|
retCh: make(chan *Article),
|
|
getCh: make(chan []Article),
|
|
}
|
|
}
|
|
|
|
func initTagList() *TagList {
|
|
return &TagList{
|
|
addCh: make(chan string),
|
|
getCh: make(chan []string),
|
|
}
|
|
}
|
|
|
|
func (al *ArticleList) start() {
|
|
al.wg.Done()
|
|
for {
|
|
select {
|
|
case article := <-al.addCh:
|
|
al.articles = append(al.articles, article)
|
|
case uuid := <-al.delCh:
|
|
for i, article := range al.articles {
|
|
if article.UUID == uuid {
|
|
al.articles = append(al.articles[:i], al.articles[i+1:]...)
|
|
al.retCh <- article
|
|
}
|
|
}
|
|
case al.getCh <- func() []Article {
|
|
var list []Article
|
|
for _, article := range al.articles {
|
|
list = append(list, *article)
|
|
}
|
|
return list
|
|
}():
|
|
}
|
|
}
|
|
}
|
|
|
|
func (tl *TagList) start() {
|
|
tl.wg.Done()
|
|
for {
|
|
select {
|
|
case tag := <-tl.addCh:
|
|
tl.tags = append(tl.tags, tag)
|
|
case tl.getCh <- tl.tags:
|
|
}
|
|
}
|
|
}
|
|
|
|
func NewArticleList() *ArticleList {
|
|
list := initArticleList()
|
|
list.articles = []*Article{}
|
|
|
|
list.wg.Add(1)
|
|
go list.start()
|
|
list.wg.Wait()
|
|
|
|
return list
|
|
}
|
|
|
|
func (al *ArticleList) Add(a *Article) {
|
|
al.addCh <- a
|
|
}
|
|
|
|
func (al *ArticleList) Release(uuid uuid.UUID) (*Article, bool) {
|
|
al.delCh <- uuid
|
|
article := <-al.retCh
|
|
|
|
if article == nil {
|
|
return nil, false
|
|
}
|
|
return article, true
|
|
}
|
|
|
|
func (al *ArticleList) Get() []Article {
|
|
return <-al.getCh
|
|
}
|
|
|
|
func (al *ArticleList) Save(filename string) error {
|
|
file, err := os.Create(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating key file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
articles := al.Get()
|
|
if err = gob.NewEncoder(file).Encode(articles); err != nil {
|
|
return fmt.Errorf("error ecoding key: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func LoadArticleList(filename string) (*ArticleList, error) {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error opening key file: %v", err)
|
|
}
|
|
|
|
articleList := NewArticleList()
|
|
if err = gob.NewDecoder(file).Decode(&articleList.articles); err != nil {
|
|
return nil, fmt.Errorf("error decoding key: %v", err)
|
|
}
|
|
|
|
return articleList, nil
|
|
}
|
|
|
|
func NewTagList() *TagList {
|
|
list := initTagList()
|
|
list.tags = []string{}
|
|
|
|
list.wg.Add(1)
|
|
go list.start()
|
|
list.wg.Wait()
|
|
|
|
return list
|
|
}
|
|
|
|
func (tl *TagList) Add(tag string) {
|
|
tl.addCh <- tag
|
|
}
|
|
|
|
func (tl *TagList) Get() []string {
|
|
return <-tl.getCh
|
|
}
|
|
|
|
func (tl *TagList) Save(filename string) error {
|
|
file, err := os.Create(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error creating key file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
tags := tl.Get()
|
|
if err = gob.NewEncoder(file).Encode(tags); err != nil {
|
|
return fmt.Errorf("error ecoding key: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func LoadTagList(filename string) (*TagList, error) {
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error opening key file: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
tagList := NewTagList()
|
|
if err = gob.NewDecoder(file).Decode(&tagList.tags); err != nil {
|
|
return nil, fmt.Errorf("error decoding key: %v", err)
|
|
}
|
|
|
|
return tagList, nil
|
|
}
|