Reputation: 31
I wanted to write this functionality in server side code. Is there effective way to write a functionality that runs in background for certain time duration and when time duration expires it triggers the event. After that it restart the timer to trigger the event for the next time, again and again.
I wanted to do this asynchronously, like Timer starts that runs in the background and when it expired call the function to execute. after the function finishes it's execution it again trigger a event/ function asynchronously that restart the timer without waiting anywhere in the code.
Time duration will be calculated dynamically every time.
I have tried using below approach but it waiting for Channels and I have to run for loop that also block the code.
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"time"
)
const INTERVAL_PERIOD time.Duration = 24 * time.Hour
var HOUR_TO_TICK int
var MINUTE_TO_TICK int
var SECOND_TO_TICK int
type jobTicker struct {
t *time.Timer
}
func setConfig(appconfs map[string]string) bool {
timeOfEventTrigger := appconfs["Task_Trigger_Time"]
clockTime := strings.Split(timeOfEventTrigger, ":")
fmt.Println("fixed clock time to trigger event ", clockTime)
HOUR_TO_TICK, _ = strconv.Atoi(clockTime[0])
MINUTE_TO_TICK, _ = strconv.Atoi(clockTime[1])
SECOND_TO_TICK, _ = strconv.Atoi(clockTime[2])
return true
}
func readConfigFromJson(configPath string) bool {
fmt.Printf("Loading Configurations from %s\n", configPath)
configMap := map[string]string{}
configfile, err := os.Open(configPath)
if err != nil {
fmt.Printf("Unable to the load the config: %v\n", err)
return false
}
byteValue, err := ioutil.ReadAll(configfile)
if err != nil {
fmt.Printf("Unable to decode the config: %v\n", err)
return false
}
err = json.Unmarshal(byteValue, &configMap)
if err != nil {
fmt.Printf("Unable to Unmarshal to JSON: %v\n", err)
return false
}
defer configfile.Close()
return setConfig(configMap)
}
func getNextTickDuration() time.Duration {
now := time.Now()
nextTick := time.Date(now.Year(), now.Month(), now.Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
if nextTick.Before(now) {
nextTick = nextTick.Add(INTERVAL_PERIOD)
}
fmt.Println("Current time is -> ", now)
fmt.Println(" next trigger at this date and time - ", nextTick)
waitDuration := nextTick.Sub(time.Now())
fmt.Println(" clock is waiting for duration -> ", waitDuration)
return waitDuration
}
func NewJobTicker() jobTicker {
fmt.Println("genrate new job ticker here")
return jobTicker{time.NewTimer(getNextTickDuration())}
}
func (jt jobTicker) updateJobTicker() {
fmt.Println("update job ticker here")
jt.t.Reset(getNextTickDuration())
}
func startTmer () {
jt := NewJobTicker()
for {
<-jt.t.C
fmt.Println(time.Now(), "- just ticked")
// do our logic
jt.updateJobTicker()
}
}
here is the json file that is being read for the time to execute event.
// config.json
{
"Task_Trigger_Time": "12:30:00"
}
Upvotes: 1
Views: 91
Reputation: 821
have added a few changes to original code. This takes care of panic, incase it happens while reading the duration, and uses time.Sleep
instead of time.AfterFunc
.
//start the timer again
func performOutdatedOperationForStore() {
// do somthing
// start the timer again
timeDurationToWait,err := getNextTickDuration()
if err!=nil{
//log error
}
go StartTimeDuration(timeDurationToWait)
}
func StartTimeDuration(timeDurationToWait string) {
// start timer
time.Sleep(timeDurationToWait)
performOutdatedOperationForStore()
//time.AfterFunc(timeDurationToWait, func() { performOutdatedOperationForStore() }): this calls performOutdatedOperationForStore() in a new go routine, which is also ok, but not nesseccary.
}
Upvotes: 1
Reputation: 31
Hi I have done it this way. Please suggest a better way if Possible in brief. I am a complete newbie it will help me a lot...
//start the timer again
func performOutdatedOperationForStore() {
// do somthing
// start the timer again
go StartTimeDuration()
}
func StartTimeDuration() {
// start timer
timeDurationToWait := getNextTickDuration()
// gvalidObjectTime := config.ConfigurationObject.ObjectLifeTimeTTL
time.AfterFunc(timeDurationToWait, func() { performOutdatedOperationForStore() })
}
Upvotes: -1