Chadburn is a scheduler alternative to cron, built on Go and designed for Docker environments.

Chadburn - a job schedulerGitHub version Testing Status

Chadburn is a modern and low footprint job scheduler for docker environments, written in Go. Chadburn aims to be a replacement for the old fashioned cron.

*** SPECIAL NOTE ***

Chadburn is a new project based on the previous and continuous work incorporated into Ofelia and a fork of Ofelia provided by @rdelcorro, of which Chadburn was forked from. This project was started as a result of needing a version of Ofelia that incorporated the following fixes:

  • Update tasks if docker containers are started, stopped, restarted, or changed
  • Do not require a dummy task on the Ofelia container just to use Chadburn.
  • Support INI and docker labels at the same time. The configs will simply be merged.
  • Do not require a restart in order to pick up new or remove tasks.

PremoWeb will be responsive to addressing issues raised in this project and will also be monitoring issues in the original Ofelia source code repository and applying changes that should be reflected in Chadburn.

Why Chadburn?

It has been a long time since cron was released, actually more than 28 years. The world has changed a lot and especially since the Docker revolution. Vixie's cron works great but it's not extensible and it's hard to debug when something goes wrong.

Many solutions are available: ready to go containerized crons, wrappers for your commands, etc. but in the end simple tasks become complex.

How?

The main feature of Chadburn is the ability to execute commands directly on Docker containers. Using Docker's API Chadburn emulates the behavior of exec, being able to run a command inside of a running container. Also you can run the command in a new container destroying it at the end of the execution.

Configuration

A wiki is being written to document how to use Chadburn. Caprover users can use a One Click App (coming soon) to deploy and implement scheduled jobs using Service Label Overrides.

For everyone else, here's the general approach to use Chadburn:

Jobs

Scheduling format is the same as the Go implementation of cron. E.g. @every 10s or 0 0 1 * * * (every night at 1 AM).

Note: the format starts with seconds, instead of minutes.

you can configure four different kind of jobs:

  • job-exec: this job is executed inside of a running container.
  • job-run: runs a command inside of a new container, using a specific image.
  • job-local: runs the command inside of the host running Chadburn.
  • job-service-run: runs the command inside a new "run-once" service, for running inside a swarm

See Jobs reference documentation for all available parameters.

INI-style config

Run with chadburn daemon --config=/path/to/config.ini

[job-exec "job-executed-on-running-container"]
schedule = @hourly
container = my-container
command = touch /tmp/example

[job-run "job-executed-on-new-container"]
schedule = @hourly
image = ubuntu:latest
command = touch /tmp/example

[job-local "job-executed-on-current-host"]
schedule = @hourly
command = touch /tmp/example


[job-service-run "service-executed-on-new-container"]
schedule = 0,20,40 * * * *
image = ubuntu
network = swarm_network
command =  touch /tmp/example

Docker labels configurations

In order to use this type of configurations, Chadburn need access to docker socket.

docker run -it --rm \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
        premoweb/chadburn:latest daemon --docker

