How to implement a timer task queue with Golang

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Golang in Timer

The Golang provides 2 timer timers and ticker (which should be known if JS is familiar), namely one-time timers and repetitive task timers.

General usage:

func main() {     input := make(chan interface{})     //producer - produce the messages    go func() {        for i := 0; i < 5; i++ {            input <- i        }        input <- "hello, world"    }()     t1 := time.NewTimer(time.Second * 5)    t2 := time.NewTimer(time.Second * 10)     for {        select {        //consumer - consume the messages        case msg := <-input:            fmt.Println(msg)         case <-t1.C:            println("5s timer")            t1.Reset(time.Second * 5)         case <-t2.C:            println("10s timer")            t2.Reset(time.Second * 10)        }    }}

SOURCE Watch

This c is what, we go to the source to see, take the timer as an example:

type Timer struct {C <-chan Timer runtimeTimer}

The original is a channel, actually have to go basic know, go operator when appear, or <-, must have one end refers to channel. In the example above, it is blocking in a for loop, waiting for the C of the timer to come out of the channel, when the value is obtained, the desired operation.

Design our scheduled Task queue

My needs

At that time, I needed to receive a request from the client and generate a timed task that would be executed at a fixed time, either once or several times, or it might be stopped automatically at the specified time, and I would be able to stop when the task was terminated.

Specifically I drew a flowchart, almost as follows, drawing level is limited, please forgive me.

Defining structures

type OnceCron struct {tasks  []*Task          //任务的列队add    chan *Task       //当遭遇到新任务的时候remove chan string       //当遭遇到删除任务的时候stop   chan struct{}      //当遇到停止信号的时候Logger *log.Logger      //日志  }type Job interface {Run()                  //执行接口}type Task struct {        Job     Job            //要执行的任务 Uuid    string           //任务标识,删除时用RunTime int64           //执行时间Spacing int64           //间隔时间EndTime int64           //结束时间Number  int             //总共要次数}

Queue implementation

First, we're going to get a queue task

Func Newcron () *oncecron general operation, in order to save space, I do not write out, specifically can see the source, posted on the bottom.

Then, the start of the timer queue run, in general, will be named start. Then there is a problem, when we first started the program, this time there is no task queue, it is not for{select{}} Waiting for a fluffy ball? So, we need to add a default task at start, and I did that by adding a repeating queue that executes once an hour to prevent the queue from exiting.

func (one *OnceCron) Start() {//初始化的時候加入一個一年的長定時器,間隔1小時執行一次task := getTaskWithFuncSpacing(3600,  time.Now().Add(time.Hour*24*365).Unix() , func() {log.Println("It's a Hour timer!")}) //为了代码格式markdown 里面有个括号我改成全角了one.tasks = append(one.tasks, task)go one.run()  //协成执行 防止主进程被阻塞}

The executive section should be focused, and my understanding is that it is divided into three parts:

    1. First, get a task that performs first
    2. Then a timer is generated to perform the task
    3. Make blocking judgments, get the action we want to take
func (one *OnceCron) run() {for {                //第一步 获取任务now := time.Now()   //获取到当前时间task, key := one.GetTask() //获取最近的一个任务的执行时间i64 := task.RunTime - now.Unix() //任务执行和当前时间的差var d time.Durationif i64 < 0 {   //如果任务时间已过期,将执行时间改成现在并且利马执行one.tasks[key].RunTime = now.Unix()  one.doAndReset(key)                        continue} else {  //否则,获取距离执行开始的间隔时间d = time.Unix(task.RunTime, 0).Sub(now)}                //第二步 产生定时器timer := time.NewTimer(d)  //第三步 捕获定时器或者其他事件for {select {                        //当定时器到了执行时间时,执行当前任务并关闭定时器case <-timer.C:one.doAndReset(key)if task != nil {go task.Job.Run()timer.Stop()}//当外部添加了任务时,关闭当前定时器case <-one.add:timer.Stop()//当外部要删除一个任务时,删除ID为uuidstr的任务case uuidstr := <-one.remove:one.removeTask(uuidstr)timer.Stop()//当遇到要关闭整个定时器任务时case <-one.stop:timer.Stop()return}break}}}

Postscript

This article is purely an article of the note Analysis class, designed to analyze how I encountered a need to generate the code that we needed by analyzing the process.

Source Address:

Timing a task queue

Application Address:

A forwarding middleware applied to Google message push

Reference Source:

Golang implementation of Crontab functions

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.