Semaphore/services/schedules/pool.go

135 lines
2.4 KiB
Go
Raw Normal View History

2021-09-06 13:05:10 +02:00
package schedules
import (
log "github.com/Sirupsen/logrus"
2021-09-06 13:05:10 +02:00
"github.com/ansible-semaphore/semaphore/db"
2022-01-30 18:43:15 +01:00
"github.com/ansible-semaphore/semaphore/lib"
"github.com/ansible-semaphore/semaphore/services/tasks"
2021-09-06 13:05:10 +02:00
"github.com/robfig/cron/v3"
"sync"
2021-09-06 13:05:10 +02:00
)
type ScheduleRunner struct {
schedule db.Schedule
pool *SchedulePool
2021-09-06 13:05:10 +02:00
}
func (r ScheduleRunner) Run() {
2022-01-31 05:22:08 +01:00
if r.schedule.RepositoryID != nil {
2022-01-30 18:43:15 +01:00
repo, err := r.pool.store.GetRepository(r.schedule.ProjectID, *r.schedule.RepositoryID)
if err != nil {
log.Error(err)
return
}
remoteHash, err := lib.GitRepository{
Logger: nil,
TemplateID: r.schedule.TemplateID,
Repository: repo,
}.GetLastRemoteCommitHash()
if err != nil {
log.Error(err)
return
}
2022-01-31 05:22:08 +01:00
if r.schedule.LastCommitHash != nil && remoteHash == *r.schedule.LastCommitHash {
2022-01-30 18:43:15 +01:00
return
}
err = r.pool.store.SetScheduleCommitHash(r.schedule.ProjectID, r.schedule.ID, remoteHash)
if err != nil {
log.Error(err)
return
}
}
_, err := r.pool.taskPool.AddTask(db.Task{
TemplateID: r.schedule.TemplateID,
ProjectID: r.schedule.ProjectID,
}, nil, r.schedule.ProjectID)
2022-01-30 18:43:15 +01:00
if err != nil {
log.Error(err)
}
2021-09-06 13:05:10 +02:00
}
type SchedulePool struct {
cron *cron.Cron
locker sync.Locker
store db.Store
taskPool *tasks.TaskPool
2021-09-06 13:05:10 +02:00
}
func (p *SchedulePool) init() {
2021-09-06 13:05:10 +02:00
p.cron = cron.New()
p.locker = &sync.Mutex{}
}
2021-09-06 13:05:10 +02:00
func (p *SchedulePool) Refresh() {
defer p.locker.Unlock()
schedules, err := p.store.GetSchedules()
2021-09-06 13:05:10 +02:00
if err != nil {
log.Error(err)
2021-09-06 13:05:10 +02:00
return
}
p.locker.Lock()
p.clear()
2021-09-06 13:05:10 +02:00
for _, schedule := range schedules {
_, err := p.addRunner(ScheduleRunner{
schedule: schedule,
pool: p,
})
2021-09-06 13:05:10 +02:00
if err != nil {
log.Error(err)
2021-09-06 13:05:10 +02:00
}
}
}
func (p *SchedulePool) addRunner(runner ScheduleRunner) (int, error) {
id, err := p.cron.AddJob(runner.schedule.CronFormat, runner)
2021-09-06 13:05:10 +02:00
if err != nil {
return 0, err
2021-09-06 13:05:10 +02:00
}
return int(id), nil
2021-09-06 13:05:10 +02:00
}
func (p *SchedulePool) Run() {
2021-09-06 13:05:10 +02:00
p.cron.Run()
}
func (p *SchedulePool) clear() {
runners := p.cron.Entries()
for _, r := range runners {
p.cron.Remove(r.ID)
}
}
func (p *SchedulePool) Destroy() {
defer p.locker.Unlock()
p.locker.Lock()
p.cron.Stop()
p.clear()
p.cron = nil
}
2021-09-06 13:05:10 +02:00
func CreateSchedulePool(store db.Store, taskPool *tasks.TaskPool) SchedulePool {
pool := SchedulePool{
store: store,
taskPool: taskPool,
}
pool.init()
pool.Refresh()
return pool
2021-09-06 13:05:10 +02:00
}
func ValidateCronFormat(cronFormat string) error {
_, err := cron.ParseStandard(cronFormat)
return err
}