tballison commented on PR #3022:
URL: https://github.com/apache/tika/pull/3022#issuecomment-5293229947

   This is a really important fix, and you caught a subtle bug in PipesClient. 
Thank you.
   
   Human feedback: the backpressure we added to tika-server via 429 is a huge 
improvement to tika-server. What's the grpc native equivalent to 429 or is it 
proto specific?
   
   This is what my agent came up with. Let me know what you think.
   
   Thank you again.
   
   ```
   Ranked findings
   
     1. [HIGH — found independently by correctness + security, mechanism 
verified by me] Interrupt path omits markServerForRestart()
     PipesClient.java:229-238. This is the only closeConnection() call site in 
the file not paired with markServerForRestart() — the OOM, TIMEOUT, CRASH,
     SocketTimeout and backstop branches all pair them.
   
     In the default mode (useSharedServer=false): the orphaned forked JVM is 
still alive mid-parse, pendingRestart was never set, so ensureRunning() returns 
early
     treating it as healthy (PerClientServerManager.java:238). But that process 
already spent its one outbound connect and will never dial back, so connect() 
blocks
     the full hardcoded 60s on accept(), then throws 
ServerInitializationException — which maybeInit() rethrows without retry → 
FAILED_TO_INITIALIZE. Every 
     subsequent call on that pool slot repeats the 60s tax until the orphan 
dies on its own. With numClients=1 a single interrupted call degrades all 
traffic.
   
     This directly contradicts the fix's own comment: it removes a stale-ping 
stall and introduces a same-sized stale-accept stall.
   
     The fix is not a blind added line — in shared mode markServerForRestart() 
force-kills a server other clients are actively using. It needs to be 
mode-aware (e.g.
     a ServerManager method that PerClientServerManager implements as 
pendingRestart = true and SharedServerManager treats as a no-op, since its 
ConnectionHandler
     already handles abandoned connections via clientGone).
   
     2. [MEDIUM — 2 reviewers] The fix doesn't cover maybeInit()
     PipesClient.java:209-221 catches only 
ServerInitializationException/SecurityException. An interrupt during the 
reconnect backoff Thread.sleep() escapes
     process() entirely with connectionTuple pointing at a half-handshaked 
socket, which PipesParser's unconditional finally re-queues. Self-healing (next 
borrower's
     ping fails fast), but it's the same gap the PR set out to close.
   
     3. [MEDIUM — maintainer decision] Both new gRPC failure modes are 
invisible server-side
     Pool exhaustion returns CLIENT_UNAVAILABLE_WITHIN_MS with no log anywhere 
— compare PipesParsingHelper.java:344, which logs it and maps to HTTP 429 
specifically
     so alerting can tell "at capacity" from "worker crashing." Separately, 
fetchAndParseImpl:332 swallows InterruptedException with no onNext/onError; 
that's
     pre-existing, but the PR adds a brand-new 60s interruptible poll() that 
makes it materially more reachable. Server-streaming callers see a successfully
     completed empty stream; bidi callers silently lose one reply with no 
correlation id to notice.
   
     4. [LOW] Dead code the PR added
     closeConnection() declares throws InterruptedException but provably never 
throws it, so the new inner catch (InterruptedException e2) at :235-237 is
     unreachable.
   
     5. [LOW] Docs/CHANGES don't match behavior
     - CHANGES claims a pooled client "cannot go back to the queue dirty" — 
finding 1 contradicts this.
     - Undisclosed footprint change: 1 forked JVM → up to numClients 
(auto-capped at 4; 4 on any ≥10-core host). Zero mentions of numClients, 
concurrency or
     threading exist in tika-grpc/README.md or the grpc docs.
     - CLIENT_UNAVAILABLE_WITHIN_MS is newly reachable by gRPC clients and 
documented nowhere; the proto's status pointer (tika.proto:116) is stale
     (org.apache.tika.pipes.PipesResult.STATUS — real type is 
...pipes.api.PipesResult.RESULT_STATUS).
     - Worth a CHANGES line: this PR is also what makes useSharedServer=true 
take effect for tika-grpc for the first time — the old 2-arg constructor 
silently forced
     per-client mode.
   
     6. [LOW] Two comments describe past code states, against the repo's 
terseness rule — TikaGrpcServerImpl.java:124-125 ("...concurrent handler 
threads corrupt its
     protocol") and the 3-line block at PipesClient.java:230-232.
   
     7. [LOW] Shared-server mode untested at the gRPC layer — both new tests 
run per-client only. Mitigated: PipesParser shared-mode concurrency is covered 
by
     SharedServerModeTest/SharedServerChaosMonkeyTest.
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to