Easy and fluent Go cron scheduling

Overview

goCron: A Golang Job Scheduling Package.

CI State Go Report Card Go Doc

goCron is a Golang job scheduling package which lets you run Go functions periodically at pre-determined interval using a simple, human-friendly syntax.

goCron is a Golang implementation of Ruby module clockwork and Python job scheduling package schedule.

See also these two great articles:

If you want to chat, you can find us at Slack!

Examples:

package main

import (
	"fmt"
	"time"

	"github.com/go-co-op/gocron"
)

func task() {
    fmt.Println("I am running task.")
}

func taskWithParams(a int, b string) {
    fmt.Println(a, b)
}

func main() {
    // defines a new scheduler that schedules and runs jobs
    s1 := gocron.NewScheduler(time.UTC)

    s1.Every(3).Seconds().Do(task)

    // scheduler starts running jobs and current thread continues to execute
    s1.StartAsync()

    // Do jobs without params
    s2 := gocron.NewScheduler(time.UTC)
    s2.Every(1).Second().Do(task)
    s2.Every(2).Seconds().Do(task)
    s2.Every(1).Minute().Do(task)
    s2.Every(2).Minutes().Do(task)
    s2.Every(1).Hour().Do(task)
    s2.Every(2).Hours().Do(task)
    s2.Every(1).Day().Do(task)
    s2.Every(2).Days().Do(task)
    s2.Every(1).Week().Do(task)
    s2.Every(2).Weeks().Do(task)
    s2.Every(1).Month(time.Now().Day()).Do(task)
    s2.Every(2).Months(15).Do(task)

    // check for errors
    _, err := s2.Every(1).Day().At("bad-time").Do(task)
    if err != nil {
        log.Fatalf("error creating job: %v", err)
    }

    // Do jobs with params
    s2.Every(1).Second().Do(taskWithParams, 1, "hello")

    // Do Jobs with tags
    // initialize tag
    tag1 := []string{"tag1"}
    tag2 := []string{"tag2"}

    s2.Every(1).Week().SetTag(tag1).Do(task)
    s2.Every(1).Week().SetTag(tag2).Do(task)

    // Removing Job Based on Tag
    s2.RemoveJobByTag("tag1")
    
    // Remove a Job after its last execution
    j, _ := s2.Every(1).StartAt(time.Now().Add(30*time.Second)).Do(task)
    j.LimitRunsTo(1)
    j.RemoveAfterLastRun()

    // Do jobs on specific weekday
    s2.Every(1).Monday().Do(task)
    s2.Every(1).Thursday().Do(task)

    // Do a job at a specific time - 'hour:min:sec' - seconds optional
    s2.Every(1).Day().At("10:30").Do(task)
    s2.Every(1).Monday().At("18:30").Do(task)
    s2.Every(1).Tuesday().At("18:30:59").Do(task)
    s2.Every(1).Wednesday().At("1:01").Do(task)

    // Begin job at a specific date/time. 
    t := time.Date(2019, time.November, 10, 15, 0, 0, 0, time.UTC)
    s2.Every(1).Hour().StartAt(t).Do(task)

    // Delay start of job
    s2.Every(1).Hour().StartAt(time.Now().Add(time.Duration(1 * time.Hour)).Do(task)

    // NextRun gets the next running time
    _, time := s2.NextRun()
    fmt.Println(time)

    // Remove a specific job
    s2.Remove(task)

    // Clear all scheduled jobs
    s2.Clear()

    // stop our first scheduler (it still exists but doesn't run anymore)
    s1.Stop() 

    // executes the scheduler and blocks current thread
    s2.StartBlocking()

    // this line is never reached
}

FAQ

  • Q: I'm running multiple pods on a distributed environment. How can I make a job not run once per pod causing duplication?
  • A: We recommend using your own lock solution within the jobs themselves (you could use Redis, for example)

Looking to contribute? Try to follow these guidelines:

  • Use issues for everything
  • For a small change, just send a PR!
  • For bigger changes, please open an issue for discussion before sending a PR.
  • PRs should have: tests, documentation and examples (if it makes sense)
  • You can also contribute by:
    • Reporting issues
    • Suggesting new features or enhancements
    • Improving/fixing documentation

Jetbrains supports this project with GoLand licenses. We appreciate their support for free and open source software!

Issues
  • [BUG] - schedule job at specific time

    [BUG] - schedule job at specific time

    Describe the bug

    I start a scheduler in my local timezone. Then I read the scheduled jobs from a struct in settings. I receive the start time as a json timestamp, which is converted to a Golang Time. In the printed output, it seems like this conversion works the way it should.

    Also when I ask when the next scheduled job is going to run, I see the correct time.

    Alas, when the time comes to run the job, nothing happens.

    If I add a recurring job to the queue, say every 2 seconds, I do see the function getting executed with the parameters that were passed.

    I also see the tag, I added to the job.

    Any idea what I might be doing wrong?

    Jo

    To Reproduce

    Steps to reproduce the behavior: `

    func main() { location, _ := time.LoadLocation("Europe/Brussels") scheduler := gocron.NewScheduler(location)

    for _, task := range settings.Schedule {
    	PrettyPrint(task)
    	now := nowFormatted()
    	if task.StartDate > now {
    		var DateRE = regexp.MustCompile(`/Date\((?P<UnixTimestamp>\d+)(?P<TZOffset>[-\+]\d+)\)`)
    		tsString := DateRE.FindStringSubmatch(task.StartDate)[1]
    		timestamp, _ := strconv.ParseInt(tsString, 10, 64)
    		startTime := time.Unix(timestamp/1000, 0)
    		job, err := scheduler.Every(1).Day().StartAt(startTime).SetTag([]string{task.ID}).Do(taskWithParams, task)
    		// scheduler.Every(2).Seconds().Do(taskWithParams, task)
    		PrettyPrint(tsString)
    		PrettyPrint(timestamp)
    		PrettyPrint(startTime.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
    		_, tt := scheduler.NextRun()
    		log.Warn("Next run")
    		PrettyPrint(tt.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
    		if err != nil {
    			log.Error(err)
    		}
    		if task.RecurrencePattern == "" {
    			job.LimitRunsTo(1)
    			job.RemoveAfterLastRun()
    		}
    scheduler.StartAsync()
    

    }

    ` Output:

    { "Action": 0, "EndDate": "/Date(1608919200000+0100)/", "Filename": "/home/pi/doSomethingImportant.sh", "Id": "8a102123-a91d-474b-8f83-547c9cdcf3ad", "Parameters": "", "ProcedureName": "main", "RecurrencePattern": "", "ScheduleType": 0, "StartDate": "/Date(1608918720000+0100)/" } "1608918720000" 1608918720000 "Fri Dec 25 18:52:00 +0100 CET 2020" WARN[25/12/2020 18:50:35] Next run "Fri Dec 25 18:52:00 +0100 CET 2020" [ "8a102123-a91d-474b-8f83-547c9cdcf3ad" ]

    bug 
    opened by PolyglotOpenstreetmap 16
  • Feature request: Store job/schedule data

    Feature request: Store job/schedule data

    Thanks for awesome library that really helps :)

    Maybe it will be good idea. In some cases people neen to run task only once. Yes i can run task and then remove.

    And also. What will happend if there are 30 tasks in scheduler and app crashed. After restart we will lose all tasks.

    If it will be good idea, can try to do this

    enhancement 
    opened by cybervagabond 14
  • [FEATURE] - Limit task by tag name

    [FEATURE] - Limit task by tag name

    Is your feature request related to a problem? Please describe

    I am not really sure if this is already present and i am missing something out in this library but it would be nice to have functionality to run only one job with assigned tag name. Right now this can be added N times. I have a requirement where i would like to add only one cron per tag

    Describe the solution you'd like

    s.Every(1).Second().Tag(tag).Lock(1).Do(task)

    enhancement 
    opened by gopherine 11
  • Add option to limit maximum concurrent jobs

    Add option to limit maximum concurrent jobs

    What does this do?

    This feature is backwards compatible and allows limiting the maximum concurrent jobs. It is useful when running resource intensive jobs and a precise start time is not critical.

    Which issue(s) does this PR fix/relate to?

    Resolves #53

    List any changes that modify/break current functionality

    None

    Have you included tests for your changes?

    No

    Did you document any new/modified functionality?

    • [X] Updated example_test.go
    • [X] Updated README.md

    Notes

    opened by dustin-decker 11
  • [FEATURE] - Error chan on scheduler

    [FEATURE] - Error chan on scheduler

    https://github.com/jasonlvhit/gocron/issues/134

    This feature was discussed before.
    hop add this feature .

    enhancement 
    opened by 110 11
  • feat: Add single mode in job

    feat: Add single mode in job

    What does this do?

    This mode prevents double start.

    opened by farwydi 9
  • Bug in scheduler

    Bug in scheduler

    package main
    
    import (
    	"fmt"
    	"time"
    
    	"github.com/go-co-op/gocron"
    )
    
    func task() {
    	fmt.Println(time.Now())
    }
    
    func main() {
    	s1 := gocron.NewScheduler(time.UTC)
    	s1.Every(10).Seconds().Do(task)
    	<-s1.Start() // starts running (blocks current thread)
    }
    
    
    go run main.go
    2020-03-31 23:10:10.5018339 -0500 CDT m=+10.003605201
    2020-03-31 23:10:20.5028812 -0500 CDT m=+20.004652501
    2020-03-31 23:10:30.501854 -0500 CDT m=+30.003625301
    2020-03-31 23:10:31.5013486 -0500 CDT m=+31.003119901
    2020-03-31 23:10:41.5022159 -0500 CDT m=+41.003987201
    2020-03-31 23:10:51.5013717 -0500 CDT m=+51.003143001
    2020-03-31 23:10:52.5031395 -0500 CDT m=+52.004910801
    2020-03-31 23:11:02.5020695 -0500 CDT m=+62.003840801
    2020-03-31 23:11:03.5014576 -0500 CDT m=+63.003228901
    2020-03-31 23:11:13.5016872 -0500 CDT m=+73.003458501
    2020-03-31 23:11:23.5017684 -0500 CDT m=+83.003539701
    2020-03-31 23:11:33.5013161 -0500 CDT m=+93.003087401
    2020-03-31 23:11:34.508206 -0500 CDT m=+94.009977301
    2020-03-31 23:11:44.5021093 -0500 CDT m=+104.003880601
    2020-03-31 23:11:45.503181 -0500 CDT m=+105.004952301
    2020-03-31 23:11:55.5017912 -0500 CDT m=+115.003562501
    2020-03-31 23:11:56.5028593 -0500 CDT m=+116.004630601
    2020-03-31 23:12:06.5013873 -0500 CDT m=+126.003158601
    2020-03-31 23:12:07.5014535 -0500 CDT m=+127.003224801
    2020-03-31 23:12:17.5013532 -0500 CDT m=+137.003124501
    2020-03-31 23:12:18.5029237 -0500 CDT m=+138.004695001
    2020-03-31 23:12:28.501378 -0500 CDT m=+148.003149301
    2020-03-31 23:12:29.5012798 -0500 CDT m=+149.003051101
    2020-03-31 23:12:39.5022707 -0500 CDT m=+159.004042001
    2020-03-31 23:12:49.5018604 -0500 CDT m=+169.003631701
    2020-03-31 23:12:50.5017803 -0500 CDT m=+170.003551601
    2020-03-31 23:13:00.5019564 -0500 CDT m=+180.003727701
    2020-03-31 23:13:10.5020875 -0500 CDT m=+190.003858801
    2020-03-31 23:13:20.5016438 -0500 CDT m=+200.003415101
    2020-03-31 23:13:21.5017742 -0500 CDT m=+201.003545501
    2020-03-31 23:13:31.503144 -0500 CDT m=+211.004915301
    2020-03-31 23:13:41.5014638 -0500 CDT m=+221.003235101
    2020-03-31 23:13:42.5028217 -0500 CDT m=+222.004593001
    2020-03-31 23:13:52.5013111 -0500 CDT m=+232.003082401
    2020-03-31 23:13:53.5014415 -0500 CDT m=+233.003212801
    2020-03-31 23:14:03.501239 -0500 CDT m=+243.003010301
    2020-03-31 23:14:04.5013094 -0500 CDT m=+244.003080701
    2020-03-31 23:14:14.5030847 -0500 CDT m=+254.004856001
    2020-03-31 23:14:24.5019311 -0500 CDT m=+264.003702401
    2020-03-31 23:14:25.5020085 -0500 CDT m=+265.003779801
    
    bug 
    opened by JohnRoesler 9
  • question

    question

    how to check all jobs

    opened by wanghuashun 9
  • [FEATURE] - Ability to reschedule a task

    [FEATURE] - Ability to reschedule a task

    Is your feature request related to a problem? Please describe

    I want to be able to change the scheduling time based on the settings received while executing a task

    Describe the solution you'd like

    I tried adding a separate channel to capture a message on task frequency change and clearing the existing task and the adding a new one with the new frequency. However this causes race conditions.

    enhancement 
    opened by apremalal 8
  • [BUG] - Removing a task fails to stop it from executing

    [BUG] - Removing a task fails to stop it from executing

    Describe the bug

    Removing a task doesn't prevent it from being executed.

    To Reproduce

    I may be missing something, but it appears that there is no way to actually remove a task. The following unit test will run 'task' for three seconds, and then remove it, but afterward the task still runs.

    func TestCron(t *testing.T) {
    	sched := gocron.NewScheduler(time.UTC)
    	sched.StartAsync()
    	i := 0
    	task := func() {
    		fmt.Printf("task %d\n", i)
    		i++
    	}
    	sched.Every(1).Second().Do(task)
    	ch := make(chan bool, 1)
    	time.AfterFunc(3*time.Second, func() {
    		fmt.Println("removing task")
    		sched.Remove(task)
    		ch <- true
    	})
    	<-ch
    	time.AfterFunc(3*time.Second, func() {
    		// during this 3 seconds, the task will still be run
    		ch <- true
    	})
    	<-ch
    }
    
    This appears to be because in scheduler.go:scheduleNextRun, the function passed to AfterFunc always calls scheduleNextRun, without regard to whether the job is still in the scheduler's jobs list. It should check that 'job' is currently in the list before scheduling the next execution. (The same issue occurs when the job is removed by reference or tag.)
    
    

    Version

    v0.5.1

    Expected behavior

    Once a periodic job is removed it should not run again.

    Additional context

    N/A

    bug 
    opened by benderdave 8
  • [FEATURE] - Run a scheduled a job once in a distributed system

    [FEATURE] - Run a scheduled a job once in a distributed system

    Is your feature request related to a problem? Please describe

    Currently If I use this package on any cluster of AWS ec2s, all my machines running production code would also run code in the scheduler. For instance if I need a background go routine to scan data every minute and I have 5 machines deployed. I don't need or want all my machines to scan the same data. It's also not cost effective to spin a single isolated ec2 to run a single job.

    Describe the solution you'd like

    I would like if gocron had to ability to add connections to persistent storage via some sort of interface to allow users to plugin any persistent storage (redis, memcache, sql, etc) such that it kept track of the jobs running. If a job is running by 1 machine and you've set the settings to allow only 1 job globally to run, then all other machines do not run the same job. In essence it would be safe to deploy code on a fleet of web servers and have only 1 web server at any given time run the same job.

    some considerations:

    • When a cluster of machines are being deployed, restarted, or added to a load balancer, there is a chance for a race condition to occur given the latency it may take the fastest instance to write to persistent storage. Example If machine A writes to storage saying "hey I'm responsible for the job" and machine B checks storage a few minutes later and doesn't find anything in persistent storage it will also say "hey I'm responsible for the job" . This is because machines get updates in batches. In order to prevent this behavior there needs to be some sort of jitter or perhaps a queue is used. For instance of all the servers start up and schedule a job. The name space for that job should be the same on each machine. If i'm using redis, I would upsert a job by some shared id. When the scheduler ticks on the application it pops from the queue, if there is an item then it's granted the ability to run the job else the job does not run. When the job completes on the machine with the successful pop, it adds the job id back to the queue for the next tick.... something like that

    Describe alternatives you've considered

    • Spinning up isolated ec2s that do nothing other then run a single job, at the cost or operational cognitive load and monetary cost
    • Use other distributed systems like machinery, however projects like machinery aren't necessarily meant for cron like tasks.
    • Compile a Go binary and use the native linux cron system, but again this means moving away from using a very clean package and system that gocron presents
    enhancement 
    opened by marcsantiago 5
  • [BUG] - Out of sync, multiple executions of same task

    [BUG] - Out of sync, multiple executions of same task

    When using a 30s interval scheduler, after a few hours it runs multiple times the same task, per second

    Example snippet

    var partialUpdatesTag = []string{"partial"}
    var partialIndexer *gocron.Scheduler
    
    func indexSomeData(){
    	log.Println("Indexing data...")
    	time.Sleep(1 * time.Second) 
    }
    
    func runPartialReindex() {
    	log.Println("Runing partial...")
    	stopPartial()
    	indexSomeData()//dummy function won't take more than 200ms to complete
    	startPartial()
    }
    
    func schedulePartialReindex() {
    	log.Println("Partial reindex scheduler running each 30 seconds")
    	partialIndexer = gocron.NewScheduler(time.Local)
    	partialIndexer.Every(30 * time.Second).Tag(partialUpdatesTag...).SingletonMode().Do(runPartialReindex)
    	partialIndexer.StartAsync()
    }
    
    func startPartial() {
    	if partialIndexer == nil {
    		partialIndexer = gocron.NewScheduler(time.Local)
    	}
    	if !partialIndexer.IsRunning() {
    		partialIndexer.Clear() //make sure the old scheduler is cleared and no settings are kept
    		for _, tag := range partialUpdatesTag {
    			partialIndexer.RemoveByTag(tag)
    		}
    		partialIndexer = gocron.NewScheduler(time.Local)
    		partialIndexer.Every(30 * time.Second).Tag(partialUpdatesTag...).SingletonMode().Do(runPartialReindex)
    		time.Sleep(30 * time.Second) //we want to delay 30s start
    		partialIndexer.StartAsync()
    	}
    }
    func stopPartial() {
    	if partialIndexer == nil {
    		partialIndexer = gocron.NewScheduler(time.Local)
    	}
    	if partialIndexer.IsRunning() {
    		partialIndexer.Stop()
    		partialIndexer.WaitForSchedule().Stop() //make sure no runing tasks
    	}
    }
    

    It wasn't expected that the runPartialReindex function was run more than once per 30s interval I did try with partialIndexer.Every(30).Second() and partialIndexer.Every(30).Seconds() but the described problem is even worse Not sure if it matters but I'm using go mod.

    bug 
    opened by alexandre-dias-cj 3
  • [BUG] - Weekday() starts schedule on next day even when current day is set

    [BUG] - Weekday() starts schedule on next day even when current day is set

    Describe the bug

    While using Weekday(), the schedule starts on the following day even if the current day is set. eg.: If the current Day is Sunday and Sunday+Monday+Tuesday are set, the first run will be scheduled for Monday.

    To Reproduce

    Steps to reproduce the behavior:

    1. s.Every(1).Weekday(time.Sunday).Weekday(time.Monday).Weekday(time.Tuesday) or
    2. s.Every(1).Sunday().Monday().Tuesday()

    Version

    1.50

    Expected behavior

    If the current day is part of the weekdays set, the schedule should begin on the current day and not on the next desired weekday.

    Additional context

    bug 
    opened by joseccandido 12
  • [BUG] - Improve documentation of `.Month()` & related functions

    [BUG] - Improve documentation of `.Month()` & related functions

    Describe the bug

    The Documentation is vague on the use of dayOfTheMonth in .Month() and .Months()

    To Reproduce

    https://pkg.go.dev/github.com/go-co-op/gocron#Scheduler.Months

    Version

    github.com/go-co-op/gocron v1.0.0

    Expected behavior

    From a comment in the source code, it seems that setting -1 will run on the last day of the previous month. That's useful but not clear from the docs. There also should be a note indicating if this day is starting from 0 or from 1. If it starts from 1, what happens if I set 0? Keeping in mind -1 seems to be the previous day of the month, 0 seems like undefined behavior.

    Additional context

    The package is great, but a bit better doc of such edge cases would be extremely helpful.

    bug 
    opened by frapa 3
  • [FEATURE] - Support saving serialized scheduler and reinstating from serialized scheduler

    [FEATURE] - Support saving serialized scheduler and reinstating from serialized scheduler

    Is your feature request related to a problem? Please describe

    Source: https://github.com/go-co-op/gocron/discussions/139

    As a user of gocron, I would like to be able to save a scheduler when restarting my application.

    Describe the solution you'd like

    Expose methods to serialize and de-serialize the scheduler

    Describe alternatives you've considered

    • allowing jobs to be saved and re-added, this would be a lot clunkier
    • making scheduler fields exported - this would expose unnecessary details to the end user

    Additional context

    Example serialization: https://stackoverflow.com/questions/28020070/golang-serialize-and-deserialize-back

    // Export serializes the scheduler and returns a base64 encoded string
    func (s *Scheduler) Export() string {}
    
    // Import deserializes the scheduler and returns it
    func ImportScheduler(in string) *Scheduler {}
    

    I am thinking we'll want to create another struct with export fields that is used for serializing and de-serializing the main scheduler struct which contains unexported fields (which cannot be serialized using gob).

    enhancement 
    opened by JohnRoesler 0
  • [FEATURE] - Support running a job multiple At() times a day/week/month

    [FEATURE] - Support running a job multiple At() times a day/week/month

    Is your feature request related to a problem? Please describe

    Describe the solution you'd like

    s.Every(1).Day().At("02:00").At("04:00").Do(func() {})
    

    Describe alternatives you've considered

    s.Every(1).Day().At("02:00").Do(func() {})
    s.Every(1).Day().At("04:00").Do(func() {})
    

    Additional context

    enhancement 
    opened by JohnRoesler 0
  • [FEATURE] - Support running a job on multiple days of a month

    [FEATURE] - Support running a job on multiple days of a month

    Is your feature request related to a problem? Please describe

    This would be nice to allow a job to run multiple days in a month vs. a single day

    Describe the solution you'd like

    s.Every(1).Month(15).Month(17).At("02:00").Do(func() {})
    

    Describe alternatives you've considered

    s.Every(1).Month(15).At("02:00").Do(func() {})
    s.Every(1).Month(15).At("02:00").Do(func() {})
    

    Additional context

    could be done by adding a func On(day int)

    s.Every(1).Month().On(15).On(17).At("02:00").Do(func() {})
    
    enhancement 
    opened by JohnRoesler 0
  • [FEATURE] - Support running weekly schedule on multiple days of the week

    [FEATURE] - Support running weekly schedule on multiple days of the week

    Is your feature request related to a problem? Please describe

    This would be nice to allow a single job to be run multiple days of the week.

    Describe the solution you'd like

    s.Every(1).Week().Monday().Thursday().Saturday().At("02:00").Do(func() {})
    

    Describe alternatives you've considered

    s.Every(1).Week().Monday().At("02:00").Do(func() {})
    s.Every(1).Week().Thursday().At("02:00").Do(func() {})
    s.Every(1).Week().Saturday().At("02:00").Do(func() {})
    

    Additional context

    Perhaps scheduledWeekday becomes a slice, and then we figure out the right way to support that in calculating the duration to next run

    // Job struct stores the information necessary to run a Job
    type Job struct {
    	...
    	scheduledWeekday  *time.Weekday // Specific day of the week to start on
    	...
    }
    

    A custom struct with the 7 weekdays as bools might be a good option.

    enhancement 
    opened by JohnRoesler 2
  • [FEATURE] - Time format allow wildcards

    [FEATURE] - Time format allow wildcards

    First of all - awesome project, just what I needed in my life :smiley:

    It seems like there's error on time format for when defining on which minute cronjob should start at eg: scheduler.Every(1).Hour().At(":00").Lock().Do(MySuperCoolMethodToDeleteOldStuff) or scheduler.Every(1).Hour().At("**:30").Lock().Do(MySuperCoolMethodToDeleteOldStuff)

    When checking https://github.com/dbader/schedule then I can see that the time format is ":00", but on ruby clockwork https://github.com/Rykian/clockwork#event-parameters then the format is "**:30". I was hoping that similar things would work on this as well, but it seems now to me moreof like a feature request.

    What I intend to do is to sync the deployments to start at same time, so only one instance of the service will execute the method.

    So, that job MySuperCoolMethodToDeleteOldStuff would run at 12:00 13:00 14:00 etc..

    enhancement 
    opened by GeitV 3
  • [BUG] - Runs task twice

    [BUG] - Runs task twice

    Hi everyone, I am trying to integrate gocron in my service. But when I tried to run task it is running it twice.

    package services
    
    import (
    	"fmt"
    	"time"
    
    	"github.com/go-co-op/gocron"
    )
    
    func task() {
    	fmt.Println("I am running task.")
    }
    func main() {
    	s1 := gocron.NewScheduler(time.UTC)
    	s1.Every(1).Monday().Do(task)
    	s1.StartAsync()
            select{}
    }
    
    Output:
    I am running task.
    I am running task.
    

    Is there something that I am missing or is it a bug?

    Thanks you very much.

    bug 
    opened by pandurang90 21
