mirror of
https://github.com/hibiken/asynq.git
synced 2026-04-26 15:35:55 +03:00
[GH-ISSUE #308] [FEATURE REQUEST] Scheduler reboot cannot reschedule old tasks #1142
Labels
No labels
CLI
bug
designing
documentation
duplicate
enhancement
good first issue
good first issue
help wanted
idea
invalid
investigate
needs-more-info
performance
pr-welcome
pull-request
question
wontfix
work in progress
work in progress
work-around-available
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/asynq#1142
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @bibilins on GitHub (Aug 5, 2021).
Original GitHub issue: https://github.com/hibiken/asynq/issues/308
Originally assigned to: @hibiken on GitHub.
I want to know, if the server/scheduler roboot, will the tasks that were previously enqueued but not executed be rescheduled?
@bibilins commented on GitHub (Aug 5, 2021):
I had tested, enqueued a task into scheduler, then reboot the scheduler, but it seems that scheduler was not scheduled the previous task
@JeremyCraven commented on GitHub (Aug 5, 2021):
I am also curious about persistence of registered tasks with the scheduler.
My use case is scheduling a task to run on a schedule for each user only after the user performs a specific action for the first time. Currently as far as I'm aware, the only way to support this use case is determining all the users eligible for registering tasks and registering them with the scheduler before starting the scheduler. Would appreciate any guidance.
@crossworth commented on GitHub (Aug 5, 2021):
Hello guys, I will try to explain how the scheduler works, but I may be wrong on some aspects, so maybe we should wait to see what @hibiken says.
Lets think about
asynqas two parts:While the worker you can have only way to handle the task (registering a handler for it), the client you have two ways to enqueue a task.
You can manually call
client.Enqueueor you can use the scheduler, when you use the scheduler, the task will not be put on the queue right away, it will be scheduled to run at the cronspec provided, than it will be put on the queue. So in theory you can have strange behaviour, like using the scheduler with a task withasynq.ProcessIn(24*time.Hour), that means that when the scheduled run it will enqueue a task to be process in 24 hours.More in depth answer:
We use
github.com/robfig/cronto handle the cron part, when we register a task usingRegister(cronspec string, task *Task, opts ...Option) (entryID string, err error), we create a new enqueueJob, that has aRunmethod to be called byrobfig/cronaccording to the cronspec definition. TheenqueueJob.Runmethod enqueues the task on the "normal" task handling workflow.So if you register a cron task to be executed in 2 hours from now, starts the process and than stop the process in a few minutes, no task should be present on the task queue, since the process that enqueues the task has not been executed.
I hope that this explanation make sense.
I dont think you need to register the task before starting the scheduler, the
Registermethod internally callsAddJoband the documentation says that you can add jobs after the scheduler has been started, but there is a map write without a lock, so it may panic withconcurrent write panic. Make sure you have the task handler registered, since you cannot dynamic register task handlers.On your use case, on scheduler startup you could loop all the users checking if they are allowed to perform the action and if so register the task, during runtime (new user register and the scheduler is already running) you could dynamic call register, I think this should work.
@hibiken commented on GitHub (Aug 6, 2021):
Thank you @bibilins for opening this issue!
@crossworth's explanation is correct. Current implementation is quite basic and it simply store all registered tasks and their cronspec in the process's memory (i.e doesn't persist it anyware), so it doesn't survive process restart.
What we want is a fault tolerant distributed cron system, I'll do some research and try to come up with a design and implementation.
Also, @JeremyCraven's use case is quite interesting. Maybe we should support dynamic registering of tasks after scheduler is launched. As @crossworth mentioned, we have to make sure to use mutex to guard that
idmap. Feel free to open a PR if anyone's interested in contributing.Thank you everyone for the feedback. This is a great opportunity to look into a more robust implementation of scheduler!
@JeremyCraven commented on GitHub (Aug 9, 2021):
Thanks @hibiken! We can work around registered tasks not surviving process restart.
I'll plan on following along and if the opportunity presents itself also help where possible. Thanks again!
@JeremyCraven commented on GitHub (Aug 16, 2021):
Hey @hibiken. Following up, it turned out that dynamic registering of tasks ended up being a blocker for us. I took a look at the scheduler code and it wasn't obvious how to implement that. If you have any suggestions, I could take an attempt at it, but either way just following up to express interest in this feature.
@hibiken commented on GitHub (Aug 16, 2021):
@JeremyCraven thank you for the update! I can revisit this and make the change within the next few days!
@hibiken commented on GitHub (Aug 18, 2021):
@JeremyCraven Please update the package to v0.18.4. I made a change so that you can call
Scheduler.Register(and alsoUnregister) concurrently. Let me know if you encounter any issues!@JeremyCraven commented on GitHub (Aug 19, 2021):
@hibiken Thank you so much! So far looks like we are unblocked.
@gf3 commented on GitHub (Oct 8, 2021):
@hibiken @crossworth i also have a use-case for a persisted/distributed schedule:
our platform allows shop owners to have multiple locations where goods are sold, each location has its own fulfillment time and rules. every order on our platform is associated with a location and has a fulfillment date in the future. therefore each location requires a daily job at a specific time to mark current orders as paid and then move tomorrow's orders into the "ready" state. of course we would like this schedule to persist across deploys and failures and we'd like to ensure the schedule works in a multi-node system, too.
@hibiken commented on GitHub (Jan 22, 2022):
Check out
PeriodicTaskManagertype, which was added in v0.21.You can store your periodic task configuration in a durable storage (e.g. file, database, etc) and write an implementation of
PeriodicTaskConfigProviderwhich exports that configuration. This also supports dynamically adding/removing periodic tasks.See this wiki page for an example.
This is a new feature, so any feedback is appreciated!