iTranslated by AI
I built a tool for exponential backoff in cron
Introduction
cron is very convenient for executing commands repeatedly.
* * * * * /path/to/the/command
Specifying it like this in crontab will execute it every minute.
*/3 * * * * /path/to/the/command
Specifying it like this will execute it every 3 minutes.
While it is very convenient, if command execution fails, it can result in redundant command runs. In cron, if a command continues to fail, emails will be repeatedly sent to the administrator.
You put a command into crontab to run every minute, confirm it starts correctly for the time being, finish your work, go home, have a beer, and just when you're thinking about going to bed, if the command starts failing, emails will keep flying until morning.
Also, if you've set up a cron job that calls a web service API and that service goes into maintenance, you might have issues. Calling an API that fails indefinitely despite being under maintenance might even lead to being banned.
The whole problem is that cron doesn't have an exponential backoff feature.
Solving it with systemd timer
You can achieve something close to exponential backoff by using systemd timers.
Thank you, moriwaka-san. However, things that have been operated with crontab until now are not easily migrated. (At least for me.)
I created a backoff command
Usage is simple. Just write backoff before the command in crontab.
* * * * * backoff /path/to/the/command
Just by writing this, the interval for the next startup will become longer when consecutive failures occur following a previous failure.
| Elapsed | Result | backoff |
|---|---|---|
| 0 min later | Success | |
| 1 min later | Success | |
| 2 min later | Failure | 1 min |
| 3 min later | Failure | 2 min |
| 4 min later | No execution | |
| 5 min later | Failure | 4 min |
| 7 min later | No execution | |
| 8 min later | No execution | |
| 9 min later | No execution | |
| 10 min later | Success | 0 min |
| 11 min later | Success | 0 min |
The mechanism is simple: this backoff command saves a leveldb database called .backoff in the current directory and increases the backoff value with each failure.
Usage of ./backoff:
-V verbose
-f string
storage file (default ".backoff")
-k string
key (default is command-line)
-max duration
max wait (default 1h0m0s)
-off duration
offset (default 1m0s)
-v show version
The directory for the .backoff directory can be changed. Also, while the above example is for every minute,
*/3 * * * * /path/to/the/command
In a case like this where it runs every 3 minutes, you would want it to increase as 3 minutes, 6 minutes, 9 minutes, and so on. In such cases, you can specify -off 3m.
*/3 * * * * backoff -off 3m /path/to/the/command
Furthermore, while the backoff increases steadily, you can also specify its maximum value. The default maximum is 1 hour, but specifying -max 0 allows it to keep increasing indefinitely.
Conclusion
I created the backoff command for those who find it difficult to move away from cron. It's still brand new, so there might be bugs. If you find any issues, please feel free to contribute.
Discussion