Skip to content

Commit

Permalink
Merge pull request #76 from jmillerv/50-enusre-schedulershuffle-has-p…
Browse files Browse the repository at this point in the history
…arity-with-schedulerrun

50 ensure schedulershuffle has parity with schedule run
  • Loading branch information
jmillerv authored Sep 23, 2023
2 parents 4145afc + af596a7 commit 2d469e4
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 34 deletions.
6 changes: 2 additions & 4 deletions content/podcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,14 @@ func (p *Podcast) Get() error { //nolint:cyclop,funlen // complexity of 11, igno
func (p *Podcast) Play() error {
log.Infof("streaming from %v ", p.URL)

if !p.Player.isPlaying {
if !p.Player.isPlaying { //nolint:nestif
log.WithField("episode", p.EpisodeGUID).Info("setting podcast played cache")

cacheData, cacheHit := cache.PodcastPlayedCache.Get(defaultPodcastCache)
if cacheHit {

_, ok := cacheData.(podcastCacheData)
if ok {
podcastCache = cacheData.(podcastCacheData)
podcastCache = cacheData.(podcastCacheData) //nolint:forcetypeassert

if p.EpisodeGUID != "" {
podcastCache.Guids = append(podcastCache.Guids, p.EpisodeGUID)
Expand All @@ -136,7 +135,6 @@ func (p *Podcast) Play() error {
}

err = p.Player.command.Start()

if err != nil {
return errors.Wrap(err, "podcast.Play::error starting podcast streamPlayer")
}
Expand Down
2 changes: 1 addition & 1 deletion content/podcast_episodes_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func (p *podcasts) getNewestEpisode() episode {
for i, ep := range p.Episodes {
// check for cacheData cache
cacheData, cacheHit := cache.PodcastPlayedCache.Get(defaultPodcastCache)
log.WithField("data", cacheData).WithField("hit", cacheHit).Info("cache data")

if cacheHit {
log.WithField("data", cacheData).WithField("hit", cacheHit).Debug("cache data")
retrieved := (&podcastCacheData{}).fromCache(cacheData) //nolint:exhaustruct // need type casting

// check for nil retrieved guids
Expand Down
122 changes: 93 additions & 29 deletions content/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,17 @@ func (s *Scheduler) Run() error { //nolint:godox,funlen,gocognit,cyclop,nolintli

// run operation in loop
for programIndex <= totalPrograms {
log.Infof("program index count %d", programIndex)
// check content from scheduler and run through it
// for loop that can be forced to continue from a go routine
for _, p := range s.Content.Programs {
now := time.Now()

log.Debugf("program %v", formatter.StructToIndentedString(p))
log.Infof("program %v", formatter.StructToIndentedString(p))

// if content is scheduled, retrieve and play
scheduled := p.Timeslot.IsScheduledNow(now)
if scheduled { //nolint:nestif // TODO: consider refactoring
if scheduled {
log.Infof("scheduler.Run::getting media type: %v", p.Type)

content := p.GetMedia()
Expand All @@ -76,39 +77,47 @@ func (s *Scheduler) Run() error { //nolint:godox,funlen,gocognit,cyclop,nolintli

// if p.getMediaType is webRadioContent or podcastContent start a timer and stop content from inside a go routine
// because these are streams rather than files they behave differently from local content.
//nolint:gocritic,godox,nolintlint // TODO: refactor as a switch case and remove the nolint directive
if p.getMediaType() == webRadioContent {
switch p.getMediaType() { //nolint:exhaustive // TODO consider refactoring into function
case webRadioContent:
log.Info("webradio content detected")

go func() {
duration := getDurationToEndTime(p.Timeslot.End) // might cause an index out of range issue
stopCountDown(content, duration, &wg)
}()

wg.Add(1)

go func() {
defer wg.Done()
log.Info("playing web radio inside of a go routine")

wg.Add(1)

err = content.Play()
if err != nil {
log.WithError(err).Error("Run::content.Play")
} // play will block until done
}()
} else if p.getMediaType() == podcastContent {
case podcastContent:
log.Info("podcast content detected")

go func() {
podcast := content.(*Podcast) //nolint:forcetypeassert // TODO: type checking
log.Infof("podcast player duration %s", podcast.Player.duration)
stopCountDown(content, podcast.Player.duration, &wg)
}()

wg.Add(1)

go func() {
defer wg.Done()
log.Info("playing podcast inside of a go routine")
wg.Add(1)

err = content.Play()
if err != nil {
log.WithError(err).Error("Run::content.Play")
} // play will block until done
}()
} else {
default:
err = content.Play() // play will block until done
if err != nil {
return err
Expand All @@ -117,7 +126,6 @@ func (s *Scheduler) Run() error { //nolint:godox,funlen,gocognit,cyclop,nolintli
}

log.Info("paused while go routines are running")

wg.Wait() // pause

if !p.Timeslot.IsScheduledNow(now) {
Expand Down Expand Up @@ -159,7 +167,11 @@ func (s *Scheduler) Run() error { //nolint:godox,funlen,gocognit,cyclop,nolintli
}

// Shuffle plays through the config content at random.
func (s *Scheduler) Shuffle() error {
func (s *Scheduler) Shuffle() error { //nolint:godox,funlen,gocognit,cyclop,nolintlint // TODO: consider refactoring
wg := new(sync.WaitGroup)

log.Info("Starting Daemon")

rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(s.Content.Programs),
func(i, j int) {
Expand All @@ -173,28 +185,80 @@ func (s *Scheduler) Shuffle() error {

exitchnl := make(chan int)

for _, p := range s.Content.Programs {
log.Debugf("program %v", formatter.StructToIndentedString(p))
log.Infof("getting media type: %v", p.Type)
content := p.GetMedia()
log.Debugf("media struct: %v", content)
totalPrograms := len(s.Content.Programs)
programIndex := 0

err := content.Get()
if err != nil {
return err
}
// run operation in loop
for programIndex <= totalPrograms {
for _, p := range s.Content.Programs {
log.Debugf("program %v", formatter.StructToIndentedString(p))
log.Infof("getting media type: %v", p.Type)
content := p.GetMedia()
log.Debugf("media struct: %v", content)

go func() {
for {
stop := <-sigchnl
s.Stop(stop, content)
err := content.Get()
if err != nil {
return err
}
}()

err = content.Play()
if err != nil {
return err
} // play will block until done
// setup channel for os.Exit signal
go func() {
for {
stop := <-sigchnl
s.Stop(stop, content)
}
}()

// if p.getMediaType is webRadioContent or podcastContent start a timer and stop content from inside a go routine
// because these are streams rather than files they behave differently from local content.
//nolint:godox,nolintlint // TODO: consider refactoring switch into single function used in Run() & Shuffle()
switch p.getMediaType() { //nolint:dupl,exhaustive
case webRadioContent:
go func() {
duration := getDurationToEndTime(p.Timeslot.End) // might cause an index out of range issue
stopCountDown(content, duration, wg)
}()

wg.Add(1)

go func() {
defer wg.Done()
log.Info("playing web radio inside of a go routine")

err = content.Play()
if err != nil {
log.WithError(err).Error("Run::content.Play")
} // play will block until done
}()
case podcastContent:
go func() {
podcast := content.(*Podcast) //nolint:forcetypeassert // TODO: type checking
log.Infof("podcast player duration %s", podcast.Player.duration)
stopCountDown(content, podcast.Player.duration, wg)
}()

wg.Add(1)

go func() {
defer wg.Done()
log.Info("playing podcast inside of a go routine")

err = content.Play()
if err != nil {
log.WithError(err).Error("Run::content.Play")
} // play will block until done
}()
default:
err = content.Play() // play will block until done
if err != nil {
return err
}
}

log.Info("paused while go routines are running")
wg.Wait() // pause
programIndex++ // increment index
}
}

exitcode := <-exitchnl
Expand Down

0 comments on commit 2d469e4

Please sign in to comment.