StackOverflow error when processing cyclic indexed embedded with excludePaths
Description
This model in particular will trigger a StackOverflowError:
I will send a PR with a reproducer.
From what I can see this stems from the fact that we (incorrectly) set includeDepth to Integer.MAX_VALUE as soon as there are excludePaths.
This is not equivalent to “no limit” as this will lead Hibernate Search to consider that the recursion will end eventually; which is true in theory, but not in practice as 2 billion levels of recursion is way more than the JVM can handle.
So, we should let includeDepth default to null as it used to, and find another way to detect infinite recursions when using excludePaths. I suspect this will involve changing org.hibernate.search.engine.mapper.mapping.building.impl.IndexSchemaFilter#getPathFromSameIndexedEmbeddedSinceNoCompositionLimits to take into account excludePaths.
Here’s the idea: you can’t tell in advance whether composition is limited by an excludePaths, so you cannot just adapt hasCompositionLimits(). But when includePaths is empty and includeDepth is null, you can detect that the same IndexedEmbedded was already encountered before, and that the excludePaths of that ancestor node will never affect the current node (because the path from the ancestor node to the current node is not a prefix of any excludePaths. Maybe that’s one solution to the problem?
This model in particular will trigger a
StackOverflowError
:I will send a PR with a reproducer.
From what I can see this stems from the fact that we (incorrectly) set includeDepth to
Integer.MAX_VALUE
as soon as there areexcludePaths
.This is not equivalent to “no limit” as this will lead Hibernate Search to consider that the recursion will end eventually; which is true in theory, but not in practice as 2 billion levels of recursion is way more than the JVM can handle.
So, we should let
includeDepth
default tonull
as it used to, and find another way to detect infinite recursions when usingexcludePaths
. I suspect this will involve changingorg.hibernate.search.engine.mapper.mapping.building.impl.IndexSchemaFilter#getPathFromSameIndexedEmbeddedSinceNoCompositionLimits
to take into accountexcludePaths
.Here’s the idea: you can’t tell in advance whether composition is limited by an
excludePaths
, so you cannot just adapthasCompositionLimits()
. But whenincludePaths
is empty andincludeDepth
is null, you can detect that the sameIndexedEmbedded
was already encountered before, and that theexcludePaths
of that ancestor node will never affect the current node (because the path from the ancestor node to the current node is not a prefix of anyexcludePaths
. Maybe that’s one solution to the problem?