PlaylistController

This commit is contained in:
Dmitry Sergeev
2026-09-01 20:02:42 +03:00
parent ce4ea3fa00
commit b160e3aba2
2 changed files with 418 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
package playback
import (
"context"
"errors"
"sync"
)
type PlaylistController struct {
playlist Playlist
retry RetryPolicy
sessions chan<- SessionCommand
mu sync.RWMutex
snapshot PlaylistSnapshot
hasSnapshot bool
}
type PlaylistSnapshot struct {
State PlaylistState
Entry PlaylistEntry
}
var (
ErrNilSessionCommandChannel = errors.New("session-command channel is nil")
)
func NewPlaylistController(
playlist Playlist,
retry RetryPolicy,
sessions chan<- SessionCommand,
) (*PlaylistController, error) {
if err := playlist.Validate(); err != nil {
return nil, err
}
if err := retry.Validate(); err != nil {
return nil, err
}
if sessions == nil {
return nil, ErrNilSessionCommandChannel
}
return &PlaylistController{
playlist: playlist,
retry: retry,
sessions: sessions,
}, nil
}
func (c *PlaylistController) Run(
ctx context.Context,
commands <-chan PlaylistCommand,
) error {
state := PlaylistState{}
c.publish(state)
for {
select {
case <-ctx.Done():
return ctx.Err()
case command, ok := <-commands:
if !ok {
return nil
}
next, sessionCommand, apply, err := ApplyPlaylistSelection(
c.playlist,
state,
command,
c.retry,
)
if err != nil {
continue
}
if apply {
select {
case <-ctx.Done():
return ctx.Err()
case c.sessions <- sessionCommand:
}
}
state = next
c.publish(state)
}
}
}
func (c *PlaylistController) Snapshot() (PlaylistSnapshot, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
return c.snapshot, c.hasSnapshot
}
func (c *PlaylistController) publish(state PlaylistState) {
entry, _ := state.Entry(c.playlist)
c.mu.Lock()
c.snapshot = PlaylistSnapshot{State: state, Entry: entry}
c.hasSnapshot = true
c.mu.Unlock()
}