Commit 35adea4
fix(client-python): retry pipe open() on transient connect-refused (#2117)
* fix(client-python): retry pipe open() on transient connect-refused
A just-registered pipeline's per-pipe data listener can occasionally
still be binding when open() reaches it - under heavy concurrent load
(e.g. many pipelines opened at once) this surfaces as a transient
ECONNREFUSED ("Connect call failed") that is indistinguishable from a
real "pipeline isn't running" failure to the caller.
Retry a few times with a short backoff when the failure message
matches this specific transient pattern; any other failure still
raises immediately on the first attempt, so genuine errors (bad
token, wrong MIME type, terminated pipeline) are not masked or
delayed.
Surfaced by CI flakiness on unrelated PRs: the same
[Errno 111] Connect call failed error hit two different, unrelated
tests (nodes/test/guardrails/test_lane_forward_once.py and
nodes/test/test_dynamic.py) on consecutive runs, each on a different
ephemeral port - consistent with this race rather than a test bug.
* fix(client-python): address review — narrow retry, recalibrate, rebase fix
Nihal's review on #2117:
- Rebase onto develop needed a deliberate resolution: #2127 (merged after
this branch was cut) rewrote the same open() failure hunk to split the
server message from a `hint` field and add `code`. Keep that split; only
the retry loop wraps it now.
- The predicate also matched "Connection refused", which a misconfigured
`remote` node raises for a permanent failure the engine's inner connect
retry never runs for — retrying it only added latency. Narrow to the
actual race-condition signature, "Connect call failed".
- The retry budget undersold itself: the engine already retries this same
connect internally (10x, 150ms apart, ~1.5s worst case) before it reports
failure, so each SDK-level attempt re-runs that whole loop. Drop from 3
attempts to 2 (one retry) and document the ~3.2s worst case instead of
silently multiplying it further.
Also pins the rebase resolution with tests for the narrowed predicate and
the message/hint split, and updates the co-located SDK doc's retry note.
* fix(client-python): correct the documented pipe-open retry latency
CodeRabbit on #2117: the retry's added delay is the 0.25s SDK backoff plus
the engine's own ~1.5s internal connect-retry cycle, so ~1.75s - not the
~1.5s the docstring and doc claimed. Also reworded the doc's PipeException
description to "past that retry budget" rather than "genuinely could not be
opened" (the earlier module comment already gets this right).
* fix(client-python): guard pipe-open retry predicate against a non-string message
CodeRabbit on #2117: response.get('message') or '' passes through a truthy
non-string value (e.g. a malformed server response with an int message)
unchanged, so _is_transient_pipe_open_error()'s `'Connect call failed' in
message` raises TypeError before PipeException can even be raised. Coerce to
str right after extraction so the retry classification and the exception it
may raise both stay safe.
* fix(client-python): don't let a falsey non-string message fall back to generic
CodeRabbit on #2117: response.get('message') or '' runs before the
just-added isinstance check, so a real-but-falsey message like 0 or False
was already flattened to '' by the time it got there - PipeException then
showed the generic "Failed to open a data pipe." instead of the server's
actual value. Check for None explicitly instead of using `or`.
---------
Co-authored-by: madhumithachandrasekaran31 <madhumitha2110549@ssn.edu.in>1 parent 81f6338 commit 35adea4
3 files changed
Lines changed: 221 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
463 | 463 | | |
464 | 464 | | |
465 | 465 | | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
466 | 471 | | |
467 | 472 | | |
468 | 473 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
63 | 88 | | |
64 | 89 | | |
65 | 90 | | |
| |||
154 | 179 | | |
155 | 180 | | |
156 | 181 | | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
157 | 188 | | |
158 | 189 | | |
159 | 190 | | |
160 | 191 | | |
161 | 192 | | |
162 | | - | |
| 193 | + | |
| 194 | + | |
163 | 195 | | |
164 | 196 | | |
165 | 197 | | |
| |||
169 | 201 | | |
170 | 202 | | |
171 | 203 | | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
182 | 216 | | |
183 | | - | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
184 | 235 | | |
185 | | - | |
186 | 236 | | |
187 | 237 | | |
188 | 238 | | |
189 | 239 | | |
190 | | - | |
| 240 | + | |
191 | 241 | | |
192 | 242 | | |
193 | 243 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
0 commit comments