1
0
mirror of https://github.com/mxpv/podsync.git synced 2024-05-11 05:55:04 +00:00

Use cron expression to set update intevals #88 #46

This commit is contained in:
Виктор Диктор
2020-02-09 02:51:30 +03:00
committed by GitHub
parent 0ef90e18af
commit db66f6c73a
5 changed files with 87 additions and 39 deletions

View File

@ -41,7 +41,7 @@ Here is an example how configuration might look like:
```toml
[server]
port = 8080
data_dir = "/path/to/data/directory"
data_dir = "/app/data" # Don't change if you run podsync via docker
[tokens]
youtube = "{YOUTUBE_API_TOKEN}" # Tokens from `Access tokens` section
@ -54,8 +54,9 @@ vimeo = "{VIMEO_API_TOKEN}"
update_period = "12h" # How often query for updates, examples: "60m", "4h", "2h45m"
quality = "high" # or "low"
format = "video" # or "audio"
cover_art = "{IMAGE_URL}" # Optional URL address of an image file
max_height = "720" # Optional maximal height of video, example: 720, 1080, 1440, 2160, ...
# cover_art = "{IMAGE_URL}" # Optional URL address of an image file
# max_height = "720" # Optional maximal height of video, example: 720, 1080, 1440, 2160, ...
# cron_schedule = "@every 12h" # Optional cron expression format. If set then overwrite 'update_period'. See details below
```
Episodes files will be kept at: `/path/to/data/directory/ID1`, feed will be accessible from: `http://localhost/ID1.xml`
@ -72,6 +73,44 @@ hostname = "https://my.test.host:4443"
...
```
## Schedule via cron expression
A cron expression represents a set of times, using 5 space-separated fields.
Field name | Mandatory? | Allowed values | Allowed special characters
---------- | ---------- | -------------- | --------------------------
Minutes | Yes | 0-59 | * / , -
Hours | Yes | 0-23 | * / , -
Day of month | Yes | 1-31 | * / , - ?
Month | Yes | 1-12 or JAN-DEC | * / , -
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
Month and Day-of-week field values are case insensitive. "SUN", "Sun", and "sun" are equally accepted.
The specific interpretation of the format is based on the Cron Wikipedia page: https://en.wikipedia.org/wiki/Cron
### Predefined schedules
You may use one of several pre-defined schedules in place of a cron expression.
Entry | Description | Equivalent To
----- | ----------- | -------------
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 1 1 *
@monthly | Run once a month, midnight, first of month | 0 0 1 * *
@weekly | Run once a week, midnight between Sat/Sun | 0 0 * * 0
@daily (or @midnight) | Run once a day, midnight | 0 0 * * *
@hourly | Run once an hour, beginning of hour | 0 * * * *
### Intervals
You may also schedule a job to execute at fixed intervals, starting at the time it's added
or cron is run. This is supported by formatting the cron spec like this:
@every <duration>
where "duration" is a string accepted by [time.ParseDuration](http://golang.org/pkg/time/#ParseDuration).
For example, "@every 1h30m10s" would indicate a schedule that activates after 1 hour, 30 minutes, 10 seconds, and then every interval after that.
Server will be accessible from `http://localhost:8080`, but episode links will point to `https://my.test.host:4443/ID1/...`
## One click deployment
@ -80,12 +119,12 @@ Server will be accessible from `http://localhost:8080`, but episode links will p
## How to run
Run as binary:
### Run as binary:
```
$ ./podsync --config config.toml
```
Run via Docker:
### Run via Docker:
```
$ docker pull mxpv/podsync:latest
$ docker run \
@ -95,7 +134,7 @@ $ docker run \
mxpv/podsync:latest
```
Run via Docker Compose:
### Run via Docker Compose:
```
$ docker-compose up
```

View File

@ -2,12 +2,15 @@ package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/jessevdk/go-flags"
"github.com/robfig/cron/v3"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
@ -91,10 +94,6 @@ func main() {
log.WithError(err).Fatal("failed to open database")
}
// Queue of feeds to update
updates := make(chan *config.Feed, 16)
defer close(updates)
// Run updater thread
log.Debug("creating updater")
updater, err := NewUpdater(cfg, downloader, database)
@ -102,42 +101,46 @@ func main() {
log.WithError(err).Fatal("failed to create updater")
}
c := cron.New(cron.WithChain(cron.SkipIfStillRunning(nil)))
group.Go(func() error {
for {
select {
case feed := <-updates:
defer func() {
log.Info("shutting down cron")
c.Stop()
}()
for _, feed := range cfg.Feeds {
if feed.CronSchedule == "" {
feed.CronSchedule = fmt.Sprintf("@every %s", feed.UpdatePeriod.String())
}
_, err = c.AddFunc(feed.CronSchedule, func() {
log.Debugf("adding %q to update queue", feed.URL)
if err := updater.Update(ctx, feed); err != nil {
log.WithError(err).Errorf("failed to update feed: %s", feed.URL)
}
case <-ctx.Done():
return ctx.Err()
}
}
})
})
// Run wait goroutines for each feed configuration
for _, feed := range cfg.Feeds {
_feed := feed
group.Go(func() error {
log.Debugf("-> %s (update every %s)", _feed.URL, _feed.UpdatePeriod)
if err != nil {
log.WithError(err).Fatalf("can't create cron task for feed: %s", feed.ID)
}
log.Debugf("-> %s (update '%s')", feed.URL, feed.CronSchedule)
// Perform initial update after CLI restart
updates <- _feed
timer := time.NewTicker(_feed.UpdatePeriod.Duration)
defer timer.Stop()
for {
select {
case <-timer.C:
log.Debugf("adding %q to update queue", _feed.URL)
updates <- _feed
case <-ctx.Done():
return ctx.Err()
}
if err := updater.Update(ctx, feed); err != nil {
log.WithError(err).Errorf("failed to update feed: %s", feed.URL)
}
})
}
}
c.Start()
for {
<-ctx.Done()
return ctx.Err()
}
})
// Run web server
srv := NewServer(cfg)
@ -167,7 +170,7 @@ func main() {
}
})
if err := group.Wait(); err != nil && err != context.Canceled {
if err := group.Wait(); err != nil && (err != context.Canceled && err != http.ErrServerClosed) {
log.WithError(err).Error("wait error")
}

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/jessevdk/go-flags v1.4.0
github.com/mxpv/podcast v0.0.0-20170823220358-fe328ad87d18
github.com/pkg/errors v0.8.1
github.com/robfig/cron/v3 v3.0.1
github.com/silentsokolov/go-vimeo v0.0.0-20190116124215-06829264260c
github.com/sirupsen/logrus v1.2.0
github.com/stretchr/testify v1.3.0

2
go.sum
View File

@ -43,6 +43,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/silentsokolov/go-vimeo v0.0.0-20190116124215-06829264260c h1:KhHx/Ta3c9C1gcSo5UhDeo/D4JnhnxJTrlcOEOFiMfY=
github.com/silentsokolov/go-vimeo v0.0.0-20190116124215-06829264260c/go.mod h1:10FeaKUMy5t3KLsYfy54dFrq0rpwcfyKkKcF7vRGIRY=

View File

@ -25,6 +25,9 @@ type Feed struct {
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
// NOTE: too often update check might drain your API token.
UpdatePeriod Duration `toml:"update_period"`
// Cron expression format is how often to check update
// NOTE: too often update check might drain your API token.
CronSchedule string `toml:"cron_schedule"`
// Quality to use for this feed
Quality model.Quality `toml:"quality"`
// Maximum height of video