Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(scheduler): allow standard and quartz spec #126

Merged
merged 5 commits into from Feb 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 4 additions & 11 deletions config-example/rules/schedule.yml
@@ -1,26 +1,19 @@
# This rule is in BETA

# meta
name: sched1
active: false

# trigger and args
schedule: '@every 5s'
# example working cron specs:
# - 0 * * * * (at minute 0)
schedule: "@every 5s"
# example cron specs:
# - */1 * * * * (at minute 0)
# - @every 1m
# - @every 10s
# example breaking cron specs:
# - */1 * * * * (at every minute)
# - 59 * * * * * (every minute using Quartz spec format)

# format_output: "On this day (${date}) in the year ${year}: ${event}"
format_output: "Hello, from Scheduler 1!"

output_to_rooms:
- general

output_to_users:
- kelly.shmelly

# help
include_in_help: false
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -18,7 +18,7 @@ require (
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.3.0
github.com/robfig/cron v1.2.0
github.com/robfig/cron/v3 v3.0.0
github.com/rs/xid v1.2.1
github.com/sirupsen/logrus v1.4.2
github.com/spf13/afero v1.2.2 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -151,8 +151,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
Expand Down
2 changes: 1 addition & 1 deletion handlers/http_test.go
Expand Up @@ -17,7 +17,7 @@ func Test_extractFields(t *testing.T) {

JSONTest := make(map[string]interface{})
JSONTest["testing"] = "test"

JSONArrTest := make([]map[string]interface{}, 0)
JSONArrTest = append(JSONArrTest, map[string]interface{}{"testing": "test"})

Expand Down
42 changes: 29 additions & 13 deletions remote/scheduler/remote.go
Expand Up @@ -5,7 +5,7 @@ import (
"strings"
"sync"

"github.com/robfig/cron"
"github.com/robfig/cron/v3"
"github.com/target/flottbot/models"
"github.com/target/flottbot/remote"
)
Expand All @@ -30,10 +30,12 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R
for {
_nil := bot.Rooms[""]
if len(bot.Rooms) > 0 {
bot.Log.Debugf("Scheduler connected to %s channels%s", strings.Title(bot.ChatApplication), _nil)
bot.Log.Debugf("scheduler connected to %s channels: %s", strings.Title(bot.ChatApplication), _nil)
break
}
}

var job *cron.Cron
// Create a list of cron jobs to execute
jobs := []*cron.Cron{}

Expand All @@ -42,26 +44,34 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R
if rule.Active && rule.Schedule != "" {
// Pre-checks before executing rule as a cron job
if len(rule.OutputToRooms) == 0 && len(rule.OutputToUsers) == 0 {
bot.Log.Debug("Scheduling rules requires the 'output_to_rooms' and/or 'output_to_users' fields to be set")
bot.Log.Debug("scheduling rules require the 'output_to_rooms' and/or 'output_to_users' fields to be set")
continue
} else if len(rule.OutputToRooms) > 0 && len(bot.Rooms) == 0 {
bot.Log.Debugf("Could not connect Scheduler to rooms: %s", rule.OutputToRooms)
bot.Log.Debugf("unable to connect scheduler to these rooms: %s", rule.OutputToRooms)
continue
} else if rule.Respond != "" || rule.Hear != "" {
bot.Log.Debug("Scheduling rules does not allow the 'respond' and 'hear' fields")
bot.Log.Debug("scheduling rules does not allow the 'respond' and 'hear' fields")
continue
}

// TODO - Regex check for correct cron syntax
bot.Log.Debugf("scheduler is adding rule '%s'", rule.Name)

// check whether we are dealing with quartz spec
specFields := strings.Fields(rule.Schedule)
if len(specFields) == 6 {
job = cron.New(cron.WithSeconds())
} else {
job = cron.New()
}

bot.Log.Debugf("Scheduler is running rule '%s'", rule.Name)
cron := cron.New()
scheduleName := rule.Name
input := fmt.Sprintf("<@%s> ", bot.ID) // send message as self
outputRooms := rule.OutputToRooms
outputUsers := rule.OutputToUsers
cron.AddFunc(rule.Schedule, func() {
// Build message

_, err := job.AddFunc(rule.Schedule, func() {
bot.Log.Debugf("executing scheduler for rule '%s'", scheduleName)
// build the message
message := models.NewMessage()
message.Service = models.MsgServiceScheduler
message.Input = input // send message as self
Expand All @@ -71,12 +81,18 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R
message.OutputToUsers = outputUsers
inputMsgs <- message
})
jobs = append(jobs, cron)

if err != nil {
bot.Log.Errorf("unable to add schedule: %v", err)
continue
}

jobs = append(jobs, job)
}
}

if len(jobs) == 0 {
bot.Log.Warn("Found no schedule-type rules. Scheduler is closing")
bot.Log.Warn("no schedules were added - please check for errors")
return
}

Expand Down Expand Up @@ -105,5 +121,5 @@ func processJobs(jobs []*cron.Cron, bot *models.Bot) {
defer job.Stop()
}
wg.Wait()
bot.Log.Warn("Scheduler is closing")
bot.Log.Warn("scheduler is closing")
}