You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: index.html
+33-4Lines changed: 33 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -1028,18 +1028,47 @@ <h2 id="errors">Errors<a class="headerlink" href="#errors" title="Permanent link
1028
1028
<ul>
1029
1029
<li><strong>Status errors</strong> (4xx/5xx responses) — raised automatically, no <code>raise_for_status()</code> needed: <code>NotFoundError</code>, <code>RateLimitedError</code>, <code>ServiceUnavailableError</code>, and the rest. All subclass <code>StatusError</code>.</li>
1030
1030
<li><strong>Transport errors</strong> — connection / network / protocol failures before a response arrived. <code>NetworkError</code> (transient) subclasses <code>TransportError</code>.</li>
1031
-
<li><strong>Resilience refusals</strong> — <code>RetryBudgetExhaustedError</code>and <code>BulkheadFullError</code>, raised by the resilience middleware.</li>
1031
+
<li><strong>Resilience refusals</strong> — <code>RetryBudgetExhaustedError</code>, <code>BulkheadFullError</code>, and <code>CircuitOpenError</code>, raised by the resilience middleware.</li>
1032
1032
<li><strong>Decode errors</strong> — <code>DecodeError</code>, raised when <code>response_model=</code> decoding fails (HTTP call itself succeeded). <code>MissingDecoderError</code>, raised when no registered decoder claims the <code>response_model=</code> type — fires <em>before</em> the HTTP call.</li>
1033
1033
</ul>
1034
1034
<p>See the <ahref="errors/">Errors reference</a> for the full tree and catching strategies.</p>
<p><code>AsyncRetry</code>/<code>Retry</code> and <code>AsyncBulkhead</code>/<code>Bulkhead</code> emit operational events via two channels — stdlib <code>logging</code> records (always on) and OpenTelemetry span events (when <code>opentelemetry-api</code> is installed). Event names and payloads are identical across sync and async; dashboards built against one class apply unchanged to the other.</p>
1037
-
<p>Logger names (<code>httpware.retry</code>, <code>httpware.bulkhead</code>) and event names (<code>retry.giving_up</code>, <code>retry.budget_refused</code>, <code>retry.streaming_refused</code>, <code>bulkhead.rejected</code>) are the stable public contract.</p>
1036
+
<p>All resilience middleware emit operational events via two channels — stdlib <code>logging</code> records (always on) and OpenTelemetry span events (when <code>opentelemetry-api</code> is installed). Event names and payloads are identical across sync and async; dashboards built against one class apply unchanged to the other.</p>
1037
+
<p>Logger names and event names are the stable public contract:</p>
<p>Each log record carries an <code>event</code> field with the event-name string (e.g. <code>event="circuit.opened"</code>), usable for log-aggregator filtering. See <ahref="resilience/">resilience.md</a> for the full event tables per middleware.</p>
<aid="__codelineno-8-6" name="__codelineno-8-6" href="#__codelineno-8-6"></a><spanclass="n">logging</span><spanclass="o">.</span><spanclass="n">getLogger</span><spanclass="p">(</span><spanclass="s2">"httpware.circuit_breaker"</span><spanclass="p">)</span><spanclass="o">.</span><spanclass="n">setLevel</span><spanclass="p">(</span><spanclass="n">logging</span><spanclass="o">.</span><spanclass="n">INFO</span><spanclass="p">)</span><spanclass="c1"># INFO for recovery events</span>
<p>For a whole-attempt wall-clock bound, use <code>httpx2.Timeout</code> on the client or
1473
-
pass <code>timeout=</code> per request. <code>httpware</code> does not own a structured-cancellation
1474
-
timeout knob.</p>
1472
+
<p>For a whole-operation wall-clock bound across all retry attempts, compose <code>AsyncTimeout</code> outermost — see <ahref="#asynctimeout">AsyncTimeout</a> below. For a per-request bound, use <code>httpx2.Timeout</code> on the client or pass <code>timeout=</code> per request.</p>
<li><strong>CLOSED</strong> — normal operation. Each counted failure increments the consecutive-failure counter. Once <code>failure_threshold</code> consecutive counted failures accumulate, the circuit opens.</li>
1595
-
<li><strong>OPEN</strong> — fast-fail. All requests are rejected immediately with <code>CircuitOpenError</code> (carrying <code>retry_after</code> seconds until the next probe window). After <code>reset_timeout</code>seconds the circuit moves to HALF_OPEN.</li>
1593
+
<li><strong>OPEN</strong> — fast-fail. While elapsed time is below <code>reset_timeout</code>, requests are rejected immediately with <code>CircuitOpenError</code> (carrying <code>retry_after</code> seconds until the next probe window). The first request after <code>reset_timeout</code>elapses transitions the circuit to HALF_OPEN and becomes the probe.</li>
1596
1594
<li><strong>HALF_OPEN</strong> — exactly one probe is admitted. If <code>success_threshold</code> consecutive probe successes are observed, the circuit closes. A single probe failure re-opens the circuit.</li>
<p><code>Retry</code> uses <code>time.sleep</code> between attempts. <code>Retry-After</code>, streaming-body refusal, exhaustion behavior, and <code>RetryBudgetExhaustedError</code> semantics are identical to <code>AsyncRetry</code>.</p>
1810
-
<p>For a whole-attempt wall-clock bound, use <code>httpx2.Timeout</code> on the wrapped client or pass <code>timeout=</code> per request. <code>httpware</code>does not own a structured-cancellation timeout knob.</p>
1808
+
<p>For a whole-attempt wall-clock bound, use <code>httpx2.Timeout</code> on the wrapped client or pass <code>timeout=</code> per request. No sync <code>Timeout</code>middleware exists — sync Python has no cancellation primitive that can interrupt a blocking call mid-flight.</p>
0 commit comments