juniper
juniper copied to clipboard
Are subscriptions limited to being top level?
I think this is a bug but I'm not sure... I've spent several days reading code and trying in vain to achieve this so I'd like a second opinion.
Queries can be set up like this (and so can mutations):
pub struct QueryRoot;
#[juniper::graphql_object(Context = Context)]
impl QueryRoot {
fn settings(&self) -> settings::SettingQueries {
settings::SettingQueries
}
fn other(&self) -> other::OtherQueries {
other::OtherQueries
}
}
However, no variation of this seems to be possible with Subscriptions (this doesn't compile):
pub struct SubscriptionRoot;
#[juniper::graphql_subscription(Context = Context)]
impl SubscriptionRoot {
fn settings(&self) -> settings::SettingSubscriptions {
settings::SettingSubscriptions
}
fn other(&self) -> other::OtherSubscriptions {
other::OtherSubscriptions
}
}
Shouldn't this work or is it a design decision? Are all subscriptions for the whole app required to be in one root impl?
What is the compilation error you are getting? I didn't work on the subscriptions work but might be able to answer the question.
Thanks @LegNeato, I should have added all this to the original issue. I'll show a couple of the angles that I've tried and their errors:
// this is identical to my usage of the Query/Mutation API but with s/graphql_object/graphql_subscription/ and async fns
pub struct SubscriptionRoot;
#[juniper::graphql_subscription(Context = Context)]
impl SubscriptionRoot {
async fn settings(&self) -> settings::SettingSubscriptions {
settings::SettingSubscriptions
}
async fn other(&self) -> other::OtherSubscriptions {
other::OtherSubscriptions
}
}
pub struct SettingSubscriptions;
#[juniper::graphql_subscription(Context = Context)]
impl SettingSubscriptions {
pub async fn settings() ...
}
gives this error at the SubscriptionRoot site:
#[juniper::graphql_subscription(Context = Context)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `futures::Stream` is not implemented for SettingSubscriptions
So I thought "maybe we can define the top level as a graphql_object
which then pulls in the graphql_subscription
":
pub struct SubscriptionRoot;
#[juniper::graphql_object(Context = Context)]
impl SubscriptionRoot {
fn settings(&self) -> settings::SettingSubscriptions {
settings::SettingSubscriptions
}
fn other(&self) -> other::OtherSubscriptions {
other::OtherSubscriptions
}
}
pub struct SettingSubscriptions;
#[juniper::graphql_subscription(Context = Context)]
impl SettingSubscriptions {
pub async fn settings() ...
}
gives this error at the SubscriptionRoot site:
#[juniper::graphql_object(Context = Context)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `GraphQLValueAsync<__S>` is not implemented for SettingSubscriptions
Which is understandable I suppose because we're defining SubscriptionRoot
as a graphql_object
. I thought perhaps this was a way that could work today in userland code but I wasn't able to get GraphQLValueAsync<__S>
defined correctly for some reason.
@jerel as far as I recall, this is not supported at the moment. The reason is that is not clear how such situations should be resolved. A subscription in a nutshell is a Stream
. So having a Stream
, whcih field resolves to another Stream
, how you expect to behave this on client?
Do you have any reference examples how it's handled in other languages?