// Run runs the safeguard func (s *Safeguard) Run(log *logrus.Entry) error { s.wg.Add(1) defer s.wg.Done() log = log.WithField("module", "safeguard") log.Debug("safeguard started") for { select { case <-s.done: log.Debug("safeguard stopped") return nil case <-s.event: // Increase the event count s.count++ if s.count >= MaxEventCount { ctx := errors.Context{ "current_count": s.count, "max_count": MaxEventCount, } return errors.New("got %d safeguard events in less than %s", s.count, MaxEventDelay).Fatal().AddContext(ctx) } case <-time.After(MaxEventDelay): // Reset the panic count is there was not panic during the // MaxPanicDelay s.count = 0 } } }
// startFsNotifier starts the FsNotifier func (o *Organizer) startFsNotifier(log *logrus.Entry) error { ctx := polochon.FsNotifierCtx{ Event: o.event, Done: o.Done, Wg: &o.Wg, } // Send a notification to organize the whole folder on app start watcherPath := o.config.Watcher.Dir ctx.Event <- watcherPath // Launch the FsNotifier if err := o.config.Watcher.FsNotifier.Watch(watcherPath, ctx, log); err != nil { return err } var err error o.Wg.Add(1) go func() { defer func() { o.Wg.Done() if r := recover(); r != nil { err = errors.New("panic recovered").Fatal().AddContext(errors.Context{ "sub_app": AppName, }) o.Stop(log) } }() for { select { case file := <-ctx.Event: log.WithField("event", file).Debugf("got an event") if err := o.organize(file, log); err != nil { log.Errorf("failed to organize file: %q", err) } case <-o.Done: log.Debug("organizer done handling events") return } } }() o.Wg.Wait() return err }
// Run starts the downloader func (d *Downloader) Run(log *logrus.Entry) error { log = log.WithField("app", AppName) // Init the app d.InitStart(log) log.Debug("downloader started") // Lauch the downloader at startup log.Debug("initial downloader launch") d.event = make(chan struct{}, 1) d.event <- struct{}{} // Start the ticker d.Wg.Add(1) go func() { defer d.Wg.Done() d.ticker(log) }() // Start the downloader var err error d.Wg.Add(1) go func() { defer func() { if r := recover(); r != nil { err = errors.New("panic recovered").Fatal().AddContext(errors.Context{ "sub_app": AppName, }) d.Stop(log) } d.Wg.Done() }() d.downloader(log) }() defer log.Debug("downloader stopped") d.Wg.Wait() return err }
// Run starts the cleaner func (c *Cleaner) Run(log *logrus.Entry) error { log = log.WithField("app", AppName) // Init the app c.InitStart(log) c.event = make(chan struct{}, 1) log.Debug("cleaner started") log.Debug("initial cleaner launch") c.event <- struct{}{} // Start the ticker c.Wg.Add(1) go func() { defer c.Wg.Done() c.ticker(log) }() // Start the cleaner var err error c.Wg.Add(1) go func() { defer func() { if r := recover(); r != nil { err = errors.New("panic recovered").Fatal().AddContext(errors.Context{ "sub_app": AppName, }) c.Stop(log) } c.Wg.Done() }() c.cleaner(log) }() defer log.Debug("cleaner stopped") c.Wg.Wait() return err }
"fmt" "os" "path" "path/filepath" "sync" "time" "github.com/Sirupsen/logrus" "github.com/odwrtw/errors" "github.com/odwrtw/polochon/lib" "github.com/odwrtw/polochon/lib/media_index" ) // Custom errors var ( ErrInvalidIndexVideoType = errors.New("library: invalid index video type") ErrMissingMovieFilePath = errors.New("library: movie has no file path") ErrMissingMovieImageURL = errors.New("library: missing movie images URL") ErrMissingShowImageURL = errors.New("library: missing URL to download show images") ErrMissingShowEpisodeFilePath = errors.New("library: missing file path") ) // Config represents configuration for the library type Config struct { MovieDir string ShowDir string } // Library represents a collection of videos type Library struct { Config