Commit 1c35867
authored
feat: honor the FDv1 fallback directive on success, error, and goodbye (#312)
Stacked on #311 (the `SseHttpError` surfacing this depends on).
## What
Honors the FDv1 fallback directive across every way the server can
deliver it:
- **Successful connection:** the directive is emitted with the basis
change set, so the streamed payload is applied *before* the SDK falls
back — previously the basis was dropped the moment the header was seen.
- **Any error response carrying the header** (`SseHttpError`,
recoverable or not): the streaming source closes the connection — which
stops the client's own retry — and routes to the fallback tier.
- **`goodbye` event with `protocolFallbackTTL`:** treated as an in-band
fallback directive, for transports that cannot read response headers.
A single helper parses the directive (presence + TTL) from response
headers, used for both the successful and error paths; the goodbye path
reads its TTL in-band.
The streaming source maps `SseHttpError` by its `recoverable` flag:
recoverable → interrupted (the client retries), unrecoverable →
terminal. The FDv1 streaming source ignores recoverable errors so a
transient 5xx no longer shuts it down.
When a fallback tier is configured the orchestrator engages it. When
none is configured, the SDK stays interrupted and retries FDv2 after the
directive's TTL (default 1 hour; a TTL of `0` means remain paused with
no retry) rather than halting or reconnecting immediately. Source
results carry the fallback TTL.
## Tests
- Orchestrator: apply-then-engage from a directive-bearing change set,
and the three no-fallback cases (finite TTL retries, absent TTL defers,
zero TTL pauses).
- `streaming_base`: defer-on-success, the TTL header, the goodbye/TTL
directive, and the `SseHttpError` paths (recoverable → interrupted/stays
open, unrecoverable → terminal/closes, directive → terminal+TTL
regardless of recoverability). `protocol_handler` covers
`protocolFallbackTTL` parsing.
- v3 contract harness `fdv1-fallback` suite passes end-to-end (816
total, 792 ran, exit 0), with no regression.
The contract-test-service capability + `fdv1Fallback` config wiring that
exercises this in the harness lives on the e2e branch and will land with
the v3 contract-tests PR.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes core FDv2 connection lifecycle, tier selection, and flag
delivery ordering when servers send fallback signals; behavior shifts
are broad but covered by new unit/contract tests.
>
> **Overview**
> Implements end-to-end handling when the server asks the SDK to fall
back from FDv2 to FDv1, including **TTL-aware retry** when no FDv1 tier
is configured.
>
> **Directive parsing and propagation:** Adds shared
`readFallbackDirective` for `x-ld-fd-fallback` / `x-ld-fd-fallback-ttl`,
threads `fdv1FallbackTtl` through `FDv2SourceResult`, and parses in-band
`protocolFallbackTTL` on goodbye events.
>
> **Streaming / polling behavior:** On a **successful** stream open, the
directive is **deferred** and emitted with the next change set so the
basis payload is applied before fallback (replacing immediate terminal
error on connect). **HTTP errors** with the header, and **goodbye** with
TTL or a pending header, surface as terminal fallback results so the
orchestrator does not recycle past the directive. Polling mirrors
goodbye/header TTL stamping. FDv2 streaming maps `SseHttpError` by
recoverability; legacy FDv1 streaming **ignores recoverable** SSE HTTP
errors so transient 5xx no longer shuts the source down.
>
> **Orchestrator:** Classifies directives into engage FDv1 tier, defer
retry (no tier: wait TTL—default 1h, zero = pause indefinitely), or
none; schedules recycle via `_pendingRetryDelay` and interruptible
`_delay` on stop.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
74e7c4b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 0707b60 commit 1c35867
12 files changed
Lines changed: 688 additions & 92 deletions
File tree
- packages/common_client
- lib/src/data_sources
- fdv2
- test/data_sources/fdv2
Lines changed: 20 additions & 0 deletions
| 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 | + | |
Lines changed: 110 additions & 32 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
37 | 51 | | |
38 | 52 | | |
39 | 53 | | |
| |||
64 | 78 | | |
65 | 79 | | |
66 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
67 | 93 | | |
68 | 94 | | |
69 | 95 | | |
| |||
117 | 143 | | |
118 | 144 | | |
119 | 145 | | |
| 146 | + | |
120 | 147 | | |
121 | 148 | | |
122 | 149 | | |
| |||
190 | 217 | | |
191 | 218 | | |
192 | 219 | | |
193 | | - | |
194 | | - | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
195 | 223 | | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | | - | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
201 | 233 | | |
202 | 234 | | |
203 | 235 | | |
204 | | - | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
205 | 252 | | |
206 | | - | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
207 | 259 | | |
208 | 260 | | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
209 | 266 | | |
210 | 267 | | |
211 | 268 | | |
| |||
225 | 282 | | |
226 | 283 | | |
227 | 284 | | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
241 | 305 | | |
242 | 306 | | |
243 | 307 | | |
| |||
253 | 317 | | |
254 | 318 | | |
255 | 319 | | |
256 | | - | |
| 320 | + | |
| 321 | + | |
257 | 322 | | |
258 | 323 | | |
259 | 324 | | |
| |||
298 | 363 | | |
299 | 364 | | |
300 | 365 | | |
301 | | - | |
302 | | - | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
303 | 370 | | |
304 | 371 | | |
305 | 372 | | |
| |||
393 | 460 | | |
394 | 461 | | |
395 | 462 | | |
396 | | - | |
397 | | - | |
398 | | - | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
399 | 471 | | |
400 | | - | |
401 | | - | |
402 | 472 | | |
403 | 473 | | |
404 | 474 | | |
| |||
421 | 491 | | |
422 | 492 | | |
423 | 493 | | |
424 | | - | |
425 | | - | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
426 | 504 | | |
427 | 505 | | |
428 | 506 | | |
| |||
Lines changed: 37 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
| |||
65 | 68 | | |
66 | 69 | | |
67 | 70 | | |
68 | | - | |
69 | | - | |
70 | | - | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
71 | 74 | | |
72 | 75 | | |
73 | 76 | | |
| |||
78 | 81 | | |
79 | 82 | | |
80 | 83 | | |
| 84 | + | |
81 | 85 | | |
82 | 86 | | |
83 | 87 | | |
| |||
89 | 93 | | |
90 | 94 | | |
91 | 95 | | |
| 96 | + | |
92 | 97 | | |
93 | 98 | | |
94 | 99 | | |
95 | 100 | | |
96 | 101 | | |
97 | 102 | | |
98 | 103 | | |
| 104 | + | |
99 | 105 | | |
100 | 106 | | |
101 | 107 | | |
102 | 108 | | |
103 | 109 | | |
104 | 110 | | |
105 | 111 | | |
| 112 | + | |
106 | 113 | | |
107 | 114 | | |
108 | 115 | | |
109 | 116 | | |
110 | 117 | | |
111 | 118 | | |
112 | 119 | | |
| 120 | + | |
113 | 121 | | |
114 | 122 | | |
115 | 123 | | |
| |||
122 | 130 | | |
123 | 131 | | |
124 | 132 | | |
| 133 | + | |
125 | 134 | | |
126 | 135 | | |
127 | 136 | | |
| |||
145 | 154 | | |
146 | 155 | | |
147 | 156 | | |
| 157 | + | |
148 | 158 | | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
154 | 173 | | |
155 | 174 | | |
156 | 175 | | |
157 | 176 | | |
| 177 | + | |
158 | 178 | | |
159 | 179 | | |
160 | 180 | | |
161 | 181 | | |
162 | 182 | | |
| 183 | + | |
163 | 184 | | |
164 | 185 | | |
165 | 186 | | |
| |||
175 | 196 | | |
176 | 197 | | |
177 | 198 | | |
| 199 | + | |
178 | 200 | | |
179 | 201 | | |
180 | 202 | | |
| |||
187 | 209 | | |
188 | 210 | | |
189 | 211 | | |
| 212 | + | |
190 | 213 | | |
191 | 214 | | |
192 | 215 | | |
| |||
0 commit comments