Releases(v1.6.2)
  • v1.6.2(Jun 10, 2021)

  • v1.6.1(Jun 9, 2021)

    Fixed

    • Clear: remove also tags from scheduler (#182) @Dasio
    • find jobs not by substring but by exact match (#185) @skinnaj
    • Optimize computing startAtTime in the future (#189) @Dasio
    • Update() func supports crontab funcs (#191) @JohnRoesler
    • wait for interval respected by cron func (#192) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v1.6.0(May 26, 2021)

    Added

    • Support for multiple days in a week (#164) @joaolcaas

    Fixed

    • fixing invalid test behavior (#167) @joaolcaas
    • fix weekly interval greater than 1 week (#168) @joaolcaas
    • fix the monthly interval (#173) @joseccandido
    • fix RemoveByTag() so it also removes the unique tag if set (#178) @skinnaj
    • fix Remove recursive read locks in job present check (#177) @migopsdinesh & @dineshkumar02

    Chores

    • add example for job.weekdays() and tweak scheduler week examlpes, go mod tidy (#166) @JohnRoesler
    • Add start example (#170) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Apr 17, 2021)

    Add

    • add funcs for WaitForSchedule and WaitForScheduleAll to allow forcing jobs to wait for the first interval rather than running the job immediately (#162) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Apr 13, 2021)

    Added

    • add CronWithSeconds() to accept cron expressions with seconds (#156) @JohnRoesler

    Fixed

    • set the scheduler location explicitly in the cron expression (#156) @JohnRoesler
    • reset the job task's context.Context when updating allowing singleton and other limited modes to update (#160) @JohnRoesler
    • handle occasional occurrence of double run on daily job when within the same second (#159) @JohnRoesler

    Chores

    • Bump github.com/robfig/cron/v3 from 3.0.0 to 3.0.1 (#158) @dependabot
    Source code(tar.gz)
    Source code(zip)
  • v1.3.1(Apr 8, 2021)

    Fix

    • A bug in the scheduler was preventing hour and minute range use in cron expressions (#154) @JohnRoesler - thanks to @zry98 for reporting (#153)
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Apr 7, 2021)

  • v1.2.0(Apr 3, 2021)

    Add

    • add support for running all jobs with a given tag - RunByTag & RunByTagWithDelay (#149) @arjunmahishi
    • add support for rescheduling jobs (#145) @JohnRoesler

    Fixed

    • fixed the RemoveByTag function so that it removes all jobs with a given tag. Not just the first job encountered (#149) @arjunmahishi

    Chores

    • create a SECURITY.md @JohnRoesler
    • add codeql for security code scanning (#146) @JohnRoesler
    • add dependabot for actions and go deps (#147) @JohnRoesler
    • bump actions/setup-go from v1 to v2.1.3 (#148) @dependabot
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Mar 26, 2021)

  • v1.0.0(Mar 12, 2021)

    Here we go folks. Thanks for all the feedback as we've worked towards this major release. It's been a long time coming and it's finally here.

    Keep the issue reports and feature requests coming! Keep on coding out there.

    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Mar 10, 2021)

    Added

    • when multiple errors occur creating a job, they are now wrapped and returned (#130) @JohnRoesler
    • allowing the enforcement of unique tags when set through the scheduler with Scheduler.TagsUnique() (#136) @JohnRoesler
    • a new explicit interval func Milliseconds() - this was already available through Every(500ms) (#137) @JohnRoesler

    Changed

    • the Job.Err func has been renamed Job.Error (#137) @JohnRoesler
    • the default behavior of LimitRunsTo removes the job from the scheduler (#137) @JohnRoesler
      • nothing can be done with a stopped job in the scheduler so we opted to remove the job instead
    • At() now accepts either string or time.Time (parses out only h,m,s) (#137) @JohnRoesler

    Removed

    • the RemoveAfterLastRun func has been removed (#137) @JohnRoesler

    Chores

    • to go 1.16 (#135) @JohnRoesler
    • updates to the readme including a design diagram (513e278, 740bcdb) @JohnRoesler
    • added a code of conduct (88fbecc) @JohnRoesler
    • updated the gitignore (a55ceb8) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v0.7.1(Mar 4, 2021)

    Fixed

    • Clear() now properly stops all jobs before removing them from the scheduler (#134) @JohnRoesler

    Chores

    • Updated the readme with details around different job modes and combinations of schedule options (2a8757a) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Feb 26, 2021)

    Added

    • singleflight mode, if the same job tries to run again while a previous run hasn't finished yet, it will either wait to run or skip the run (#123) thanks @farwydi
    • the ability to limit the number of concurrent jobs, useful for resource intensive jobs (#126) thanks @dustin-decker

    Changed

    • we now send jobs to a job executor through channels instead of handling them directly in the scheduler, allowing us to get rid of many mutexes (#122) @JohnRoesler

    Fixed

    • a race condition issue on some getter methods (#124) thanks @amirhosseinvz94
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Feb 9, 2021)

    Added

    • allow starting Jobs at a date in the past (#113) @calvinmclean
    • add job limit and remove after last run to scheduler chain (#116) @JohnRoesler
    • scheduler.Every() now accepts int, time.Duration, and string to allow any desired duration between runs (#119) @JohnRoesler

    Changed

    • sets the default unit to seconds (#112) @JohnRoesler
    • catches a bad interval of 0 with an error (#112) @JohnRoesler
    • clarified several function names and accepted values (#121) @JohnRoesler
      • The job Tag func now accepts a variadic string parameter instead of a slice
      • The scheduler SetTag is now Tag and also accepts a variadic string parameter
      • The scheduler RemoveJobByTag is now RemoveByTag to be consistent with Remove and RemoveByReference
      • The scheduler RunAllWithDelay func now accepts a time.Duration instead of an int representing seconds
      • The scheduler Scheduled func is now TaskPresent - scheduled was confusing name because until the scheduler is started, it's not actually "scheduled to run". Now you can check whether the task is present in the scheduler.

    Fixed

    • fixed the bug with jobs not being stopped upon removal (5027f53) thanks @huage1994
    • catches nil timer with stopTimer() func (#112) @JohnRoesler
    • fix a bug where the monthly calculation failed rounding to midnight (#104) @sdw2330976
    • fix bug with limit runs to not stopping jobs (#114) @JohnRoesler

    Removed

    • remove stopChan from Scheduler (#105) @arjunmahishi

    Chores

    • documentation clean up (#112) @JohnRoesler
    • add golangci to actions - and address lint issues (#117) (#118) @JohnRoesler
    • add examples for all funcs to godoc (#121) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Jan 15, 2021)

  • v0.5.0(Dec 31, 2020)

    :exclamation: A bug was discovered and patched in v0.5.1

    Added

    • func to remove a particular job reference from the scheduler after the last execution of the job (#90) - thanks @dlaweb

    Changed

    • refactor scheduler to schedule jobs with time.AfterFunc() (#99) @Streppel

    Fixed

    • ran go test -race and cleans up all the race conditions (#92) @JohnRoesler
    • add mutex to scheduler location (#93) @JohnRoesler

    Removed

    • removed the deprecated StartImmediately() func (#92) @JohnRoesler

    Chores

    • added a makefile to enable easy fmt checks, lint, vet, test -race (#92) @JohnRoesler
    • Add a contributing md (#94) @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Dec 11, 2020)

    Added

    • Expose the Job's lastRun, nextRun and runCount (#83) @arjunmahishi

    Changed

    • scheduleNextRun now uses duration (#79) @Streppel
    • Start jobs immediately by default - StartImmediately() has been deprecated (#82) @JohnRoesler
      • To achieve the prior behavior of starting after the interval, use StartAt()
        s := gocron.NewScheduler(time.UTC)
        _, _ = s.Every(1).Hour().StartAt(time.Now().Add(time.Hour() * 1)).Do(task)
        s.StartBlocking()
        

    Fixed

    • Re-set the job's last run in scheduler run() (#81) @JohnRoesler
    • Fix runnableJobs where subsequent jobs are never checked (#87) @JohnRoesler
    • Handle job creation errors (#89) @arjunmahishi

    Removed

    • Non-working distributed lock (#77) @Streppel

    Chores

    • Add funding doc d12fdaf b7cd523 😃 @JohnRoesler
    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Nov 10, 2020)

  • v0.3.2(Nov 3, 2020)

    Added

    • Add a new Job method called 'LimitRunsTo' (#67)

    Changed

    • rewriting scheduler logic (#54)
    • regex for at time accepts time without leading zeros (#56)

    Fixed

    • Make sure Do() does not override the nextRun time when StartAt() is used (#49)
    • scheduler schedules jobs registration when already running (#61)

    Chores

    • Add godoc badge to README (#51)
    • removing legacy deterministic tests (#62)
    • Add examples from README to example_test.go (#66)
    • add go 1.15 to testing matrix and remove 1.13 (#68)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jul 21, 2020)

  • v0.2.1(Jul 16, 2020)

    Fixed

    • Fixed a bug in the removeByCondition func trying to access elements outside the slice range #46 - thank you @ridwanakf for your contribution!
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Apr 10, 2020)

    Added

    • Started an example_test.go file to provide examples in our go documentation #15

    Changed

    • Moved job locker into separate package #21
    • Fixed bug where jobs were executed twice in a row #20 #23
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Mar 28, 2020)

    We have forked this repo from https://github.com/jasonlvhit/gocron, because as the readme notes - we haven't heard from Jason in a long time and want to keep the code progressing.

    This is initial release provides some changes / updates to the way the prior code performed.

    Added

    • added the timeHelper interface to abstract the use of the time package and support future time mocking for testing

    Changed

    • the jobs array is now a slice
    • the scheduling logic was transferred from the job handling scheduling itself to the scheduler handling scheduling of all jobs
    • .From(gocron.NextTick) was changed to .StartImmediately
    • moved StartAt into the scheduler
    • the scheduler stopped chan uses an empty struct instead of a bool

    Removed

    • removed the default scheduler
    • removed the mustInterval func - Second and Seconds provide the same behavior and are for grammar / semantics only at this point
    Source code(tar.gz)
    Source code(zip)
Owner
Go Co Op
Go Co Op
Run Jobs on a schedule, supports fixed interval, timely, and cron-expression timers; Instrument your processes and expose metrics for each job.

A simple process manager that allows you to specify a Schedule that execute a Job based on a Timer. Schedule manage the state of this job allowing you to start/stop/restart in concurrent safe way. Schedule also instrument this Job and gather metrics and optionally expose them via uber-go/tally scope.

Sherif Abdel-Naby 53 Jul 2, 2021
Chrono is a scheduler library that lets you run your task and code periodically

Chrono is a scheduler library that lets you run your tasks and code periodically. It provides different scheduling functionalities to make it easier t

Procyon 104 Jul 20, 2021
Lightweight, fast and dependency-free Cron expression parser (due checker) for Golang (tested on v1.13 and above)

adhocore/gronx gronx is Golang cron expression parser ported from adhocore/cron-expr. Zero dependency. Very fast because it bails early in case a segm

Jitendra Adhikari 166 Jul 24, 2021
A simple job scheduler backed by Postgres.

A simple job scheduler backed by Postgres used in production at https://operand.ai. Setup needs two environment variables, SECRET and ENDPOINT. The se

Morgan Gallant 6 May 31, 2021
Easy and fluent Go cron scheduling

goCron: A Golang Job Scheduling Package. goCron is a Golang job scheduling package which lets you run Go functions periodically at pre-determined inte

Go Co Op 952 Jul 22, 2021
goCron: A Golang Job Scheduling Package.

goCron: A Golang Job Scheduling Package.

辣椒面 2.6k Jul 22, 2021
You had one job, or more then one, which can be done in steps

Leprechaun Leprechaun is tool where you can schedule your recurring tasks to be performed over and over. In Leprechaun tasks are recipes, lets observe

Strahinja 83 Jul 10, 2021
Distributed Task Scheduling System|分布式定时任务调度平台

Crocodile Distributed Task Scheduling System English | 中文 Introduction A distributed task scheduling system based on Golang that supports http request

labulaka521 591 Jul 18, 2021
gron, Cron Jobs in Go.

gron Gron provides a clear syntax for writing and deploying cron jobs. Goals Minimalist APIs for scheduling jobs. Thread safety. Customizable Job Type

roylee0704 863 Jul 20, 2021
Framework for performing work asynchronously, outside of the request flow

JobRunner JobRunner is framework for performing work asynchronously, outside of the request flow. It comes with cron to schedule and queue job functio

Bam Azizi 861 Jul 27, 2021
A persistent and flexible background jobs library for go.

Jobs Development Status Jobs is no longer being actively developed. I will still try my best to respond to issues and pull requests, but in general yo

Alex Browne 482 May 31, 2021
A simple Cron library for go that can execute closures or functions at varying intervals, from once a second to once a year on a specific date and time. Primarily for web applications and long running daemons.

Cron.go This is a simple library to handle scheduled tasks. Tasks can be run in a minimum delay of once a second--for which Cron isn't actually design

Robert K 202 Jun 12, 2021
Easily schedule commands to run multiple times at set intervals (like a cronjob, but with one command)

hakcron Easily schedule commands to run multiple times at set intervals (like a cronjob, but for a single command) Description hakcron allows you to r

Luke Stephens (hakluke) 58 Jul 21, 2021
定时任务管理系统

gocron - 定时任务管理系统 项目简介 使用Go语言开发的轻量级定时任务集中调度和管理系统, 用于替代Linux-crontab 查看文档 原有的延时任务拆分为独立项目延迟队列 功能特性 Web界面管理定时任务 crontab时间表达式, 精确到秒 任务执行失败可重试 任务执行超时, 强制结束

qiang.ou 3.6k Jul 25, 2021