[ 
https://issues.apache.org/jira/browse/TIKA-4795?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18100952#comment-18100952
 ] 

Davide Polato commented on TIKA-4795:
-------------------------------------

[~tallison] [~krickert] there is a decision in here that I do not think should 
be mine.

h3. The bound on the branch does not actually do anything

PARSE_BYTES_MAX_BYTES is 64 MiB and the handler rejects anything bigger with 
RESOURCE_EXHAUSTED. But grpc-java's default maxInboundMessageSize is about 4 
MiB, so a 10 MB request never gets as far as that check. The transport refuses 
it first. The 64 MiB number is decoration.

It took me a while to notice because the tests use the in-process transport, 
which ignores the inbound limit entirely. Whatever we settle on needs at least 
one test against a real Netty server, otherwise we are only exercising a path 
no client ever takes.

There is a second limit above us that no configuration can move. Pipes frames 
are Smile-encoded, which measures at roughly 1.14x expansion on this payload 
shape, and PipesMessage.MAX_PAYLOAD_BYTES is 100 MiB checked when the frame is 
read. So an oversized frame does not fail politely in the server, it kills the 
worker. Usable content tops out somewhere near 87 MiB no matter what the 
transport is willing to accept.

h3. Why I am asking rather than picking one

maxInboundMessageSize is a per-server setting. Raising it for ParseBytes raises 
it for SaveFetcher, SavePipesIterator and the rest of the management surface, 
which only ever carry small JSON. That changes what the server will accept from 
anyone who can reach it, and it is not the sort of thing I want to slip in 
quietly inside a feature branch.

Three ways to go:

# Leave the default alone, and operators who want large ParseBytes payloads 
raise maxInboundMessageSize themselves. The server ships conservative. The cost 
is that ParseBytes is capped near 4 MiB out of the box, which is small for the 
crawler-shaped callers this ticket is aimed at.
# Raise the server default to 100 MB. ParseBytes then works without 
configuration and the code stays simple. The cost is that every other RPC now 
accepts 100 MB too.
# Raise the default to 100 MB and add a ServerInterceptor that puts the limit 
back near 4 MiB for every method except ParseBytes. Large payloads only where 
they are meant to be. The cost is another moving part, and one more thing to 
remember whenever a method is added.

I lean towards the third. It is the only one that gives ParseBytes room without 
also widening what the management RPCs will swallow, and an interceptor says 
the intent out loud instead of burying it in one global number. The second is 
defensible if the view is that a Tika gRPC server never faces untrusted 
callers, but that is a judgement about how people actually deploy this, and I 
would rather hear it from someone who has seen more deployments than I have.

h3. What has to happen either way

Right now the bound is validated in two places that answer with two different 
gRPC statuses, RESOURCE_EXHAUSTED in the v2 handler and INVALID_ARGUMENT 
further down. Only the first one is reachable today, but they should collapse 
into a single check with a single answer. The constant then needs to line up 
with whatever the real transport limit turns out to be and with the worker 
ceiling above it. Plus the real-transport test.

h3. This is what is keeping the ticket open

The bound is one of the two things this ticket says it needs. The other is 
cancellation. Aelled when the client disconnects, and with a shared 
PipesClient, interrupting one requestdisturbs the worker that is serving the 
others. That needs its own ticket and its own fix, and I have not started it.

So TIKA-4795 cannot close on what is on the branch today. Either both land, or 
we agree here to split cancellation out and say so on the ticket instead of 
leaving it implied.

The branch is at 
https://github.com/ai-pipestream/tika/tree/TIKA-4795-parseBytes. It sits on top 
of the TIKA-4766 branch from #2961, so it cannot be a pull request of its own 
until that one lands.

> ParseBytes: parse-only entrypoint for callers that already hold the document 
> bytes
> ----------------------------------------------------------------------------------
>
>                 Key: TIKA-4795
>                 URL: https://issues.apache.org/jira/browse/TIKA-4795
>             Project: Tika
>          Issue Type: New Feature
>          Components: tika-pipes
>    Affects Versions: 4.0.0
>            Reporter: Davide Polato
>            Priority: Major
>              Labels: grpc, pipes, protobuf
>
> h4. Goal
> Add a parse-only tika-grpc entrypoint that parses the exact bytes supplied by 
> the caller, without asking Tika to fetch or re-fetch the resource.
> This was split from the typed {{Document}} work in 
> [TIKA-4766|https://issues.apache.org/jira/browse/TIKA-4766] / [PR 
> #2961|https://github.com/apache/tika/pull/2961], whose description states 
> that "{{ParseBytes}} is deferred to its own JIRA."
> h4. Motivation
> {{FetchAndParse}} obtains content through a registered fetcher. Callers such 
> as web crawlers have already acquired the resource bytes. Requiring another 
> acquisition path can duplicate the transfer or parse a different 
> representation from the one the caller observed because of redirects, 
> cookies, authentication, robots and rate-limiting decisions, or transient 
> content.
> The parse result should correspond to the exact representation captured by 
> the caller.
> Apache StormCrawler is a concrete consumer. Its parsing bolts already receive 
> the acquired bytes together with URL and protocol metadata. StormCrawler can 
> contribute crawler requirements and input fixtures including truncated 
> payloads, declared-vs-actual charset mismatches, malformed archives, 
> documents containing embedded resources, HTML with {{<base>}}, and distinct 
> URLs with identical content.
> h4. Proposed observable behavior
> This issue defines observable behavior, not the internal buffering, fetcher, 
> or Pipes implementation.
> The request carries the exact byte sequence. It may also carry:
> * an optional opaque caller correlation id, echoed but never interpreted
> * source URI and effective URI when available, plus a base URI for link 
> resolution; these are provenance metadata and must never be dereferenced by 
> the service
> * resource name
> * declared media type and charset hints
> * optional declared content length and digest
> * a truncation flag
> Input must be bounded, and deadline or cancellation must terminate the 
> associated parse work.
> The reply reuses the typed {{Document}} contract introduced by #2961 rather 
> than defining a second parse-result model.
> The current direction discussed in #2961 is to place this on the experimental 
> v2 surface so that it does not gate the 4.0.0 release.
> h4. Open design decisions
> * bounded unary versus client streaming for the request bytes
> * exact service and package placement within v2
> * which provenance fields and parsing hints are necessary
> * whether and how caller-supplied length and digest are validated
> * maximum payload size and behavior for truncated payloads
> h4. Non-goals
> This issue does not define the structured content tree or its Markdown 
> projection, the embedded-document representation, extension payloads such as 
> {{google.protobuf.Any}}, or downstream NLP and embedding enrichment. Those 
> remain separate TIKA-4766 stages and follow-up issues.



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

Reply via email to