Davide Polato created TIKA-4804:
-----------------------------------

             Summary:  tika-grpc: fetchAndParseServerSideStreaming never sends 
a terminal signal
                 Key: TIKA-4804
                 URL: https://issues.apache.org/jira/browse/TIKA-4804
             Project: Tika
          Issue Type: Bug
          Components: tika-pipes
    Affects Versions: 3.0.0, 4.0.0
            Reporter: Davide Polato
         Attachments: TerminalSignalLocalDiagnostic.java

h3. Summary

{{TikaGrpc.fetchAndParseServerSideStreaming}} delivers its reply and then never
closes the call. This happens on the success path, not only on error. gRPC does
not close a call when the handler returns: for a server-streaming method the
server must call {{onCompleted()}}, and this handler never does.

The client sees one message and then waits until its deadline, or forever if it
set none. Each call also leaves server-side call state alive.

h3. Where

{{TikaGrpcServerImpl.fetchAndParseServerSideStreaming}} calls
{{fetchAndParseImpl}} and returns. {{fetchAndParseImpl}} calls only
{{onNext(...)}}.

For contrast, in the same class:
* unary {{fetchAndParse}} calls {{fetchAndParseImpl}} and then 
{{onCompleted()}} -- correct
* {{fetchAndParseBiDirectionalStreaming}} forwards the client's {{onCompleted}} 
-- correct

Only the server-streaming variant is missing the terminal signal.

h3. Affected versions

Present in every released version that ships tika-grpc: 3.0.0, 3.0.0-BETA2,
3.1.0, 3.2.0, 3.2.1, 3.2.2, 3.2.3, 3.3.0, 3.3.1, 3.3.2, and the 4.0.0 alpha and
beta tags. The handler has had this shape since the RPC was introduced.

h3. Reproduction

Attached: TerminalSignalLocalDiagnostic.java. Drop it into
tika-grpc/src/test/java/org/apache/tika/pipes/grpc/ and run

{noformat}
mvn -pl tika-grpc test -Dtest=TerminalSignalLocalDiagnostic
{noformat}

It fetches one real file through an in-process server with an async stub and
waits up to 10 seconds for a terminal signal on four RPCs:

{noformat}
v1 fetchAndParse (unary)                messages=1  terminal=YES  onCompleted
v1 fetchAndParseServerSideStreaming     messages=1  terminal=NO -- HUNG
v2 fetchAndParse (unary)                messages=1  terminal=YES  onCompleted
v2 fetchAndParseServerSideStreaming     messages=1  terminal=NO -- HUNG
sanity fetch status = PARSE_SUCCESS
{noformat}

The test then fails in GrpcCleanupExtension with

{noformat}
PostconditionViolationException: One or more Resources couldn't be released
{noformat}

because those two calls are still open. That failure is part of the finding, not
noise: two independent signals, one cause.

h3. Scope notes

* Measured against 4.0.0-SNAPSHOT. The 3.x handlers are structurally identical,
  so the same result is expected there, but I have not executed the probe 
against
  a 3.x build.
* The v2 experimental service (TIKA-4766) inherits the shape from v1. Fixing v1
  does not automatically fix v2; both need the terminal signal.
* Found while working on TIKA-4795. Unrelated to that ticket's feature and
  independent of it.

h3. Fix

One line per handler: call {{responseObserver.onCompleted()}} after
{{fetchAndParseImpl}}, matching what the unary handler already does. Happy to
put up a patch with a regression test if that is wanted -- the probe above turns
into one directly.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to