Commit 6e8b12e
committed
refactor: proposal — stash inline Arrow IPC, serve via /arrow-result
DRAFT proposal. Replaces the `arrow_inline` SSE message type from #256
with an out-of-band delivery mechanism. Motivation: remove the SSE
event-size cap as a constraint on inline Arrow result size.
Architecture
------------
ARROW_STREAM responses are now delivered uniformly:
1. The connector returns the base64 Arrow IPC attachment in
`result.attachment` for INLINE responses (unchanged from #256).
2. The analytics route base64-decodes it once, stashes the resulting
buffer in `InlineArrowStash` (bounded LRU + TTL), and emits the
same `{ type: "arrow", statement_id }` SSE message that
EXTERNAL_LINKS already uses — with a synthetic id prefixed
`inline-`.
3. The client (unchanged from main) calls `/arrow-result/:jobId` for
any `type: "arrow"` message.
4. The route handler checks the stash first; if the id has the
`inline-` prefix and is still present, it serves the bytes from
memory. Otherwise it falls through to the existing warehouse
fetch path for real EXTERNAL_LINKS statement_ids.
The `arrow_inline` SSE message type, the client-side base64 decode
helper, and the SSE buffer-size bumps from #256 all go away.
Reasoning
---------
SSE was designed for streams of small control messages. Pushing
multi-MB Arrow IPC bytes through it has two unavoidable costs:
- single-event memory ceiling on both server and client,
- proxy/load-balancer compatibility issues for large events.
Bumping the SSE buffer (5b in the design discussion) raises both
caps but doesn't fix the architectural mismatch. This PR moves bulk
bytes to HTTP, where they belong:
- HTTP/2 streaming, gzip, and browser background-fetch all work
naturally.
- SSE buffer can stay at the conservative 1 MiB default.
- The wire protocol unifies INLINE and EXTERNAL_LINKS — the client
has a single code path for ARROW_STREAM data.
- Inline result size cap goes back up to the Databricks API limit
(25 MiB) instead of being constrained by SSE.
Tradeoffs
---------
- Server holds IPC buffers in memory until the client fetches them
(one-shot `take()` removes on read; passive TTL evicts otherwise).
For 100 entries × 25 MiB worst case, that's 2.5 GiB peak — but
steady state is much smaller because entries are removed as soon
as the client fetches.
- Single-process only. A multi-server deployment would need a
shared store (Redis or equivalent) keyed on the synthetic id. The
stash interface is small enough to swap implementations.
- One-shot reads mean the client cannot retry a failed fetch.
Acceptable for our use case (warehouse query returned data, the
hook either succeeds in fetching or surfaces a generic error).
Status
------
DRAFT: opened to discuss the architectural direction before landing.
#256 ships with the simpler 5b SSE-buffer-bump approach (8 MiB) which
is sufficient for the realistic analytics range. This proposal is the
cleaner long-term solution if the team wants to invest in the
server-side state.
Co-authored-by: Isaac
Signed-off-by: James Broadhead <jamesbroadhead@gmail.com>1 parent aef9042 commit 6e8b12e
10 files changed
Lines changed: 296 additions & 125 deletions
File tree
- packages
- appkit-ui/src
- js/sse
- react/hooks
- __tests__
- appkit/src
- connectors/sql-warehouse
- tests
- plugins/analytics
- tests
- stream
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
| 21 | + | |
25 | 22 | | |
26 | 23 | | |
27 | 24 | | |
| |||
Lines changed: 27 additions & 55 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
34 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | 38 | | |
41 | 39 | | |
42 | 40 | | |
43 | 41 | | |
44 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
59 | 56 | | |
60 | 57 | | |
61 | | - | |
62 | | - | |
63 | | - | |
| 58 | + | |
64 | 59 | | |
65 | | - | |
| 60 | + | |
66 | 61 | | |
67 | 62 | | |
68 | 63 | | |
69 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
70 | 68 | | |
71 | 69 | | |
72 | 70 | | |
73 | | - | |
74 | | - | |
75 | | - | |
| 71 | + | |
76 | 72 | | |
77 | | - | |
| 73 | + | |
78 | 74 | | |
79 | 75 | | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
| 76 | + | |
| 77 | + | |
104 | 78 | | |
105 | | - | |
106 | 79 | | |
107 | | - | |
| 80 | + | |
108 | 81 | | |
109 | 82 | | |
110 | 83 | | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
| 84 | + | |
115 | 85 | | |
116 | 86 | | |
117 | 87 | | |
118 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
119 | 91 | | |
120 | | - | |
| 92 | + | |
121 | 93 | | |
122 | 94 | | |
Lines changed: 3 additions & 41 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | 25 | | |
36 | 26 | | |
37 | 27 | | |
| |||
139 | 129 | | |
140 | 130 | | |
141 | 131 | | |
142 | | - | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
143 | 135 | | |
144 | 136 | | |
145 | 137 | | |
| |||
161 | 153 | | |
162 | 154 | | |
163 | 155 | | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | 156 | | |
195 | 157 | | |
196 | 158 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
296 | | - | |
297 | | - | |
| 296 | + | |
| 297 | + | |
298 | 298 | | |
299 | 299 | | |
300 | 300 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
40 | 42 | | |
| 43 | + | |
41 | 44 | | |
42 | 45 | | |
43 | 46 | | |
| |||
76 | 79 | | |
77 | 80 | | |
78 | 81 | | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
79 | 100 | | |
80 | 101 | | |
81 | 102 | | |
| |||
247 | 268 | | |
248 | 269 | | |
249 | 270 | | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
254 | 276 | | |
255 | | - | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
256 | 280 | | |
257 | 281 | | |
258 | 282 | | |
| |||
Lines changed: 101 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 | + | |
| 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 | + | |
0 commit comments