ttacon / gofourit

Ensure singleton execution of cron jobs across a distributed system.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

gofourit

Motivation

You need to run a single function on a cron-style schedule, but you need to ensure that it only runs once across a fleet of tasks or servers. As such, this library is more of an opinionated take on how to do this as opposed to a general solution.

Installation

The usual manner of grabbing the go package:

go get github.com/ttacon/gofourit

Usage

The examples/ folder has more examples, but basic usage looks as follows:

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"syscall"

	"github.com/go-redis/redis/v8"
	"github.com/ttacon/gofourit"
	"github.com/ztrue/shutdown"
)

var (
	id = flag.String("id", "", "ID for this process")
)

func main() {
	flag.Parse()
	if len(*id) == 0 {
		log.Println("must provide -id flag")
		os.Exit(1)
	}

	rCron := gofourit.New(
		gofourit.NewRedisRemoteSource(
			redis.NewClient(
				&redis.Options{
					Network: "tcp",
					Addr:    "127.0.0.1:6379",
				},
			),
		),
	)

	shHandler := shutdown.New()
	shHandler.Add(func() {
		rCron.Stop()
	})

	rCron.AddFunc("* * * * *", "print-it", func() {
		fmt.Printf("running `print-it` from: %q\n", *id)
	})

	rCron.AddFunc("* * * * *", "say-hello", func() {
		fmt.Printf("hello from: %q\n", *id)
	})
	rCron.Start()

	log.Println("up and running...")
	shHandler.Listen(syscall.SIGTERM)
}

How it works

Unique key per function

gofourit works by wrapping each registered function in a function that attempts to acquire a lock based on the given name. If the function gets the lock, it'll run the function, if it doesn't it returns immediately.

Because we use a unique key per function, this means functions will be run by whichever owning process grabs the lock.

Compared to cron-cluster in nodejs

This library takes inspiration in spirit from cron-cluster in Node.js, but differs in one primary way. cron-cluster uses an underlying algorithm to identify who should be the leader for the given instantiation of that CronJob (it uses redis-leader for this leader identification). This means that if you register multiple cron jobs, they will all run on whichever task is currently the leader.

gofourit instead takes the stance to share this load out, instead of potentially isolating all cron jobs to run on the same task.

Future enhancements

  • Better logging options
  • Better lock configuration options (TTLs, retries, maintaining a lock)
  • Further remote source implementations (e.g. DynamoDB)

About

Ensure singleton execution of cron jobs across a distributed system.

License:MIT License


Languages

Language:Go 100.0%