https://github.com/gochore/dcron
A distributed cron framework.
https://github.com/gochore/dcron
cron cronjob distributed distributed-cron go golang
Last synced: 5 months ago
JSON representation
A distributed cron framework.
- Host: GitHub
- URL: https://github.com/gochore/dcron
- Owner: gochore
- License: mit
- Created: 2020-03-01T08:08:46.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-11-10T03:36:03.000Z (over 2 years ago)
- Last Synced: 2025-08-15T09:27:37.076Z (10 months ago)
- Topics: cron, cronjob, distributed, distributed-cron, go, golang
- Language: Go
- Homepage:
- Size: 63.5 KB
- Stars: 18
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dcron
[](https://pkg.go.dev/github.com/gochore/dcron)
[](https://github.com/gochore/dcron/actions)
[](https://codecov.io/gh/gochore/dcron)
[](https://goreportcard.com/report/github.com/gochore/dcron)
[](https://github.com/gochore/dcron/blob/master/go.mod)
[](https://github.com/gochore/dcron/releases)
A distributed cron framework.
## Install
```shell
go get github.com/gochore/dcron
```
## Quick Start
First, implement a distributed atomic operation that only requires support for one method: `SetIfNotExists`.
You can implement it in any way you prefer, such as using Redis `SetNX`.
```go
import "github.com/redis/go-redis/v9"
type RedisAtomic struct {
client *redis.Client
}
func (m *RedisAtomic) SetIfNotExists(ctx context.Context, key, value string) bool {
ret := m.client.SetNX(ctx, key, value, time.Hour)
return ret.Err() == nil && ret.Val()
}
```
Now you can create a cron with that:
```go
func main() {
atomic := &RedisAtomic{
client: redis.NewClient(&redis.Options{
Addr: "localhost:6379",
}),
}
cron := dcron.NewCron(dcron.WithKey("TestCron"), dcron.WithAtomic(atomic))
}
```
Then, create a job and add it to the cron.
```go
job1 := dcron.NewJob("Job1", "*/15 * * * * *", func(ctx context.Context) error {
if task, ok := dcron.TaskFromContext(ctx); ok {
log.Println("run:", task.Job.Spec(), task.Key)
}
// do something
return nil
})
if err := cron.AddJobs(job1); err != nil {
log.Fatal(err)
}
```
Finally, start the cron:
```go
cron.Start()
log.Println("cron started")
time.Sleep(time.Minute)
<-cron.Stop().Done()
```
If you start the program multiple times, you will notice that the cron will run the job once every 15 seconds on only one of the processes.
| process 1 | process 2 | process 3 |
|------------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
| 2023/10/13 11:39:45 cron started | 2023/10/13 11:39:47 cron started | 2023/10/13 11:39:48 cron started |
| | | 2023/10/13 11:40:00 run: */15 * * * * * dcron:TestCron.Job1@1697168400 |
| | 2023/10/13 11:40:15 run: */15 * * * * * dcron:TestCron.Job1@1697168415 | |
| | | 2023/10/13 11:40:30 run: */15 * * * * * dcron:TestCron.Job1@1697168430 |
| 2023/10/13 11:40:45 run: */15 * * * * * dcron:TestCron.Job1@1697168445 | | |
One more thing, since `dcron.WithAtomic(atomic)` is optional, it's also a good idea to use it as a local cron.
```go
cron := dcron.NewCron()
job2 := dcron.NewJob("A local job", "*/15 * * * * *", func(ctx context.Context) error {
// do something
return nil
})
if err := cron.AddJobs(job2); err != nil {
log.Fatal(err)
}
```