Refactored the way views are stored with a mgiration off the old data (to be removed)
This commit is contained in:
parent
7113a7bd05
commit
2c8af03164
5 changed files with 165 additions and 83 deletions
27
app/app.go
27
app/app.go
|
@ -292,21 +292,33 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
views, err := a.Store.GetViews(prefix, id)
|
views, err := a.Store.GetViews(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("error retrieving views for %s %s: %w", prefix, id, err)
|
err := fmt.Errorf("error retrieving views for %s: %w", id, err)
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
playing.Views = views
|
playing.Views = views
|
||||||
|
|
||||||
|
playlist := a.Library.Playlist()
|
||||||
|
|
||||||
|
// TODO: Optimize this? Bitcask has no concept of MultiGet / MGET
|
||||||
|
for _, video := range playlist {
|
||||||
|
views, err := a.Store.GetViews(video.ID)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("error retrieving views for %s: %w", video.ID, err)
|
||||||
|
log.Warn(err)
|
||||||
|
}
|
||||||
|
video.Views = views
|
||||||
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
ctx := &struct {
|
ctx := &struct {
|
||||||
Playing *media.Video
|
Playing *media.Video
|
||||||
Playlist media.Playlist
|
Playlist media.Playlist
|
||||||
}{
|
}{
|
||||||
Playing: playing,
|
Playing: playing,
|
||||||
Playlist: a.Library.Playlist(),
|
Playlist: playlist,
|
||||||
}
|
}
|
||||||
a.render("index", w, ctx)
|
a.render("index", w, ctx)
|
||||||
}
|
}
|
||||||
|
@ -325,8 +337,13 @@ func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Store.IncView(prefix, id); err != nil {
|
if err := a.Store.Migrate(prefix, id); err != nil {
|
||||||
err := fmt.Errorf("error updating view for %s %s: %w", prefix, id, err)
|
err := fmt.Errorf("error migrating store data: %w", err)
|
||||||
|
log.Warn(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.Store.IncViews(id); err != nil {
|
||||||
|
err := fmt.Errorf("error updating view for %s: %w", id, err)
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,38 @@ func NewBitcaskStore(path string, options ...bitcask.Option) (Store, error) {
|
||||||
return &BitcaskStore{db: db}, nil
|
return &BitcaskStore{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migrate ...
|
||||||
|
func (s *BitcaskStore) Migrate(collection, id string) error {
|
||||||
|
if s.db.Has([]byte(fmt.Sprintf("/views/%s/%s", collection, id))) {
|
||||||
|
oldViews, err := s.GetViews_(collection, id)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("error getting old views for %s %s: %w", collection, id, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(buf, uint64(oldViews))
|
||||||
|
err = s.db.Put([]byte(fmt.Sprintf("/views/%s/%s", id)), buf)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("error storing new views for %s: %w", id, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.db.Delete([]byte(fmt.Sprintf("/views/%s/%s", collection, id))); err != nil {
|
||||||
|
err := fmt.Errorf("error deleting old views for %s %s: %w", collection, id, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Close ...
|
// Close ...
|
||||||
func (s *BitcaskStore) Close() error {
|
func (s *BitcaskStore) Close() error {
|
||||||
return s.db.Close()
|
return s.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetViews ...
|
// GetViews_ ...
|
||||||
func (s *BitcaskStore) GetViews(collection, id string) (int64, error) {
|
func (s *BitcaskStore) GetViews_(collection, id string) (int64, error) {
|
||||||
var views uint64
|
var views uint64
|
||||||
rawViews, err := s.db.Get([]byte(fmt.Sprintf("/views/%s/%s", collection, id)))
|
rawViews, err := s.db.Get([]byte(fmt.Sprintf("/views/%s/%s", collection, id)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,9 +70,9 @@ func (s *BitcaskStore) GetViews(collection, id string) (int64, error) {
|
||||||
return int64(views), nil
|
return int64(views), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncView ...
|
// IncView_ ...
|
||||||
func (s *BitcaskStore) IncView(collection, id string) error {
|
func (s *BitcaskStore) IncView_(collection, id string) error {
|
||||||
views, err := s.GetViews(collection, id)
|
views, err := s.GetViews_(collection, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("error getting existing views for %s %s: %w", collection, id, err)
|
err := fmt.Errorf("error getting existing views for %s %s: %w", collection, id, err)
|
||||||
return err
|
return err
|
||||||
|
@ -64,3 +89,40 @@ func (s *BitcaskStore) IncView(collection, id string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetViews ...
|
||||||
|
func (s *BitcaskStore) GetViews(id string) (int64, error) {
|
||||||
|
var views uint64
|
||||||
|
rawViews, err := s.db.Get([]byte(fmt.Sprintf("/views/%s", id)))
|
||||||
|
if err != nil {
|
||||||
|
if err != bitcask.ErrKeyNotFound {
|
||||||
|
err := fmt.Errorf("error getting views for %s: %w", id, err)
|
||||||
|
log.Error(err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
views = binary.BigEndian.Uint64(rawViews)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int64(views), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncViews ...
|
||||||
|
func (s *BitcaskStore) IncViews(id string) error {
|
||||||
|
views, err := s.GetViews(id)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("error getting existing views for %s: %w", id, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 8)
|
||||||
|
views++
|
||||||
|
binary.BigEndian.PutUint64(buf, uint64(views))
|
||||||
|
err = s.db.Put([]byte(fmt.Sprintf("/views/%s", id)), buf)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("error storing updated views for %s: %w", id, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
140
app/rice-box.go
140
app/rice-box.go
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,9 @@ package app
|
||||||
// Store ...
|
// Store ...
|
||||||
type Store interface {
|
type Store interface {
|
||||||
Close() error
|
Close() error
|
||||||
GetViews(collection, id string) (int64, error)
|
Migrate(collection, id string) error
|
||||||
IncView(collection, id string) error
|
GetViews_(collection, id string) (int64, error)
|
||||||
|
IncView_(collection, id string) error
|
||||||
|
GetViews(id string) (int64, error)
|
||||||
|
IncViews(id string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<img src="/t/{{ $m.ID }}">
|
<img src="/t/{{ $m.ID }}">
|
||||||
<div>
|
<div>
|
||||||
<h1>{{ $m.Title }}</h1>
|
<h1>{{ $m.Title }}</h1>
|
||||||
<h2>{{ $m.Modified }}</h2>
|
<h2>{{ $m.Views }} views • {{ $m.Modified }}</h2>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
Loading…
Reference in a new issue