Files
GopherGate/target/doc/tower/retry/budget/index.html
2026-02-26 12:00:21 -05:00

61 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="A retry “budget” for allowing only a certain amount of retries over time."><title>tower::retry::budget - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-ca0dd0c4.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="tower" data-themes="" data-resource-suffix="" data-rustdoc-version="1.93.1 (01f6ddf75 2026-02-11) (Arch Linux rust 1:1.93.1-1)" data-channel="1.93.1" data-search-js="search-9e2438ea.js" data-stringdex-js="stringdex-a3946164.js" data-settings-js="settings-c38705f0.js" ><script src="../../../static.files/storage-e2aeef58.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-a410ff4d.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-263c88ec.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">Module budget</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../tower/index.html">tower</a><span class="version">0.5.3</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module budget</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#why-budgets-and-not-max-retries" title="Why budgets and not max retries?">Why budgets and not max retries?</a></li><li><a href="#examples" title="Examples">Examples</a></li></ul><h3><a href="#reexports">Module Items</a></h3><ul class="block"><li><a href="#reexports" title="Re-exports">Re-exports</a></li><li><a href="#modules" title="Modules">Modules</a></li><li><a href="#traits" title="Traits">Traits</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In tower::<wbr>retry</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">tower</a>::<wbr><a href="../index.html">retry</a></div><h1>Module <span>budget</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/tower/retry/budget/mod.rs.html#1-90">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>A retry “budget” for allowing only a certain amount of retries over time.</p>
<h2 id="why-budgets-and-not-max-retries"><a class="doc-anchor" href="#why-budgets-and-not-max-retries">§</a>Why budgets and not max retries?</h2>
<p>The most common way of configuring retries is to specify a maximum
number of retry attempts to perform before giving up. This is a familiar idea to anyone
whos used a web browser: you try to load a webpage, and if it doesnt load, you try again.
If it still doesnt load, you try a third time. Finally you give up.</p>
<p>Unfortunately, there are at least two problems with configuring retries this way:</p>
<p><strong>Choosing the maximum number of retry attempts is a guessing game.</strong>
You need to pick a number thats high enough to make a difference when things are somewhat failing,
but not so high that it generates extra load on the system when its really failing. In practice,
you usually pick a maximum retry attempts number out of a hat (e.g. 3) and hope for the best.</p>
<p><strong>Systems configured this way are vulnerable to retry storms.</strong>
A retry storm begins when one service starts to experience a larger than normal failure rate.
This causes its clients to retry those failed requests. The extra load from the retries causes the
service to slow down further and fail more requests, triggering more retries. If each client is
configured to retry up to 3 times, this can quadruple the number of requests being sent! To make
matters even worse, if any of the clients clients are configured with retries, the number of retries
compounds multiplicatively and can turn a small number of errors into a self-inflicted denial of service attack.</p>
<p>Its generally dangerous to implement retries without some limiting factor. <a href="trait.Budget.html" title="trait tower::retry::budget::Budget"><code>Budget</code></a>s are that limit.</p>
<h2 id="examples"><a class="doc-anchor" href="#examples">§</a>Examples</h2>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::{future, sync::Arc};
<span class="kw">use </span>tower::retry::{budget::{Budget, TpsBudget}, Policy};
<span class="kw">type </span>Req = String;
<span class="kw">type </span>Res = String;
<span class="attr">#[derive(Clone, Debug)]
</span><span class="kw">struct </span>RetryPolicy {
budget: Arc&lt;TpsBudget&gt;,
}
<span class="kw">impl</span>&lt;E&gt; Policy&lt;Req, Res, E&gt; <span class="kw">for </span>RetryPolicy {
<span class="kw">type </span>Future = future::Ready&lt;()&gt;;
<span class="kw">fn </span>retry(<span class="kw-2">&amp;mut </span><span class="self">self</span>, req: <span class="kw-2">&amp;mut </span>Req, result: <span class="kw-2">&amp;mut </span><span class="prelude-ty">Result</span>&lt;Res, E&gt;) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>::Future&gt; {
<span class="kw">match </span>result {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<span class="comment">// Treat all `Response`s as success,
// so deposit budget and don't retry...
</span><span class="self">self</span>.budget.deposit();
<span class="prelude-val">None
</span>}
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; {
<span class="comment">// Treat all errors as failures...
// Withdraw the budget, don't retry if we overdrew.
</span><span class="kw">let </span>withdrew = <span class="self">self</span>.budget.withdraw();
<span class="kw">if </span>!withdrew {
<span class="kw">return </span><span class="prelude-val">None</span>;
}
<span class="comment">// Try again!
</span><span class="prelude-val">Some</span>(future::ready(()))
}
}
}
<span class="kw">fn </span>clone_request(<span class="kw-2">&amp;mut </span><span class="self">self</span>, req: <span class="kw-2">&amp;</span>Req) -&gt; <span class="prelude-ty">Option</span>&lt;Req&gt; {
<span class="prelude-val">Some</span>(req.clone())
}
}</code></pre></div></div></details><h2 id="reexports" class="section-header">Re-exports<a href="#reexports" class="anchor">§</a></h2><dl class="item-table reexports"><dt id="reexport.TpsBudget"><code>pub use tps_budget::<a class="struct" href="tps_budget/struct.TpsBudget.html" title="struct tower::retry::budget::tps_budget::TpsBudget">TpsBudget</a>;</code></dt></dl><h2 id="modules" class="section-header">Modules<a href="#modules" class="anchor">§</a></h2><dl class="item-table"><dt><a class="mod" href="tps_budget/index.html" title="mod tower::retry::budget::tps_budget">tps_<wbr>budget</a></dt><dd>Transactions Per Minute (Tps) Budget implementations</dd></dl><h2 id="traits" class="section-header">Traits<a href="#traits" class="anchor">§</a></h2><dl class="item-table"><dt><a class="trait" href="trait.Budget.html" title="trait tower::retry::budget::Budget">Budget</a></dt><dd>For more info about <a href="trait.Budget.html" title="trait tower::retry::budget::Budget"><code>Budget</code></a>, please see the <a href="index.html" title="mod tower::retry::budget">module-level documentation</a>.</dd></dl></section></div></main></body></html>