forked from gospackler/metre
/
metre.go
119 lines (102 loc) · 2.93 KB
/
metre.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Package metre is used to schedule end execute cron jobs in a simplified fashion
package metre
import (
"strings"
"errors"
"github.com/robfig/cron"
log "github.com/Sirupsen/logrus"
)
const LOCALHOST string = "127.0.0.1" // Default host for cache and queue
const QUEUEPORT string = "5555" // Default port for queue
const CACHEPORT string = "6379" // Default port for cache
type Metre struct {
Cron cron.Cron
Queue Queue
Cache Cache
Scheduler Scheduler
TaskMap map[string]Task
// Add func(t Task)
}
// New creates a new scheduler to manage task scheduling and states
func New(queueUri string, cacheUri string) (Metre, error) {
if cacheUri == "" {
cacheUri = LOCALHOST + ":" + CACHEPORT
} else if strings.Index(cacheUri, ":") == 0 {
cacheUri = LOCALHOST + ":" + cacheUri
}
if queueUri == "" {
queueUri = LOCALHOST + ":" + QUEUEPORT
} else if strings.Index(queueUri, ":") == 0 {
queueUri = LOCALHOST + ":" + queueUri
}
cron := *cron.New()
c, cErr := NewCache(cacheUri)
if cErr != nil {
return Metre{}, cErr
}
q, qErr := NewQueue(queueUri)
if qErr != nil {
return Metre{}, qErr
}
s := NewScheduler(q, c)
m := make(map[string]Task)
return Metre{cron, q, c, s, m}, nil
}
// Add adds a cron job task to schedule and process
func (m *Metre) Add(t Task) {
if _, exists := m.TaskMap[t.ID]; exists {
panic("attempted to add two tasks with the same ID [" + t.ID + "]")
}
m.TaskMap[t.ID] = t
m.Cron.AddFunc(t.Interval, func () {
t.Schedule(NewTaskRecord(t.ID), m.Scheduler, m.Cache, m.Queue)
})
}
// Schedule schedules a singular cron task
func (m *Metre) Schedule(ID string) (string, error) {
e := m.Queue.BindPush()
if e != nil{
return "", nil
}
t, ok := m.TaskMap[ID]
if ok == false {
return "", errors.New("task [" + ID + "] not recognized")
}
tr := NewTaskRecord(t.ID)
t.Schedule(tr, m.Scheduler, m.Cache, m.Queue)
return buildTaskKey(tr), nil
}
// Scheduler processes a singular cron task
func (m *Metre) Process(ID string) (string, error) {
t, ok := m.TaskMap[ID]
if ok == false {
return "", errors.New("task [" + ID + "] not recognized")
}
tr := NewTaskRecord(t.ID)
t.Process(tr, m.Scheduler, m.Cache, m.Queue)
return buildTaskKey(tr), nil
}
func (m *Metre) StartMaster() {
e := m.Queue.BindPush()
if e != nil {
panic(e)
}
m.Cron.Start()
}
func (m *Metre) StartSlave() {
e := m.Queue.ConnectPull()
if e != nil {
panic(e)
}
for {
msg := m.Queue.Pop()
tr, _ := ParseTask(msg)
if tr.ID == "" || tr.UID == "" {
log.Warn("Failed to parse task from message: " + msg)
continue
}
m.Cache.Delete(buildTaskKey(tr))
tsk := m.TaskMap[tr.ID]
go tsk.Process(tr, m.Scheduler, m.Cache, m.Queue)
}
}