gocraft / work

Process background jobs in Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

If I stop the worker and start it later the periodic job runs hundreds of times

ciokan opened this issue · comments

I have a periodic job that runs every second. If I stop the worker for 5 minutes (usually during development) and then start it again, the job will run 300 times in a row before re-entering it's cycle of 1 per second.

	beego.Debug("Starting worker")
	pool := work.NewWorkerPool(Context{}, 1, "typely", redisPool)
	
	// Add middleware that will be executed for each job
	pool.Middleware((*Context).Log)
	
	pool.PeriodicallyEnqueue("*/1 * * * * *", "create_invoices")
	pool.Job("create_invoices", (*Context).CreateInvoices)
	
	// Start processing jobs
	pool.Start()
	
	// Wait for a signal to quit:
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, os.Kill)
	<-signalChan
	
	// Stop the pool
	pool.Stop()
}

func (c *Context) Log(job *work.Job, next work.NextMiddlewareFunc) error {
	beego.Debug("Starting job: ", job.Name)
	return next()
}

func (c *Context) CreateInvoices(job *work.Job) error {
	return CreateInvoices()
}```

During downtime, if I change the cron to run every hour, when I restart it, it still makes up for the lost seconds running 300 times and only then it enters the new cycle of 1/h.

Is this desired behavior?

Hi, I found this "issue", too.

After investigation, I think the root cause is, the "periodicEnqueuer" enqueues jobs to queue "[name_space]:scheduled" ahead of time, so when you start a worker pool after 5 minutes, the "schedulerRequeuer" will push these "outdated" jobs to queue "[name_space]:jobs:[job_name]", then the jobs are processed by workers.

At first, I tried to solve this problem by comparing "now()" with the "scheduled time" by myself, but I failed, because I can not get the "scheduled time", the "Job.enqueuedAt" is the time of the job put into queue "[name_space]:jobs:[job_name]", which is now(), and the time is changed in "redis.go@line 235". Besides, I don't think it is elegant to do such compare.

Then I remember how this problem was solved in K8S:
https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#starting-deadline-seconds
Now I'm trying to add similar feature.

I'll create a PR when I finish, along with other 2 PRs -- #67 and #68 , I think they are bugs.

Hi, I created a PR:
#78