Categorygithub.com/ankorstore/yokai/fxcron
modulepackage
1.1.0
Repository: https://github.com/ankorstore/yokai.git
Documentation: pkg.go.dev

# README

Fx Cron Module

ci go report codecov Deps PkgGoDev

Fx module for gocron.

Installation

go get github.com/ankorstore/yokai/fxcron

Features

This module provides the possibility to run internal cron jobs in your application with:

  • automatic panic recovery
  • configurable cron jobs scheduling and execution options
  • configurable logging, tracing and metrics for cron jobs executions

Documentation

Dependencies

This module is intended to be used alongside:

Loading

To load the module in your Fx application:

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxcron"
	"github.com/ankorstore/yokai/fxgenerate"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxmetrics"
	"github.com/ankorstore/yokai/fxtrace"
	"github.com/go-co-op/gocron/v2"
	"go.uber.org/fx"
)

func main() {
	fx.New(
		fxconfig.FxConfigModule,                      // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxtrace.FxTraceModule,
		fxmetrics.FxMetricsModule,
		fxgenerate.FxGenerateModule,
		fxcron.FxCronModule,                          // load the module
		fx.Invoke(func(scheduler gocron.Scheduler) {
			scheduler.Start()                         // start the cron jobs scheduler
		}),
	).Run()
}

Configuration

Configuration reference:

# ./configs/config.yaml
app:
  name: app
  env: dev
  version: 0.1.0
  debug: true
modules:
  log:
    level: info
    output: stdout
  trace:
    processor:
      type: stdout
  cron:
    scheduler:
      seconds: true                   # to allow seconds based cron jobs expressions (impact all jobs), disabled by default
      concurrency:
        limit:
          enabled: true               # to limit concurrent cron jobs executions, disabled by default
          max: 3                      # concurrency limit
          mode: wait                  # "wait" or "reschedule"
      stop:
        timeout: 5s                   # scheduler shutdown timeout for graceful cron jobs termination, 10 seconds by default
    jobs:                             # common cron jobs options
      execution:
        start:
          immediately: true           # to start cron jobs executions immediately (by default)
          at: "2023-01-01T14:00:00Z"  # or a given date time (RFC3339)
        limit:
          enabled: true               # to limit the number of per cron jobs executions, disabled by default
          max: 3                      # executions limit
      singleton:
        enabled: true                 # to execute the cron jobs in singleton mode, disabled by default
        mode: wait                    # "wait" or "reschedule"
    log:
      enabled: true                   # to log cron jobs executions, disabled by default (errors will always be logged).
      exclude:                        # to exclude by name cron jobs from logging
        - foo
        - bar
    metrics:
      collect:
        enabled: true                 # to collect cron jobs executions metrics (executions count and duration), disabled by default
        namespace: foo                # cron jobs metrics namespace (empty by default)
        subsystem: bar                # cron jobs metrics subsystem (empty by default)
      buckets: 1, 1.5, 10, 15, 100    # to define custom cron jobs executions durations metric buckets (in seconds)
    trace:
      enabled: true                   # to trace cron jobs executions, disabled by default
      exclude:                        # to exclude by name cron jobs from tracing
        - foo
        - bar

Notes:

  • the cron jobs executions logging will be based on the fxlog module configuration
  • the cron jobs executions tracing will be based on the fxtrace module configuration

Check the configuration files documentation for more details.

Cron jobs

Definition

This module provides a simple CronJob interface to implement for your cron jobs:

package cron

import (
	"context"

	"github.com/ankorstore/yokai/fxcron"
	"path/to/service"
)

type SomeCron struct {
	service *service.SomeService
}

func NewSomeCron(service *service.SomeService) *SomeCron {
	return &SomeCron{
		service: service,
	}
}

func (c *SomeCron) Name() string {
	return "some cron job"
}

func (c *SomeCron) Run(ctx context.Context) error {
	// contextual job name and execution id
	name, id := fxcron.CtxCronJobName(ctx), fxcron.CtxCronJobExecutionId(ctx)

	// contextual tracing
	ctx, span := fxcron.CtxTracer(ctx).Start(ctx, "some span")
	defer span.End()

	// contextual logging
	fxcron.CtxLogger(ctx).Info().Msg("some log")

	// invoke autowired dependency
	err := c.service.DoSomething(ctx, name, id)

	// returned errors will automatically be logged
	return err
}

Notes:

  • your cron job dependencies will be autowired
  • you can access from the provided context:
    • the cron job name with CtxCronJobName()
    • the cron job execution id with CtxCronJobExecutionId()
    • the tracer with CtxTracer(), which will automatically add to your spans the CronJob name and CronJobExecutionID attributes
    • the logger with CtxLogger(), which will automatically add to your log records the cronJob name and cronJobExecutionID fields

Registration

Once ready, you can register and schedule your cron job with AsCronJob():

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxcron"
	"github.com/ankorstore/yokai/fxgenerate"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxmetrics"
	"github.com/ankorstore/yokai/fxtrace"
	"github.com/go-co-op/gocron/v2"
	"go.uber.org/fx"
	"path/to/cron"
)

