self-update-extras
Self-updating support for CLI binaries.
self-update-extras provides two small, composable wrappers around any type that
implements self_update's
ReleaseUpdate trait. Each wrapper is itself a ReleaseUpdate, so they layer
over a backend — or over each other — and can be used anywhere a
ReleaseUpdate is expected.
throttle::Update— limits how often update checks run, recording the time of the last check in a throttle file in the system temp directory.restart::Update— re-executes the process with the freshly installed binary after a successful update, using a guard environment variable to prevent restart loops.
The actual update source (GitHub, a custom server, etc.) is supplied by the
caller as any ReleaseUpdate implementation, e.g. one of self_update's
backends.
Installation
[]
= "0.1"
= "0.44"
Usage
Each wrapper follows self_update's builder convention: Update::configure()
returns an UpdateBuilder, and build() produces a
Box<dyn ReleaseUpdate>.
use ;
use github;
use ReleaseUpdate;
use Duration;
Composition order matters
Both wrappers can be used individually — you can wrap a backend with just
throttle::Update or just restart::Update without the other. But if you
use both, restart must always be the outermost layer:
backend → throttle → restart
On a successful update, restart replaces the current process (exec on
Unix) or spawns the new binary and exits (Windows) — in both cases the call
never returns on success. If throttle were the outer wrapper, its
"record the check time" step would never run because the process would already
have been replaced.
Wrappers
throttle::Update
Why: Update checks over the network waste bandwidth, battery, and server resources.
Without throttling, a user launching the same CLI multiple times in a short window
would hammer the update endpoint every single time. Many SaaS providers (GitHub,
GitLab, etc.) also enforce API rate limits — unthrottled checks can burn through
those quotas quickly, causing legitimate API calls to fail with 403 errors.
The throttle wrapper records the last check time and returns UpToDate immediately
when the configured window hasn't elapsed, avoiding unnecessary network calls and
protecting against rate-limit exhaustion.
| Builder method | Description |
|---|---|
release_update(Box<dyn ReleaseUpdate>) |
The wrapped updater. Required. |
throttle_window(Duration) |
Minimum interval between checks. Default: 15 minutes. |
build() |
Returns Result<Box<dyn ReleaseUpdate>>; errors if release_update is missing. |
When update() is called, the check is skipped (returning UpToDate) if the
throttle file was modified within throttle_window. Otherwise the wrapped
updater runs and the throttle file is touched. The file lives at
<temp_dir>/<bin_name>.throttle, where bin_name comes from the wrapped
updater.
restart::Update
Why: After installing a new binary, the old process image is still loaded in memory.
On Unix, calling exec replaces it in-place; on Windows, the caller must spawn the
new binary and exit. The restart wrapper handles this transparently, re-executing the
process with the same arguments so the user never has to manually re-launch.
Windows note: On Windows the wrapper spawns the new binary and exits the old one, so the original process ID is lost. If a parent process tracks your application by PID (e.g. a service manager or supervisor), it must be prepared to handle the PID disappearing and a new one appearing after an update.
| Builder method | Description |
|---|---|
release_update(Box<dyn ReleaseUpdate>) |
The wrapped updater. Required. |
guard_env(&str) |
Guard environment variable used to prevent restart loops. Default: RESTART_GUARD. |
build() |
Returns Result<Box<dyn ReleaseUpdate>>; errors if release_update is missing. |
When update() returns Updated, the process restarts into the freshly
installed binary, forwarding the original arguments and setting the guard
variable. On the re-executed run the guard is detected and the check is
skipped, so the update happens at most once per launch. Restart is supported
on both Unix (via exec) and Windows (spawn-and-exit, propagating the child's
exit code).
License
Apache-2.0 — see LICENSE for details.