Labels format: `chadburn.<JOB_TYPE>.<JOB_NAME>.<JOB_PARAMETER>=<PARAMETER_VALUE>. This type of configuration supports all the capabilities provided by INI files.

Also, it is possible to configure job-exec by setting labels configurations on the target container. To do that, additional label chadburn.enabled=true need to be present on the target container.

For example, we want chadburn to execute uname -a command in the existing container called my_nginx. To do that, we need to we need to start my_nginx container with next configurations:

docker run -it --rm \
    --label chadburn.enabled=true \
    --label chadburn.job-exec.test-exec-job.schedule="@every 5s" \
    --label chadburn.job-exec.test-exec-job.command="uname -a" \
        nginx

Now if we start chadburn container with the command provided above, it will execute the task:

  • Exec - uname -a

Or with docker-compose:

version: "3"
services:
  chadburn:
    image: premoweb/chadburn:latest
    depends_on:
      - nginx
    command: daemon --docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  nginx:
    image: nginx
    labels:
      chadburn.enabled: "true"
      chadburn.job-exec.datecron.schedule: "@every 5s"
      chadburn.job-exec.datecron.command: "uname -a"

Dynamic docker configuration

You can start Chadburn in its own container or on the host itself, and it will magically pick up any container that starts, stops or is modified on the fly. In order to achieve this, you simply have to use docker containers with the labels described above and let Chadburn take care of the rest.

Hybrid configuration (INI files + Docker)

You can specify part of the configuration on the INI files, such as globals for the middlewares or even declare tasks in there but also merge them with docker. The docker labels will be parsed, added and removed on the fly but also, the file config can be used to execute tasks that are not possible using just docker labels such as:

  • job-local
  • job-run

Use the INI file to:

  • Configure the slack or other middleware integration
  • Configure any global setting
  • Create a job-run so it executes on a new container each time
[global]
slack-webhook = https://myhook.com/auth

[job-run "job-executed-on-new-container"]
schedule = @hourly
image = ubuntu:latest
command = touch /tmp/example

Use docker to:

docker run -it --rm \
    --label chadburn.enabled=true \
    --label chadburn.job-exec.test-exec-job.schedule="@every 5s" \
    --label chadburn.job-exec.test-exec-job.command="uname -a" \
        nginx

Logging

Chadburn comes with three different logging drivers that can be configured in the [global] section:

  • mail to send mails
  • save to save structured execution reports to a directory
  • slack to send messages via a slack webhook

Options

  • smtp-host - address of the SMTP server.

  • smtp-port - port number of the SMTP server.

  • smtp-user - user name used to connect to the SMTP server.

  • smtp-password - password used to connect to the SMTP server.

  • email-to - mail address of the receiver of the mail.

  • email-from - mail address of the sender of the mail.

  • mail-only-on-error - only send a mail if the execution was not successful.

  • save-folder - directory in which the reports shall be written.

  • save-only-on-error - only save a report if the execution was not successful.

  • slack-webhook - URL of the slack webhook.

  • slack-only-on-error - only send a slack message if the execution was not successful.

Overlap

Chadburn can prevent that a job is run twice in parallel (e.g. if the first execution didn't complete before a second execution was scheduled. If a job has the option no-overlap set, it will not be run concurrently.

Installation

The easiest way to deploy Chadburn is using Docker. See examples above.

If don't want to run Chadburn using our Docker image you can download a binary from releases page.

Thank You to team Ofelia and it's contributors.

A special thanks to @rdelcorro for the work in fixing the issues referenced in this pull request https://github.com/mcuadros/ofelia/pull/137, despite this pull request having been ignored for 30 days. PremoWeb aims to ensure that open software is continously improve and will remain responsive to raised issues and pull requests.

Much thanks to the original work that went into Ofelia by it's author and contributors.

Comments
  • Job is always being deregistered

    Job is always being deregistered

    Hi, it seems that if I use a configuration file instead of the labels option in the docker-compose file my job is always deregistered for some reason:

    scheduler  | daemon.go:41 ▶ DEBUG Config file: /etc/chadburn.conf not found                                     │
    scheduler  | scheduler.go:45 ▶ NOTICE New job registered "users-tasks" - "uname -a" - "@every 20s" - ID: 1      │
    scheduler  | scheduler.go:56 ▶ DEBUG Starting scheduler                                                         │
    scheduler  | cron_utils.go:13 ▶ DEBUG start                                                                     │
    scheduler  | cron_utils.go:13 ▶ DEBUG schedule
    scheduler  | scheduler.go:50 ▶ NOTICE Job deregistered (will not fire again) "users-tasks" - "uname -a" - "@ever│
    y 20s" - ID: 1                                                                                                  │
    scheduler  | cron_utils.go:13 ▶ DEBUG removed
    

    My config.conf:

    [global]
    save-folder = /etc/logs
    
    [job-exec "users-tasks"]
    schedule = @every 20s
    container = api
    network = app-network
    command = uname -a
    

    My docker-compose.yml:

    api:
            image: some-cool-image
            labels:
                chadburn.enabled: "true"
    
    scheduler:
            image: premoweb/chadburn:latest
            container_name: scheduler
            restart: unless-stopped
            volumes:
                - /var/run/docker.sock:/var/run/docker.sock:ro
                - ./scheduler/config.conf:/etc/chadburn.conf
            depends_on:
                - api
            networks:
                - app-network
    

    But it works if I do this:

    api:
            image: some-cool-image
            labels:
                chadburn.enabled: "true"
                chadburn.job-exec.datecron.schedule: "@every 5s"
                chadburn.job-exec.datecron.command: "uname -a"
    
    scheduler:
            image: premoweb/chadburn:latest
            container_name: scheduler
            restart: unless-stopped
            volumes:
                - /var/run/docker.sock:/var/run/docker.sock:ro
            depends_on:
                - api
            networks:
                - app-network
    
  • ARM/v7 Support? (ready-to-use docker image)

    ARM/v7 Support? (ready-to-use docker image)

    This issue opened as a result of a question asked by @markfqs seeking an "off the shelf" solution for the arm/v7 architecture:

    See original comment raising the issue: https://github.com/mcuadros/ofelia/pull/137#issuecomment-934487429.

    I'm still new to Github's CI/CD tooling for automated Actions in Workflows but I'm pretty sure I can get you a usable product soon. While I do not currently have possession of any device with an ARM Cortex A9 chipset (ARM/v7), I do know that there hosting providers that do provide VPS accounts that use this architecture.

    In a quick search, I see that there are example Github workflows for building form ARM/v7. I'll try and see what I can do in the coming days to solve this for you.

    So, @markfqs, what kind of device using ARM/v7 version of the ARM Cortex A9 chipset you wish to see support for?

  • Email reporting: allow SMTP auth on unencrypted connections

    Email reporting: allow SMTP auth on unencrypted connections

    Copied from https://github.com/mcuadros/ofelia/issues/173 as Ofelia seems unmaintained:

    I want to use the email option together with gotify-smtp, which requires you to put the destination user that should receive the notifications in the authentication username field. However, Ofelia refuses to allow this:

    mail.go:57 ▶️ ERROR Mail error: "unencrypted connection"
    

    In general, I totally agree with this behaviour. But given I am only trying to communicate to another Docker container on the same network, there is no security issue that I can tell from using an unencrypted connection. It would be nice if there could be an option to allow authenticating over an unencrypted connection (disabled by default, of course). Thank you for considering :)

  • Config file cannot be loaded on startup

    Config file cannot be loaded on startup

    I'm not yet sure as to why this is happening, but my config file wont read at startup and thus I dont get logging right.

    I am using the latest docker container and I've tried mounting the config file via volume, copying it into /tmp in the container and even setting chmod to 777.

    I did also start chadburn a second time inside the container - with same results. Logging would be really great as I cannot get my jobs working. Surprisingly the config file gets loaded successfully for the jobs - even though they are not working.

    / # /usr/bin/chadburn daemon --config=/tmp/chadburn.conf 
    daemon.go:41 ▶ DEBUG Config file: /tmp/chadburn.conf not found
    scheduler.go:45 ▶ NOTICE New job registered "autoprint-test1" - "cd /app/autoprint/test1 && php -q index.php" - "@every 2m" - ID: 1
    scheduler.go:45 ▶ NOTICE New job registered "autoprint-test2" - "cd /app/autoprint/test2 && php -q index.php" - "@every 2m" - ID: 2
    scheduler.go:56 ▶ DEBUG Starting scheduler
    cron_utils.go:13 ▶ DEBUG start
    cron_utils.go:13 ▶ DEBUG schedule
    cron_utils.go:13 ▶ DEBUG schedule
    scheduler.go:50 ▶ NOTICE Job deregistered (will not fire again) "autoprint-test1" - "cd /app/autoprint/test1 && php -q index.php" - "@every 2m" - ID: 1
    scheduler.go:50 ▶ NOTICE Job deregistered (will not fire again) "autoprint-test2" - "cd /app/autoprint/test2 && php -q index.php" - "@every 2m" - ID: 2
    cron_utils.go:13 ▶ DEBUG removed
    cron_utils.go:13 ▶ DEBUG removed
    
    / # cat /tmp/chadburn.conf 
    [global]
    save-folder = /etc/logs
    
    [job-exec "autoprint-test1"]
    schedule = @every 2m
    container = autoprint
    network = mybridge
    command = cd /app/autoprint/test1 && php -q index.php
    
    [job-exec "autoprint-test2"]
    schedule = @every 2m
    container = autoprint
    network = mybridge
    command = cd /app/autoprint/test2 && php -q index.php
    
    / # ping autoprint
    PING autoprint (172.19.0.4): 56 data bytes
    64 bytes from 172.19.0.4: seq=0 ttl=64 time=0.112 ms
    64 bytes from 172.19.0.4: seq=1 ttl=64 time=0.075 ms
    ^C
    --- autoprint ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max = 0.075/0.093/0.112 ms
    
  • Chadburn is not picking up any tasks

    Chadburn is not picking up any tasks

    Setup:

    docker-compose chadburn:

    version: "3"
    services:
      chadburn:
        image: premoweb/chadburn:latest
        container_name: chadburn
        restart: always
        command: daemon
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
    
        networks:
          - traefik
    
    networks:
      traefik:
        external:
          name: traefik-network
    

    docker-compose influxdb

    version: '3.7'
    
    services:
      influxdb:
        image: arm64v8/influxdb:2.2
        container_name: influxdb
        restart: always
        labels:
          chadburn.enabled: true
          chadburn.job-exec.backup-influxdb.schedule: "38 8 * * *"
          chadburn.job-exec.backup-influxdb.command: "/backup/backup.sh"
    [....]
    

    docker inspect of the container

    ❯ docker inspect influxdb | jq ".[].Config.Labels"
    {
      "chadburn.enabled": "True",
      "chadburn.job-exec.backup-influxdb.command": "/backup/backup.sh",
      "chadburn.job-exec.backup-influxdb.schedule": "38 8 * * *",
      "com.docker.compose.config-hash": "5e307b1e77c4fd6682759977b4a9472868ed6d75fd76d30a7492bc328eb5c14d",
      "com.docker.compose.container-number": "1",
      "com.docker.compose.oneoff": "False",
      "com.docker.compose.project": "influxdb2",
      "com.docker.compose.project.config_files": "docker-compose.yaml",
      "com.docker.compose.project.working_dir": "/opt/influxdb2",
      "com.docker.compose.service": "influxdb",
      "com.docker.compose.version": "1.29.2"
    }
    

    Logs of chadburn

    Attaching to chadburn
    chadburn    | daemon.go:47 ▶ DEBUG Config file: /etc/chadburn.conf not found
    chadburn    | scheduler.go:101 ▶ DEBUG Starting scheduler
    chadburn    | cron_utils.go:13 ▶ DEBUG start
    

    Do I miss something?

  • Dockerhub Tags

    Dockerhub Tags

    Could you tag the docker images with version and hashes please?

    In reference to #9 since there is only a latest tag we can't pull the v1.0.0 release to get docker label detection working again.

    it also makes for following a practice of running containers are a specific version to avoid auto-upgrades.

  • Detection of service label updates/changes (Broken / Re-write in progress)

    Detection of service label updates/changes (Broken / Re-write in progress)

    Today was really fced up.

    Tried to incorporate the changes from Ofelia, thinking they finally got around to accepting the pull request. I didn't verify this before bringing all the changes over. As a result, v1.0.1 fully breaks the ability to automatically see service label changes. You will need to pull v1.0.0 and build it yourself until this is fixed.

    We're back to operating in a world of restarting the scheduler.

    Hey @rdelcorro, when did you make your changes? I am trying to reverse engineer their changes and mix in your code changes to see if I can hammer out a quick repair.

    Spending my day tomorrow (Christmas day) working on this.

  • Known memory leak issue possible.

    Known memory leak issue possible.

    As maintainer of this Chadburn fork of Ofelia, I am concerned about the problem of memory leaks for at least some users.

    mcuadros/ofelia#107

    Thank you @helmut72 for raising this issue over at the Ofelia project. I'm tracking it here as well.

    A feature request to switch to Chadburn has been raised but another question was raised about the known memory leak issue. See:
    mailcow/mailcow-dockerized#4362

    I am creating this issue for others who may have come across this problem in Chadburn. Since this was raised with Ofelia project, the focus should remain there, however this issue will get updated when I or others discover relevant updates addressing the problem.

  • Soon to be chadburn.app website currently inaccessable.

    Soon to be chadburn.app website currently inaccessable.

    Just a heads up for anyone trying to reach the https://chadburn.app address for the future website, it's currently not accessible to many due to ongoing DNS-over-http infrastructure attacks across the United States.

    I don't have much more information other than you may notice this also affects any .google, .dev and any other specialty "SSL Required" type domains.

  • Mail notifications fail with unknown certificate

    Mail notifications fail with unknown certificate

    We using custom CA on our SMTP server and we get following error. mail.go:57 ▶ ERROR Mail error: "x509: certificate signed by unknown authority"

    Any idea how to fix it?

  • Reconsider name

    Reconsider name

    While Chronos is an amazing name, it's already in use by a well known cron repoacement: https://github.com/mesos/chronos

    TikTok eould also work but also taken 😅

  • overriding job defaults possible?

    overriding job defaults possible?

    Hi,

    I am wondering if it's possible to override default job parameter values?

    My use case is for setting the user or no-overlap on job-exec once per container vs having to specify it for every job, i.e.

        labels:
          chadburn.enabled: "true"
          
          # test task
          chadburn.job-exec.test-job.schedule: '@every 1h'
          chadburn.job-exec.test-job.command: 'bash -lc "python -u -m test_task'
          chadburn.job-exec.test-job.no-overlap: 'true'
          chadburn.job-exec.test-job.user: "non-root"
    
          # different test task
          chadburn.job-exec.test-job-2.schedule: '@every 2h'
          chadburn.job-exec.test-job-2.command: 'bash -lc "python -u -m test_task_2'
          chadburn.job-exec.test-job-2.no-overlap: 'true'
          chadburn.job-exec.test-job-2.user: "non-root"
    

    and im wondering If something like below can be achieved?

        labels:
          chadburn.enabled: "true"
          chadburn.default.job-exec.user: "non-root"
          chadburn.default.job-exec.no-overlap: "true"
          
          # test task
          chadburn.job-exec.test-job.schedule: '@every 1h'
          chadburn.job-exec.test-job.command: 'bash -lc "python -u -m test_task'
    
          # different test task
          chadburn.job-exec.test-job-2.schedule: '@every 2h'
          chadburn.job-exec.test-job-2.command: 'bash -lc "python -u -m test_task_2'
    

    thanks!

  • How to remove previous jobs?

    How to remove previous jobs?

    Discussed in https://github.com/PremoWeb/chadburn/discussions/33

    Originally posted by Turab August 26, 2022 Hi,

    Using Caprover overrides to register jobs and it works. However, when I change the name of the job an save; I get two jobs. Means the old job still stays there. How can I remove the jobs?

    Btw, I have my instance complaining that there isn't a config file; which there really isn't. I am running Chadburn from single-click app in Caprover.

  • Static only config without docker socket

    Static only config without docker socket

    Add support to run chadburn with static config and without docker socket

    Currently it breaks with:

    daemon.go:46 ▶ CRITICAL Can't start the app: Get "http://unix.sock/info": dial unix /var/run/docker.sock: connect: no such file or directory
    
  • job service ignores entrypoint

    job service ignores entrypoint

    The command parameter should be applied as arguments in a service but it appears to be replacing entrypoint.

    Also it would be nice to have a configuration entrypoint to explicitly override entrypoint

  • Does not give notice when there's an error on INI and INI does not support multiple lines.

    Does not give notice when there's an error on INI and INI does not support multiple lines.

    My INI file. All I did was put new lines in the command. On the upstream it gives an error saying that that string is not terminated which doesn't appear to be true. but on the fork it does not even show an error message.

    [global]
    
    [job-service-run "Do a job at CA1"]
    schedule = @every 10s
    image = fullstorydev/grpcurl:latest
    delete = false
    
    command = """
      grpcurl --plaintext -d {'name':'foo'} ca1:6565 rpc.Greeter/SayHello
    """
    

    Docker compose

    version: "3.7"
    services:
      scheduler:
        image: ghcr.io/premoweb/chadburn:latest
        command: daemon --config=/jobs.ini
        deploy:
          resources:
            limits:
              memory: 256M
          placement:
            constraints:
              - "node.role == manager"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
        configs:
          - source: jobs
            target: /jobs.ini
            mode: 0600
    configs:
      jobs:
        file: ./example.ini
    
Statefulset-scheduler (aka sfs-scheduler)

statefulset-scheduler (aka sfs-scheduler) Installation I already upload docker i

Dec 19, 2021
Scheduler: the scheduler of distbuild written in Golang

scheduler Introduction scheduler is the scheduler of distbuild written in Go. Pr

Feb 9, 2022
Scheduler - Scheduler package is a zero-dependency scheduling library for Go

Scheduler Scheduler package is a zero-dependency scheduling library for Go Insta

Jan 14, 2022
Linstor-scheduler-extender - LINSTOR scheduler extender plugin for Kubernetes

linstor-scheduler-extender LINSTOR scheduler extender plugin for Kubernetes whic

Dec 30, 2022
Crane scheduler is a Kubernetes scheduler which can schedule pod based on actual node load.

Crane-scheduler Overview Crane-scheduler is a collection of scheduler plugins based on scheduler framework, including: Dynamic scheuler: a load-aware

Dec 29, 2022
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

Dec 17, 2022
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.

Dec 8, 2022
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

Dec 30, 2022
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

Jan 8, 2023
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

Dec 20, 2022
a cron library for go

cron Cron V3 has been released! To download the specific tagged release, run: go get github.com/robfig/cron/[email protected] Import it in your program as: im

Dec 25, 2022
分布式定时任务库 distributed-cron
分布式定时任务库 distributed-cron

dcron 分布式定时任务库 原理 基于redis同步节点数据,模拟服务注册。然后将任务名 根据一致性hash 选举出执行该任务的节点。 流程图 特性 负载均衡:根据任务数据和节点数据均衡分发任务。 无缝扩容:如果任务节点负载过大,直接启动新的服务器后部分任务会自动迁移至新服务实现无缝扩容。

Dec 29, 2022
基于 Redis 和 Cron 的定时任务队列

RTask RTask 是 Golang 一款基于 Redis 和 Cron 的定时任务队列。 快速上手 您需要使用 Go Module 导入 RTask 工具包。 go get -u github.com/avtion/rtask 使用教程 package main import ( "con

Oct 27, 2021
A cron-like strategy plugin for HashiCorp Nomad Autoscaler

Nomad Autoscaler Cron Strategy A cron-like strategy plugin, where task groups are scaled based on a predefined scheduled. job "webapp" { ... group

Feb 14, 2022
Go-based runner for Cron Control

Cron Control Runner A Go-based runner for processing WordPress cron events, via Cron Control interfaces. Installation & Usage Clone the repo, and cd i

Jul 19, 2022
This package provides the way to get the previous timestamp or the next timestamp that satisfies the cron expression.

Cron expression parser Given a cron expression, you can get the previous timestamp or the next timestamp that satisfies the cron expression. I have us

May 3, 2022
Graceful shutdown with repeating "cron" jobs (running at a regular interval) in Go

Graceful shutdown with repeating "cron" jobs (running at a regular interval) in Go Illustrates how to implement the following in Go: run functions ("j

May 30, 2022
Zdpgo cron - 在golang中使用cron表达式并实现定时任务

zdpgo_cron 在golang中使用cron表达式并实现定时任务 项目地址:https://github.com/zhangdapeng520/zdpgo

Feb 16, 2022
Cloud-native, enterprise-level cron job platform for Kubernetes
Cloud-native, enterprise-level cron job platform for Kubernetes

Furiko Furiko is a cloud-native, enterprise-level cron and adhoc job platform for Kubernetes. The main website for documentation and updates is hosted

Dec 30, 2022