gofourit

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2020 License: MIT Imports: 4 Imported by: 0

README

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)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cron

type Cron interface {
	AddFunc(cronString, key string, fn func()) Cron
	Entries() []cron.Entry

	Start()
	Stop()
}

Cron is the interface for our distributed cron scheduler

func New

func New(rSrc RemoteSource) Cron

New returns a new Cron that will use the given RemoteSource to generate generate locks.

type Lock

type Lock interface {
	Release()
}

Lock is the interface for Locks generated by our RemoteSource.

type RemoteSource

type RemoteSource interface {
	GrabLock(key string) Lock
}

RemoteSource is the source of how we acquire locks to run jobs on a single node.

func NewRedisRemoteSource

func NewRedisRemoteSource(client redislock.RedisClient) RemoteSource

NewRedisRemoteSource returns a new RemoteSource based on the given redis client.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL