如果作业花费的时间超过预定时间间隔,如何防止 GoCron 中堆积的作业执行?

问题描述 投票:0回答:1

我在 Go 项目中使用 github.com/go-co-op/gocron 包来安排任务。该作业设置为每 2 分钟运行一次,但在某些情况下,该任务可能需要比该时间间隔更长的时间(例如,该作业需要 7 分钟才能完成)。长时间运行的作业完成后,会连续触发多个作业实例,从而导致重叠执行。

func newScheduler(loc *time.Location) {
    e := gocron.NewScheduler(loc)
    e.SingletonModeAll()

    e.Every("2m").Do(func() {
        Logger.Warn("Task Started at: " + time.Now().Format("2006-01-02 15:04:05"))
        err := tasks.MyTask()
        if err != nil {
            Logger.Error("Error occurred during task execution: ", err)
        }
        Logger.Warn("Task Completed at: " + time.Now().Format("2006-01-02 15:04:05"))
    })

    e.StartAsync()
    select {}
}

问题: 当作业花费的时间超过计划的时间间隔(例如,7 分钟而不是 2 分钟)时,在长时间运行的作业完成后,作业的多个实例将连续执行。这会导致性能问题和重叠的作业。

问题: 有没有一种方法可以确保作业执行后只有一个作业实例运行,后续作业等到前一个实例完成后才开始,并且应该根据下一个时间间隔只运行一次?

我尝试过的: 我启用了 SingletonModeAll(),但是当由于长时间运行的任务而错过间隔时,它不会阻止执行背靠背作业。

期望的结果: 我想确保在执行作业后,它应该忽略堆积的作业,并且不应该背靠背运行,即使作业花费的时间比计划的时间间隔长。

任何关于如何在 GoCron 中处理此问题或替代方法的指导将不胜感激!

go cron scheduled-tasks scheduler
1个回答
0
投票

您正在使用旧的 v1 API,上面写着

如果特定作业的先前实例尚未完成其运行,SingletonModeAll 会阻止新作业启动

警告:如果您的工作量将继续堆积,超出工人的极限能力,请勿使用此模式。

你要使用的是`SetMaxConcurrentJobs:

限制可以同时运行的作业数量。

RescheduleMode

默认情况下,如果有最大限制 设置并发作业并达到限制,作业将 跳过它的运行并在计划中的下一个事件中重试

所以

    e.SetMaxConcurrentJobs(1, gocron. RescheduleMode)

请注意,我建议切换到

github.com/go-co-op/gocron/v2
,其中有
WithLimitConcurrentJobs

    e, err := gocron.NewScheduler(gocron.WithLimitConcurrentJobs(1, gocron.LimitModeReschedule))
© www.soinside.com 2019 - 2024. All rights reserved.