func main() {
	fx.New(
		fxconfig.FxConfigModule,      // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxmetrics.FxMetricsModule,
		fxgenerate.FxGenerateModule,
		fxcron.FxCronModule,          // load the module
		fx.Options(
			// register, autowire and schedule SomeCron to run every 2 minutes
			fxcron.AsCronJob(cron.NewSomeCron, `*/2 * * * *`),
		),
	).Run()
}

You can override, per job, the common job execution options by providing your own list of gocron.JobOption, for example:

fxcron.AsCronJob(cron.NewSomeCron, `*/2 * * * *`, gocron.WithLimitedRuns(10)),

If you need cron jobs to be scheduled on the seconds level, configure the scheduler with modules.cron.scheduler.seconds=true.

It will add seconds field to the beginning of the scheduling expression, for example to run every 5 seconds:

fxcron.AsCronJob(cron.NewSomeCron, `*/5 * * * * *`),

Note: you can use https://crontab.guru to help you with your scheduling definitions.

Override

By default, the gocron.Scheduler is created by the DefaultCronSchedulerFactory.

If needed, you can provide your own factory and override the module:

package main

import (
	"github.com/ankorstore/yokai/fxconfig"
	"github.com/ankorstore/yokai/fxcron"
	"github.com/ankorstore/yokai/fxgenerate"
	"github.com/ankorstore/yokai/fxlog"
	"github.com/ankorstore/yokai/fxmetrics"
	"github.com/ankorstore/yokai/fxtrace"
	"github.com/go-co-op/gocron/v2"
	"go.uber.org/fx"
)

type CustomCronSchedulerFactory struct{}

func NewCustomCronSchedulerFactory() fxcron.CronSchedulerFactory {
	return &CustomCronSchedulerFactory{}
}

func (f *CustomCronSchedulerFactory) Create(options ...gocron.SchedulerOption) (gocron.Scheduler, error) {
	return gocron.NewScheduler(options...)
}

func main() {
	fx.New(
		fxconfig.FxConfigModule, // load the module dependencies
		fxlog.FxLogModule,
		fxtrace.FxTraceModule,
		fxmetrics.FxMetricsModule,
		fxgenerate.FxGenerateModule,
		fxcron.FxCronModule,                         // load the module
		fx.Decorate(NewCustomCronSchedulerFactory),  // override the module with a custom factory
		fx.Invoke(func(scheduler gocron.Scheduler) { // invoke the cron scheduler
			// ...
		}),
	).Run()
}

# Functions

AnnotateTracerProvider extends a provided [oteltrace.TracerProvider] spans with cron jobs execution attributes.
AsCronJob registers a cron job into Fx, with an optional list of [gocron.JobOption].
Contains returns true if a provided string is found in a list of strings.
CtxCronJobExecutionId returns the contextual cron job execution id.
CtxCronJobName returns the contextual cron job name.
CtxLogger returns the contextual logger.
CtxTracer returns the contextual tracer.
GetReturnType returns the return type of a target.
GetType returns the type of a target.
NewCronJobDefinition returns a new [CronJobDefinition].
NewCronJobMetrics returns a new [CronJobMetrics] instance for provided metrics namespace and subsystem.
NewCronJobMetricsWithBuckets returns a new [CronJobMetrics] instance for provided metrics namespace, subsystem and buckets.
NewDefaultCronSchedulerFactory returns a [DefaultCronSchedulerFactory], implementing [CronSchedulerFactory].
NewFxCron returns a new [gocron.Scheduler].
NewFxCronJobRegistry returns as new [CronJobRegistry].
NewFxCronModuleInfo returns a new [FxCronModuleInfo].
NewResolvedCronJob returns a new [ResolvedCronJob] instance.
NewTracerProviderCronJobAnnotator returns a new [TracerProviderWorkerAnnotator].
Sanitize transforms a given string to not contain spaces or dashes, and to be in lower case.
Split trims and splits a provided string by comma.

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Variables

FxCronModule is the [Fx] cron module.

# Structs

CronJobMetrics is the metrics handler for the cron jobs.
CronJobRegistry is the registry collecting cron jobs and their definitions.
CtxCronJobExecutionIdKey is a contextual struct key.
CtxCronJobNameKey is a contextual struct key.
DefaultCronSchedulerFactory is the default [CronSchedulerFactory] implementation.
FxCronJobRegistryParam allows injection of the required dependencies in [NewFxCronJobRegistry].
FxCronModuleInfo is a module info collector for fxcore.
FxCronParam allows injection of the required dependencies in [NewFxCron].
ResolvedCronJob represents a resolved cron job, with its expression and execution options.
TracerProviderCronJobAnnotator is the [oteltrace.TracerProvider] cron jobs annotator, implementing [otelsdktrace.SpanProcessor].

# Interfaces

CronJob is the interface for cron jobs.
CronJobDefinition is the interface for cron job definitions.
CronSchedulerFactory is the interface for [gocron.Scheduler] factories.