debounce is a simple utility to limit the rate at which a command can fire.
I've written a blog post on
the motivation behind this tool.
The command format is:
debounce <integer> <unit> <command>Available units are:
- seconds (s)
- minutes (m)
- hours (h)
- days (d)
The following are equivalent:
debounce 1 s some-command
debounce 1 second some-command
debounce 1 seconds some-commanddebounce 1 m some-command
debounce 1 minute some-command
debounce 1 minutes some-commanddebounce 1 h some-command
debounce 1 hour some-command
debounce 1 hours some-commanddebounce 1 d some-command
debounce 1 day some-command
debounce 1 days some-commandNote that day is shorthand for 24 hours. Daylight Saving Time is not taken
into account.
Choose from the following options to install debounce.
go install github.com/oalders/debounce@latestor for a specific version:
go install github.com/oalders/debounce@v0.5.2You can use ubi to install debounce.
#!/usr/bin/env bash
set -eux -o pipefail
# Choose a directory in your $PATH
dir="$HOME/local/bin"
if [ ! "$(command -v ubi)" ]; then
curl --silent --location \
https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh |
TARGET=$dir sh
fi
ubi --project oalders/debounce --in "$dir"You can download the latest release directly from here.
This runs the command without any parameters but prevents repeated execution within the set time window.
$ debounce 2 seconds date
Mon Aug 5 23:09:09 EDT 2024
$ debounce 2 seconds date
π₯ will not run date more than once every 2 secondsThis example uses ubi to install is into the current directory. The command won't be executed more than once every 8 hours.
$ debounce 8 hours ubi --verbose --project oalders/is --in .
[ubi::installer][INFO] Installed binary into ./is
$ debounce 8 hours ubi --verbose --project oalders/is --in .
π₯ will not run "ubi --verbose --project oalders/is --in ." more than once every 8 hoursRemember to single quote variables which shouldn't be expanded until the command is run.
debounce 10 s zsh -c 'echo $PWD'You can use && and || in your commands. You'll want to quote your command to
ensure that the entire command is passed to debounce.
debounce 2 s bash -c 'sleep 2 && date'It's important to add debounce flags before other command arguments to avoid
confusion between debounce flags and flags meant for your command.
Good: β
debounce --debug 90 s curl https://www.olafalders.comBad: π₯
$ debounce 90 s curl https://www.prettygoodping.com --debug
π Running command: curl https://www.prettygoodping.com --debug
curl: option --debug: is unknownYou could be explicit about this by using -- as a visual indicator that flag
parsing has ended.
debounce --debug 90 s -- curl https://www.prettygoodping.comSpecify an alternate cache directory to use. The directory must already exist.
debounce --cache-dir /tmp 30 s dateThe --local flag modifies the behavior of debounce by including the full
path to the current working directory in the cache key. This ensures that the
cache is specific to the directory from which the command is run.
By default, debounce works globally. It generates a cache key based on the
command and its arguments. This means that if you run the same command from
different directories, debounce will treat them as the same command and use
the same cache file. This can be useful if you want to limit the execution of a
command globally, regardless of the directory.
With the --local flag, debounce includes the full path to the current
working directory in the cache key. This means that the cache is specific to the
directory from which the command is run. If you run the same command from
different directories, debounce will treat them as different commands and use
separate cache files. This is useful if you want to limit the execution of a
command on a per-directory basis.
# Run a command without the --local flag
debounce 10 s echo "Hello, World!"
# Run the same command again within 10 seconds
debounce 10 s echo "Hello, World!"
# Output: π₯ will not run "echo Hello, World!" more than once every 10 seconds
# Run a command with the --local flag
debounce --local 10 s echo "Hello, Local World!"
# Run the same command again within 10 seconds from the same directory
debounce --local 10 s echo "Hello, Local World!"
# Output: π₯ will not run "echo Hello, Local World!" more than once every 10 seconds
# Run the same command from a different directory
cd /another/directory
debounce --local 10 s echo "Hello, Local World!"
# Output: Hello, Local World!Print debounce status information for a command.
debounce --status 30 s date
π cache location: /Users/olaf/.cache/debounce/0e87632cd46bd4907c516317eb6d81fe0f921a23c7643018f21292894b470681
π§ cache last modified: Thu, 19 Sep 2024 08:28:20 EDT
β²οΈ debounce interval: 00:00:30
π°οΈ cache age: 00:00:12
β³ time remaining: 00:00:17Since the cache is just a file, you can rm the cache location file whenever
you'd like to start fresh.
rm /Users/olaf/.cache/debounce/0e87632cd46bd4907c516317eb6d81fe0f921a23c7643018f21292894b470681Prints current version.
debounce --version
0.5.2Displays usage instructions.
debounce --help
Usage: debounce <quantity> <unit> <command> ... [flags]
limit the rate at which a command can fire
Arguments:
<quantity> Quantity of time
<unit> s,second,seconds,m,minute,minutes,h,hour,hours,d,day,days
<command> ... Command to run
Flags:
-h, --help Show context-sensitive help.
--debug Print debugging info to screen
--version Print version to screen
--status Print cache information for a command without running it
--local Localize debounce to current working directory
--cache-dir=STRING Override the default cache directory
Under the hood, debounce creates or updates a cache file to track when a
command was run successfully. This means that, under the right conditions, it's
entirely possible to kick off two long-running tasks in parallel without
debounce knowing about it.
Additionally, if a command fails, the cache file will not be created or updated.
I've created this tool in a way that meets my needs. I will consider pull requests for additional functionality to address issues like these. Please get in touch with me first to discuss your feature if you'd like to add something.