Open n1ru4l opened 2 years ago
We definitely intend to do this (I've been speaking with @enisdenjo about it) but it is out of scope for the 1.0 release which we basically need to feature freeze right now in order to try and get it cut along with the GraphQL spec in October.
Currently a GraphQL over SSE Protocol RFC.
Even though SSE is indeed quite simple, there are some "complexities" added to the Protocol which aim to overcome common problems, just to name a few:
EventSource.onerror
complete
message to distinguish when a connection gets closed because of a network loss vs. when the subscription is actually completedThe "single connection mode" aiming to help with HTTP/1 servers and subscription heavy apps
In my opinion, this added complexity can be optional as servers that support HTTP/2 don't need to do this. HTTP/2 support for browsers seems quite high (97%). From quick research, overall the current adoption for web servers is around 44%
In my opinion, this added complexity can be optional as servers that support HTTP/2 don't need to do this.
Completely agree! But that is not the only reason, when using HTTP/2 the max number of simultaneous HTTP streams default to 100. Even though this is quite high, I feel like subscription heavy apps might be reaching this limit. One example I could think of is file upload with server processing progress tracking, uploading 100+ files in one swab, and subscribing to every each one of them, might issue problems. However, I agree that this might be a long shot, but I think it's still worth considering.
Subscriptions are typically best when really granular (quite the opposite of queries where you want to get everything at once). This means you can unsubscribe from old items in a list and subscribe to new ones as the user scrolls (without affecting the subscriptions to those in the middle). As such, the number of active subscriptions on any one page on a large screen could easily be 30-50, and when you multiply that by all tabs in a browser that's quickly going to break the 100 limit.
I totally agree! Applications could easily have more than 100 active subscriptions. Take something like a chat app with channels where the client subscribes to each channel and each member for updates/state changes. Or something twitter-like where you subscribe to each tweet and the authors of these. And with each reply you receive (via the subscription on a tweet), you subscribe to the reply and the author of the reply as well.
Subscriptions are typically best when really granular (quite the opposite of queries where you want to get everything at once).
That is an interesting take, it would be nice to get feedback from people who build Twitter-like applications. In the past, I moved the subscriptions up in order to reduce the concurrent amount of subscriptions.
For applying live updates to a paginated list I used the following Subscription model before, of course, this differs from the use-case where you only want to update certain properties within a single item. For stuff where you don't care about the exact event though I used to find live queries to be a bit more convenient, those have other issues with paginated data, and I don't wanna pull live queries into this discussion.
type Query {
notes(first: Int, after: String): NoteConnection!
}
type NoteConnection {
edges: [NoteEdge!]!
pageInfo: PageInfo!
}
type NoteEdge {
cursor: String!
node: Note!
}
type Note implements Node {
id: ID!
documentId: ID!
title: String!
content: String!
contentPreview: String!
createdAt: Int!
viewerCanEdit: Boolean!
viewerCanShare: Boolean!
access: String!
isEntryPoint: Boolean!
updatedAt: Int!
}
type NotesUpdates {
"""
A node that was added to the connection.
"""
addedNode: NotesConnectionEdgeInsertionUpdate
"""
A note that was updated.
"""
updatedNote: Note
"""
A note that was removed.
"""
removedNoteId: ID
}
type NotesConnectionEdgeInsertionUpdate {
"""
The cursor of the item before which the node should be inserted.
"""
previousCursor: String
"""
The edge that should be inserted.
"""
edge: NoteEdge
}
type Subscription {
notesUpdates(endCursor: String!, hasNextPage: Boolean!): NotesUpdates!
}
I agree that the spec should at least mention Subscriptions, regardless of if if describes some implementation over HTTP or not. Something like "Subscriptions are out of scope of this spec because ....". Just to clear user's possible confusion - where are subscriptions? Currently spec has 0 occurrences of "subscription"
@rivantsov It was mentioned before https://github.com/graphql/graphql-over-http/pull/166
well, yes, but mentioned in particular context - POST op, as far as I understood. As a result of discussion Subscriptions were removed from there, resulting in current situation when subs are not mentioned at all. I think we need to fix it. Queries and mutations are mentioned, but subs are not, at all. Should be.
Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection, that does not require any complex protocol compared to WebSocket, thus making it a perfect fit for having a recommended and standardized way of doing GraphQL Subscriptions in the GraphQL over HTTP specification.