Hi,
Is this a bug in Absinthe I’ve just ran into? Here’s an SDL schema:
interface A { bs: [B!]! }
interface B { a: A! }
type A1 implements A { bs: [B!]! }
type A2 implements A { bs: [B!]! } # the same as A1 for now
type B1 implements B { a: A! }
type B2 implements B { a: A! } # this is the same as B1
This is a perfectly fine, valid SDL, and Absinthe is able to use it. So far so good.
We have two interfaces here called A
and B
. The types implementing interface A
have to have a field called bs
containing a list of values of any type implementing B
. The types implementing interface B
have to have a field called a
containing a value of a type that implements A
. We also have four types that implement these interfaces. A1
and A2
implement interface A
, while B1
and B2
implement interface B
.
At this point A1
and A2
, just like B1
and B2
have the exact same SDL definitions. Let’s play around with the idea that A1
has to do something with B1
and also that A2
has to do something with B2
:
Let’s say that the field a
of A1
can be specified more accurately. Instead of just containing B
s in general, we know it always holds B1
values. The same goes for the relationship of A2
and B2
, so let’s replace the identical definition with this more specific one:
type A1 implements A { bs: [B1!]! }
type A2 implements A { bs: [B2!]! }
This is also a valid SDL, and Absinthe deals with it. B1
and B2
both implement B
, so the interface requirement is fulfilled. bs
holds values of types implementing interface B
.
Just like when we undo the above change, and replace the definition of B1
and B2
with this:
type B1 implements B { a: A1! }
type B2 implements B { a: A2! }
This is also valid, because A1
and A2
implement A
, so the interface that B1
and B2
implement (that is interface B
) is satisfied.
The problem comes up when both the above modifications are done, like this:
interface A { bs: [B!]! }
interface B { a: A! }
type A1 implements A { bs: [B1!]! }
type A2 implements A { bs: [B2!]! }
type B1 implements B { a: A1! }
type B2 implements B { a: A2! }
Absinthe cannot compile the schema module with an SDL like this. It just eats up the memory of the machine and then the OS kills the compilation process. (I bet this is due to mutually referencing types.)
This might seem like an artificial problem, but actually this was discovered in a real life application with more meaningful types and interfaces that these A
s and B
s. The only workaround I found is that we only replace interfaces with types from one direction, not both.
Is this an Absinthe problem or this is something impossible to resolve in general?
Is there any way we can keep the specific types (instead of the generic interfaces) in our schema?