Refactored the way views are stored with a mgiration off the old data (to be removed)

This commit is contained in:
James Mills 2020-03-25 16:01:29 +10:00
parent 7113a7bd05
commit 2c8af03164
No known key found for this signature in database
GPG key ID: AC4C014F1440EBD6
5 changed files with 165 additions and 83 deletions

View file

@ -292,21 +292,33 @@ func (a *App) pageHandler(w http.ResponseWriter, r *http.Request) {
return
}
views, err := a.Store.GetViews(prefix, id)
views, err := a.Store.GetViews(id)
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)
}
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")
ctx := &struct {
Playing *media.Video
Playlist media.Playlist
}{
Playing: playing,
Playlist: a.Library.Playlist(),
Playlist: playlist,
}
a.render("index", w, ctx)
}
@ -325,8 +337,13 @@ func (a *App) videoHandler(w http.ResponseWriter, r *http.Request) {
return
}
if err := a.Store.IncView(prefix, id); err != nil {
err := fmt.Errorf("error updating view for %s %s: %w", prefix, id, err)
if err := a.Store.Migrate(prefix, id); err != nil {
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)
}

View file

@ -23,13 +23,38 @@ func NewBitcaskStore(path string, options ...bitcask.Option) (Store, error) {
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 ...
func (s *BitcaskStore) Close() error {
return s.db.Close()
}
// GetViews ...
func (s *BitcaskStore) GetViews(collection, id string) (int64, error) {
// GetViews_ ...
func (s *BitcaskStore) GetViews_(collection, id string) (int64, error) {
var views uint64
rawViews, err := s.db.Get([]byte(fmt.Sprintf("/views/%s/%s", collection, id)))
if err != nil {
@ -45,9 +70,9 @@ func (s *BitcaskStore) GetViews(collection, id string) (int64, error) {
return int64(views), nil
}
// IncView ...
func (s *BitcaskStore) IncView(collection, id string) error {
views, err := s.GetViews(collection, id)
// IncView_ ...
func (s *BitcaskStore) IncView_(collection, id string) error {
views, err := s.GetViews_(collection, id)
if err != nil {
err := fmt.Errorf("error getting existing views for %s %s: %w", collection, id, err)
return err
@ -64,3 +89,40 @@ func (s *BitcaskStore) IncView(collection, id string) error {
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
}

File diff suppressed because one or more lines are too long

View file

@ -3,6 +3,9 @@ package app
// Store ...
type Store interface {
Close() error
GetViews(collection, id string) (int64, error)
IncView(collection, id string) error
Migrate(collection, id string) error
GetViews_(collection, id string) (int64, error)
IncView_(collection, id string) error
GetViews(id string) (int64, error)
IncViews(id string) error
}

View file

@ -20,7 +20,7 @@
<img src="/t/{{ $m.ID }}">
<div>
<h1>{{ $m.Title }}</h1>
<h2>{{ $m.Modified }}</h2>
<h2>{{ $m.Views }} views • {{ $m.Modified }}</h2>
</div>
</a>
{{ end }}