Commit ed8164e
Stream PDF from disk, s3 or zip files through memory (#124)
process_pdf could only read the document from disk, so callers holding a
PDF in memory - fetched from an API, read out of a database or an object
store - had to write it to a temporary file only for the client to open
it again.
It now takes the document itself as well: bytes, or any binary stream.
Nothing says which of the two it is; the object does. A document also
names itself, from the "name" attribute open() sets on files and that can
be set on anything else, io.BytesIO included, so the identity of a
document is not lost by going through memory - it travels with the
request and comes back with the result. Bytes on their own have nothing
to be named after and fall back to DEFAULT_IN_MEMORY_NAME.
A stream is read once, up front, and re-served from memory afterwards:
the 503 retry sends the same document again, and a consumed (or
non-seekable) stream would silently post an empty body the second time
around. That is also why the retry no longer recurses through the public
entry point, which would have had to re-derive a name from a source that
is by then exhausted.
process_documents processes several of them concurrently, through the
same ThreadPoolExecutor the file-based processing uses. Results come back
in input order rather than in completion order: in-memory documents have
no filenames to be matched back on afterwards, so the caller has nothing
but the order to zip them onto. A single PDF passed by mistake raises
instead of being iterated, which would otherwise send one request per
byte.
An in-memory run keeps up to n documents in flight against the server,
so a client concurrency above the server's engine pool only piles up
requests that queue there or come back as 503, while one below it
leaves engines idle. Neither is visible from the client side until the
throughput disappoints.
Before process_documents and the in-memory archive/s3 streaming start,
the client now asks /api/health how many engines the server has
(pool.maxActive) and logs a warning when n exceeds them - with the
number to use instead - and an info message when they outnumber n. The
check is advisory, not a gate: a server without the endpoint (older
GROBID), an unreadable answer or a connection failure never blocks the
run. A server answering ready: false is also surfaced as a warning.
Completes what #117 left pending on #67.
---------
Co-authored-by: Jan Göpfert <94385965+jangoepfert@users.noreply.github.com>1 parent a936d3c commit ed8164e
4 files changed
Lines changed: 991 additions & 45 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
| |||
188 | 189 | | |
189 | 190 | | |
190 | 191 | | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
195 | 196 | | |
196 | 197 | | |
197 | 198 | | |
198 | 199 | | |
199 | 200 | | |
200 | | - | |
| 201 | + | |
| 202 | + | |
201 | 203 | | |
202 | 204 | | |
203 | 205 | | |
| |||
289 | 291 | | |
290 | 292 | | |
291 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
292 | 351 | | |
293 | 352 | | |
294 | 353 | | |
| |||
0 commit comments