blob: 973865e43531f6a6b5a56cd8ad0526f587583aee [file] [log] [blame]
Stephane Barbarie35595062018-02-08 08:34:39 -05001package common
2
3import (
4 "github.com/sirupsen/logrus"
5 "sync"
6 "time"
7)
8
9/*
10 IntervalHandler is used to run a routine at regular intervals and provide all the necessary
11 utilities to manage the execution.
12*/
13
14type IntervalHandler struct {
15 // Interval period in between each execution (in seconds?)
16 Interval int
17 // function to execute after each interval
18 function func()
19 // Channel listening to execution events
20 execute chan _ExecutionState
21 // Channel listening for a termination event
22 terminate chan struct{}
23 // Current execution state of the handler
24 state _ExecutionState
25 wg sync.WaitGroup
26}
27
28// Define execution state constants
29type _ExecutionState uint8
30
31const (
32 STARTED _ExecutionState = iota
33 STOPPED
34 PAUSED
35 RESUMED
36)
37
38// Execute state string equivalents
39var _ExecutionStateEnum = []string{
40 "STARTED",
41 "STOPPED",
42 "PAUSED",
43 "RESUMED",
44}
45
46func (s _ExecutionState) String() string {
47 return _ExecutionStateEnum[s]
48}
49
50/*
51NewIntervalHandler instantiates a new interval based function execution handler
52*/
53func NewIntervalHandler(interval int, function func()) *IntervalHandler {
54 handler := &IntervalHandler{
55 Interval: interval,
56 function: function,
57 }
58
59 handler.execute = make(chan _ExecutionState)
60 handler.terminate = make(chan struct{})
61 handler.state = STOPPED
62
63 return handler
64}
65
66/*
67_Execute is a routine running concurrently and listening to execution events
68*/
69func (h *IntervalHandler) _Execute() {
70 defer h.wg.Done()
71 for {
72 select {
73 case h.state = <-h.execute:
74 Logger().WithFields(logrus.Fields{
75 "handler": h,
76 }).Debug("Processing execution state")
77 switch h.state {
78 case STARTED:
79 case PAUSED:
80 case RESUMED:
81 h.state = STARTED
82 case STOPPED:
83 fallthrough
84 default:
85 h.terminate <- struct{}{}
86 }
87
88 case <-h.terminate:
89 return
90
91 default:
92 if h.state == STARTED {
93 h.function()
94 time.Sleep(time.Duration(h.Interval) * time.Second)
95 } else {
96 // TODO: replace hardcoded delay with a configurable parameter
97 time.Sleep(1 * time.Second)
98 }
99 }
100 }
101}
102
103/*
104Start initiates the interval based function execution
105*/
106func (h *IntervalHandler) Start() {
107 Logger().WithFields(logrus.Fields{
108 "handler": h,
109 }).Info("Starting interval handler")
110
111 if h.execute == nil {
112 return
113 }
114 if h.state == STOPPED {
115 go h._Execute()
116 h.execute <- STARTED
117 }
118}
119
120/*
121Pause interrupts the interval based function execution
122*/
123func (h *IntervalHandler) Pause() {
124 Logger().WithFields(logrus.Fields{
125 "handler": h,
126 }).Info("Pausing interval handler")
127
128 if h.execute == nil || h.state == STOPPED {
129 return
130 }
131 if h.state == STARTED {
132 h.execute <- PAUSED
133 }
134}
135
136/*
137Resume continues the interval based function execution
138*/
139func (h *IntervalHandler) Resume() {
140 Logger().WithFields(logrus.Fields{
141 "handler": h,
142 }).Info("Resuming interval handler")
143
144 if h.execute == nil || h.state == STOPPED {
145 return
146 }
147 if h.state == PAUSED {
148 h.execute <- RESUMED
149 }
150}
151
152/*
153Stop terminates the interval based function execution
154*/
155func (h *IntervalHandler) Stop() {
156 Logger().WithFields(logrus.Fields{
157 "handler": h,
158 }).Info("Stopping interval handler")
159
160 if h.execute == nil || h.state == STOPPED {
161 return
162 }
163 h.execute <- STOPPED
164}