How to write a functionality on web based service that runs when the time duration will expire and restart the timer again in golang

huangapple go评论90阅读模式
英文:

How to write a functionality on web based service that runs when the time duration will expire and restart the timer again in golang

问题

我想将这个功能写在服务器端的代码中。有没有一种有效的方法来编写一个在后台运行一段时间并在时间到期时触发事件的功能?之后,它会重新启动计时器以触发下一次事件,一次又一次。

我想以异步的方式实现这个功能,就像启动一个在后台运行的计时器,当它到期时调用函数执行。函数执行完毕后,它会异步地触发一个事件/函数,重新启动计时器,而不需要在代码中等待任何地方。

时间持续时间将根据每次动态计算。

我尝试使用下面的方法,但它在等待通道,并且我必须运行一个阻塞代码的循环。

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()
	}
}

这是被读取用于执行事件的时间的 JSON 文件。

// config.json
{
    "Task_Trigger_Time": "12:30:00"
}
英文:

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 (
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;io/ioutil&quot;
&quot;os&quot;
&quot;strconv&quot;
&quot;strings&quot;
&quot;time&quot;
)
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[&quot;Task_Trigger_Time&quot;]
clockTime := strings.Split(timeOfEventTrigger, &quot;:&quot;)
fmt.Println(&quot;fixed clock time to trigger event  &quot;, 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(&quot;Loading Configurations from %s\n&quot;, configPath)
configMap := map[string]string{}
configfile, err := os.Open(configPath)
if err != nil {
fmt.Printf(&quot;Unable to the load the config: %v\n&quot;, err)
return false
}
byteValue, err := ioutil.ReadAll(configfile)
if err != nil {
fmt.Printf(&quot;Unable to decode the config: %v\n&quot;, err)
return false
}
err = json.Unmarshal(byteValue, &amp;configMap)
if err != nil {
fmt.Printf(&quot;Unable to Unmarshal to JSON: %v\n&quot;, 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(&quot;Current time is -&gt; &quot;, now)
fmt.Println(&quot; next trigger at this date and time - &quot;, nextTick)
waitDuration := nextTick.Sub(time.Now())
fmt.Println(&quot; clock is waiting for duration -&gt; &quot;, waitDuration)
return waitDuration
}
func NewJobTicker() jobTicker {
fmt.Println(&quot;genrate new job ticker here&quot;)
return jobTicker{time.NewTimer(getNextTickDuration())}
}
func (jt jobTicker) updateJobTicker() {
fmt.Println(&quot;update job ticker here&quot;)
jt.t.Reset(getNextTickDuration())
}
func startTmer () {
jt := NewJobTicker()
for {
&lt;-jt.t.C
fmt.Println(time.Now(), &quot;- just ticked&quot;)
// do our logic 
jt.updateJobTicker()
}
}

here is the json file that is being read for the time to execute event.

// config.json
{
&quot;Task_Trigger_Time&quot;: &quot;12:30:00&quot;
}

答案1

得分: 1

我对原始代码进行了一些更改。这样可以处理在读取持续时间时发生的恐慌,并且使用time.Sleep而不是time.AfterFunc

//重新启动计时器
func performOutdatedOperationForStore() {

//做一些事情

//重新启动计时器
timeDurationToWait,err := getNextTickDuration()
if err!=nil{
//记录错误
}

go StartTimeDuration(timeDurationToWait)

}

func StartTimeDuration(timeDurationToWait string) {

//启动计时器
time.Sleep(timeDurationToWait)
performOutdatedOperationForStore()
//time.AfterFunc(timeDurationToWait, func() { performOutdatedOperationForStore() }): 这会在新的go例程中调用performOutdatedOperationForStore(),这也可以,但不是必要的。
英文:

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.
}

答案2

得分: -1

你好,我已经这样做了。如果可能的话,请简要提供更好的方法。我是一个完全的新手,这将对我有很大帮助...

//重新启动计时器
func performOutdatedOperationForStore() {
//做一些事情
//重新启动计时器
go StartTimeDuration()
}
func StartTimeDuration() {
//启动计时器
timeDurationToWait := getNextTickDuration()
// gvalidObjectTime := config.ConfigurationObject.ObjectLifeTimeTTL
time.AfterFunc(timeDurationToWait, func() { performOutdatedOperationForStore() })
}
英文:

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() })
}

huangapple
  • 本文由 发表于 2022年9月1日 09:31:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/73563452.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定