Open carlwoodhouse opened 5 years ago
We have a simular request from the organisation, any pointers to how we should proceed?
You might be able to add a subscription already
Start with something like this services.AddSingleton<ISchemaBuilder, ContentItemSubscription>();
which will give you access to the ISchema
that contains access to queries, mutations and subscriptions. From that just follow the documentation from GraphQL.NET
Yeah just follow what’s in the links; I think the only thing is you have to enable web sockets .. plenty of examples about
On Thu, 7 Nov 2019 at 19:07, Sébastien Ros notifications@github.com wrote:
You might be able to add a subscription already
Start with something like this services.AddSingleton<ISchemaBuilder, ContentItemSubscription>(); which will give you access to the ISchema that contains access to queries, mutations and subscriptions. From that just follow the documentation from GraphQL.NET
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/OrchardCMS/OrchardCore/issues/4489?email_source=notifications&email_token=AADRUEB22XBYV36E2FYIEKLQSRRQHA5CNFSM4I6COKZ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDNPEMY#issuecomment-551219763, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADRUEDTGUXV6SL5ERPI7KTQSRRQHANCNFSM4I6COKZQ .
Ok, not quite familiar with it, but I will have a look. I don't think it is as simple as adding a schema, we also have to have the middleware handling the request.
The sample link @carlwoodhouse provided is really good https://github.com/graphql-dotnet/server/blob/develop/samples/Samples.Server/Startup.cs
I would suggest implementing this under its own feature such as "OrchardCore.Apis.GraphQL.Subscriptions" so that WebSockets is only enabled when subscriptions are used. So you would call AddWebSockets/UseWebSockets from a SubscriptionsStartup class like how the Users module does it here.
As for what the schema would look like for subscriptions, we need to discuss. Here's some initial options:
type Subscription {
contentItem(where: SubscriptionWhereInput) : ContentItemSubscriptionPayload
# OPTION 1
blogPost(where: BlogPostSubscriptionWhereInput): BlogPostSubscriptionPayload
# OPTION 2
blogPost(where: SubscriptionWhereInput): BlogPostSubscriptionPayload
# OPTION 3
blogPostCreated : BlogPost
blogPostUpdated: BlogPost
blogPostRemoved: BlogPost
blogPostPublished: BlogPost
...
}
# FILTER OPTION 1 (Simpler)
input SubscriptionWhereInput {
# Filter for a specific mutation:
# CREATED, UPDATED, REMOVED, PUBLISHED, UNPUBLISHED, CLONED
mutation_in: [MutationType!]
}
# FILTER OPTION 2 (Allows for flexibility in future to filter on BlogPost specific fields.)
input BlogPostSubscriptionWhereInput {
# Filter for a specific mutation:
# CREATED, UPDATED, REMOVED, PUBLISHED, UNPUBLISHED, CLONED
mutation_in: [MutationType!]
}
type BlogPostSubscriptionPayload {
mutation: MutationType!
node: BlogPost
}
Then create a ISchemaBuilder like public class ContentTypeSubscriptions : ISchemaBuilder
similar to ContentTypeQuery
that uses IObservable and ContentHandlerBase. Not sure exactly how this part would work currently.
We would actually be the first headless CMS to support graphql subscriptions once completed which would be cool! 🎉
Totally agree it should be feature based due to the sockets dependency
On Fri, 8 Nov 2019 at 14:09, James Restall notifications@github.com wrote:
The sample link @carlwoodhouse https://github.com/carlwoodhouse provided is really good https://github.com/graphql-dotnet/server/blob/develop/samples/Samples.Server/Startup.cs
I would suggest implementing this under its own feature such as "OrchardCore.Apis.GraphQL.Subscriptions" so that WebSockets is only enabled when subscriptions are used. So you would call AddWebSockets/UseWebSockets from a SubscriptionsStartup class like how the Users module does it here https://github.com/OrchardCMS/OrchardCore/blob/dev/src/OrchardCore.Modules/OrchardCore.Users/Startup.cs .
As for what the schema would look like for subscriptions, we need to discuss. Here's some initial options:
type Subscription {
contentItem(where: SubscriptionWhereInput) : ContentItemSubscriptionPayload
OPTION 1
blogPost(where: BlogPostSubscriptionWhereInput): BlogPostSubscriptionPayload
OPTION 2
blogPost(where: SubscriptionWhereInput): BlogPostSubscriptionPayload
OPTION 3
blogPostCreated : BlogPost
blogPostUpdated: BlogPost
blogPostRemoved: BlogPost
blogPostPublished: BlogPost
...
}
FILTER OPTION 1 (Simpler)
input SubscriptionWhereInput {
Filter for a specific mutation:
CREATED, UPDATED, REMOVED, PUBLISHED, UNPUBLISHED, CLONED
mutation_in: [MutationType!]
}
FILTER OPTION 2 (Allows for flexibility in future to filter on BlogPost specific fields.)
input BlogPostSubscriptionWhereInput {
Filter for a specific mutation:
CREATED, UPDATED, REMOVED, PUBLISHED, UNPUBLISHED, CLONED
mutation_in: [MutationType!]
}
type BlogPostSubscriptionPayload {
mutation: MutationType!
node: BlogPost
}
Then create a ISchemaBuilder like public class ContentTypeSubscriptions : ISchemaBuilder similar to ContentTypeQuery that uses IObservable and ContentHandlerBase. Not sure exactly how this part would work currently.
We would actually be the first headless CMS to support graphql subscriptions once completed which would be cool! 🎉
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/OrchardCMS/OrchardCore/issues/4489?email_source=notifications&email_token=AADRUEHFSFUJYWRRR6LMI4TQSVXJPA5CNFSM4I6COKZ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDSG4HQ#issuecomment-551841310, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADRUEDNH37VYGWKODZZNOLQSVXJPANCNFSM4I6COKZQ .
I think you can only provide subs for
Because a query (sql or lucene) would be too complex to handle.
I'd like to hear about scenarios for subscriptions, and see how these points would solve them.
I'd like to hear about scenarios for subscriptions
Since Orchard Core an Application framework rather than just a CMS. Because of its multitenancy support, modularity, and great rendering engine, we have plans to use Orchard Core as FrontBack as a middleman between React client app and other backend services. We have non-CMS related scenarios where we need to send notifications from backend services to client React app, we use to use SignalR in the first Orchard for this purpose.
I dig a little bit further.
The problem is: Graphql-dotnet still relies on Single instance Schema. But we use ISchemaFactory.GetSchemaAsync
These are places in Startup.cs where a single schema is used: https://github.com/graphql-dotnet/server/blob/develop/samples/Samples.Server/Startup.cs
I see multiple ways to adopt current implementation to our's 1) We have to reimplement the next services to use our's factory approach for Subscriptions
GraphQLWebSocketsMiddleware<TSchema>
https://github.com/graphql-dotnet/server/blob/develop/src/Transports.Subscriptions.WebSockets/GraphQLWebSocketsMiddleware.cs
WebSocketConnectionFactory<TSchema>
https://github.com/graphql-dotnet/server/blob/develop/src/Transports.Subscriptions.WebSockets/WebSocketConnectionFactory.cs
DefaultGraphQLExecuter<TSchema>
https://github.com/graphql-dotnet/server/blob/develop/src/Core/Internal/DefaultGraphQLExecuter.cs
I have a concern about this one, cause it is under .Internal namespace.
2) Try to embrace it by using a hack by registration services in our Startup.cs like
services.AddTransient(typeof(IGraphQLExecuter<Schema>), provider =>
new DefaultGraphQLExecuter<Schema>(
provider.GetService<ISchemaFactory>().GetSchemaAsync().Result as Schema,
provider.GetService<IDocumentExecuter>(),
provider.GetService<IOptions<GraphQLOptions>>(),
provider.GetServices<IDocumentExecutionListener>(),
provider.GetServices<IValidationRule>()));
3) Another way to create a Decorator and register one as Single Instance schema like
public class SchemaDecorator : Schema
{
public SchemaDecorator(IServiceProvider serviceProvider)
{
var dependencyResolver = serviceProvider.GetService<IDependencyResolver>();
var factory = dependencyResolver.Resolve<ISchemaFactory>();
var schema = factory.GetSchema().Result;
.....// continue replace fields from our factory
and use it like in https://github.com/graphql-dotnet/server/blob/develop/samples/Samples.Server/Startup.cs instead of ChatSchema use SchemaDecorator
4) We can contact to graphql-dotnet dev and ask for solution/fix
5) Switch to Hot Chocolate https://hotchocolate.io here is comparisons https://www.reddit.com/r/graphql/comments/dpnqdx/hotchocolate_vs_graphqlnet/ https://github.com/ChilliCream/hotchocolate/issues/392 performance comparison: https://chillicream.com/blog/2019/06/05/hot-chocolate-9.0.0#performance
cc: @sebastienros
Are you sure hotchocolate would solve the issue?
I’d love to switch to hot chocolate; I’ve been using it away from ocore and it’s a much better library; data loaders, Di support etc out of the box and tons of other features. the perf is much better too.
However ..
Can’t say if it would fix this or not; as didn’t look into it.
The upgrade to ocore would be massive. I know this cos I started on a poc branch several months ago.
It would be a major breaking change to anyone who has written their own graph types etc. So would need serious thought.
On Thu, 13 Aug 2020 at 18:30, Sébastien Ros notifications@github.com wrote:
Are you sure hotchocolate would solve the issue?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/OrchardCMS/OrchardCore/issues/4489#issuecomment-673608916, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADRUEE4L7CDLRQ6V4Y2SCTSAQPMLANCNFSM4I6COKZQ .
The upcoming version 11 solves your issues, as I understand.
https://chillicream.github.io/hotchocolate/blog/2020/07/16/version-11
The new schema configuration API allows full async creation and update of dynamic schemas since Hot Chocolate supports schema stitching we reworked version 11 to be able to push schema changes to the GraphQL Gateway dynamically. Schema stitching/schema federation and standard schemas become the same and let you fuse multiple sources and update them on the fly.
If you guys need help, let us now.
And sorry for barging in on this issue :) I just saw it linked to another issue on our project.
At that point I don't expect many have implemented custom graphql extensions. Breaking would be fine, as long as we document how to upgrade the code.
We'd need to check we can still provide the support we have done, with parts, where clauses, paging, ...
Unfortunately, I do not have time to implement Hot Chocolate for the whole Orchard. But I implemented my own module based on the same abstractions we have, it was easy. I do not have to implement my own Middleware like we did with graphql-dotnet and rewriting SchemaFactory was pretty straightforward. I didn't integrate OrchardCore security model with hot chocolate but there are lots of integration points where we can do it. Plus there are already build in solutions for: -Paging https://hotchocolate.io/docs/pagination -Filtration and Sorting https://hotchocolate.io/docs/filters they were made via hot chocolate's Middleware https://hotchocolate.io/docs/middleware, which we can always rewrite or extend
I was thinking about using Schema stitching, where each OrchardCore module/feature can define their own schema, and it will be up to the module/feature to decide either combine their schema with default single schema or expose module's schema as a separate end-point. With Hot chocolate 11, it will be even easier to define schema right in the startup with a fluent builder api, please see https://chillicream.github.io/hotchocolate/blog/2020/07/16/version-11
I can share my implementation with someone who wishes to start implementing Hot chocolate
Supporting subscriptions would allow us to notify consumers of the api that content has changed; which they might use for invalidating caching, rebuilding gatsby sites, etc.
more info: