diff --git a/cmd/data/articles.go b/cmd/data/articles.go index a174dc1..85c4982 100644 --- a/cmd/data/articles.go +++ b/cmd/data/articles.go @@ -1,6 +1,7 @@ package data import ( + "sync" "time" "github.com/google/uuid" @@ -16,14 +17,25 @@ type Article struct { } type ArticleList struct { - addCh chan *Article - delCh chan uuid.UUID - retCh chan *Article - listCh chan []Article - list []*Article + addCh chan *Article + delCh chan uuid.UUID + retCh chan *Article + getCh chan []Article + list []*Article + wg sync.WaitGroup +} + +func minArticleList() *ArticleList { + return &ArticleList{ + addCh: make(chan *Article), + delCh: make(chan uuid.UUID), + retCh: make(chan *Article), + getCh: make(chan []Article), + } } func (l *ArticleList) start() { + l.wg.Done() for { select { case article := <-l.addCh: @@ -35,7 +47,7 @@ func (l *ArticleList) start() { l.retCh <- article } } - case l.listCh <- func() []Article { + case l.getCh <- func() []Article { var list []Article for _, article := range l.list { list = append(list, *article) @@ -47,14 +59,13 @@ func (l *ArticleList) start() { } func NewArticleList() *ArticleList { - list := &ArticleList{ - addCh: make(chan *Article), - delCh: make(chan uuid.UUID), - retCh: make(chan *Article), - listCh: make(chan []Article), - list: []*Article{}, - } + list := minArticleList() + list.list = []*Article{} + + list.wg.Add(1) go list.start() + list.wg.Wait() + return list } @@ -71,6 +82,6 @@ func (l *ArticleList) Release(uuid uuid.UUID) (*Article, bool) { return article, true } -func (l *ArticleList) List() []Article { - return <-l.listCh +func (l *ArticleList) Get() []Article { + return <-l.getCh } diff --git a/cmd/data/rss.go b/cmd/data/rss.go index c34b1e7..3801f10 100644 --- a/cmd/data/rss.go +++ b/cmd/data/rss.go @@ -4,57 +4,74 @@ import ( "encoding/gob" "fmt" "os" + "sync" "github.com/gorilla/feeds" ) type Feed struct { - addCh chan *feeds.Item - openCh chan feeds.Feed - saveCh chan feeds.Feed - showCh chan feeds.Feed - feed feeds.Feed + addCh chan *feeds.Item + setCh chan feeds.Feed + getCh chan feeds.Feed + feed feeds.Feed + wg sync.WaitGroup +} + +func minFeed() *Feed { + return &Feed{ + addCh: make(chan *feeds.Item), + setCh: make(chan feeds.Feed), + getCh: make(chan feeds.Feed), + } } func (f *Feed) start() { + f.wg.Done() for { select { case item := <-f.addCh: f.feed.Items = append(f.feed.Items, item) - case f.saveCh <- f.feed: - case tmpFeed := <-f.openCh: - f.feed = tmpFeed - case f.showCh <- f.feed: + case f.getCh <- f.feed: + case f.feed = <-f.setCh: } } } func NewFeed(title, link, desc string) *Feed { - feed := &Feed{ - addCh: make(chan *feeds.Item), - openCh: make(chan feeds.Feed), - saveCh: make(chan feeds.Feed), - showCh: make(chan feeds.Feed), - feed: feeds.Feed{ - Title: title, - Link: &feeds.Link{Href: link}, - Description: desc, - }, + feed := minFeed() + feed.feed = feeds.Feed{ + Title: title, + Link: &feeds.Link{Href: link}, + Description: desc, } + + feed.wg.Add(1) go feed.start() + feed.wg.Wait() + return feed } -func OpenFeed(filename string) (*Feed, error) { - feed := new(Feed) - go feed.start() +func (f *Feed) Get() feeds.Feed { + return <-f.getCh +} +func (f *Feed) Set(feed feeds.Feed) { + f.setCh <- feed +} + +func OpenFeed(filename string) (*Feed, error) { file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("error opening file %v: %v", filename, err) } defer file.Close() + feed := minFeed() + feed.wg.Add(1) + go feed.start() + feed.wg.Wait() + decoder := gob.NewDecoder(file) tmpFeed := new(feeds.Feed) err = decoder.Decode(tmpFeed) @@ -62,7 +79,7 @@ func OpenFeed(filename string) (*Feed, error) { return nil, fmt.Errorf("error decoding file %v: %v", filename, err) } - feed.openCh <- *tmpFeed + feed.Set(*tmpFeed) return feed, nil } @@ -75,7 +92,7 @@ func (f *Feed) Save(filename string) error { defer file.Close() encoder := gob.NewEncoder(file) - feed := <-f.saveCh + feed := f.Get() err = encoder.Encode(feed) if err != nil { return fmt.Errorf("error encoding file %v: %v", filename, err) @@ -87,7 +104,3 @@ func (f *Feed) Save(filename string) error { func (f *Feed) Add(i *feeds.Item) { f.addCh <- i } - -func (f *Feed) Show() feeds.Feed { - return <-f.showCh -} diff --git a/cmd/ui/articles.go b/cmd/ui/articles.go index f08ee4e..a3c9281 100644 --- a/cmd/ui/articles.go +++ b/cmd/ui/articles.go @@ -60,7 +60,7 @@ func FinishArticle(l *data.ArticleList) http.HandlerFunc { func ShowUnpublishedArticles(l *data.ArticleList) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - template.Must(template.ParseFiles("web/templates/unpublished-articles.html")).ExecuteTemplate(w, "page-content", l.List) + template.Must(template.ParseFiles("web/templates/unpublished-articles.html")).ExecuteTemplate(w, "page-content", l.Get()) } } @@ -73,7 +73,7 @@ func ReviewArticle(l *data.ArticleList) http.HandlerFunc { return } - for _, article := range l.List() { + for _, article := range l.Get() { if article.UUID == uuid { template.Must(template.ParseFiles("web/templates/to-be-published.html")).ExecuteTemplate(w, "page-content", article) return diff --git a/cmd/ui/rss.go b/cmd/ui/rss.go index 1b373c1..1b7e4bb 100644 --- a/cmd/ui/rss.go +++ b/cmd/ui/rss.go @@ -10,7 +10,7 @@ import ( func ShowRSS(f *data.Feed) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - feed := f.Show() + feed := f.Get() rss, err := feed.ToRss() if err != nil { log.Println(err)