I have an issue where the subscriptions are firing multiple times per event when they should only fire once. The number of times the subscriptions fire increases the more requests the server receives.
The issue can be reproduced with this project: https://github.com/howtographql/react-apollo/tree/gc-1.0
Any news on this @schickling?
For me it doesn't get fired :(
@tfiwm can you share a link to your repo so we can reproduce your issue?
Might be related to this, @tfiwm: https://github.com/graphcool/prisma/issues/1734
I'm experiencing this as well:
Response from http://localhost:4466/homeroom-api/dev:
{
"message": {
"node": {
"text": "twice?",
"sender": {
"id": "cjcq8hd7e00130143cj9sg8mz",
"name": "Logan Bernard",
"__typename": "User"
},
"__typename": "Message"
},
"__typename": "MessageSubscriptionPayload"
}
}
Response from http://localhost:4466/homeroom-api/dev:
{
"message": {
"node": {
"text": "twice?",
"sender": {
"id": "cjcq8hd7e00130143cj9sg8mz",
"name": "Logan Bernard",
"__typename": "User"
},
"__typename": "Message"
},
"__typename": "MessageSubscriptionPayload"
}
}
Response from http://localhost:4466/homeroom-api/dev:
{
"message": {
"node": {
"text": "twice?",
"sender": {
"id": "cjcq8hd7e00130143cj9sg8mz",
"name": "Logan Bernard",
"__typename": "User"
},
"__typename": "Message"
},
"__typename": "MessageSubscriptionPayload"
}
}
@tfiwm found out that this is easily reproduced when refreshing the browser. Then a new connection is created, but old connections are _also_ set up again.
Is this reproducable in the playground? Or just combined with the apollo-client?
It's reproducible with this "subscription client": https://gist.github.com/marktani/5df524523693c88be425bfb623ca8b8a
Note that this observation might be a different phenomenon than what @nikolasburk originally reported.
It might be two separate problems, client and server side.
https://github.com/oxy88/prisma_subscription
In my case,
@oxy88 Your steps description seems to indicate that yoga is not involved here?
Anyone have an update here? I'm not sure if this is graphql-yoga related or not.
I currently have a work around to ignore duplicate subscription messages, but it's less than ideal 馃槄
We are currently looking into this with a fix coming up soon 馃檪
I did a PR to graphql-tools, as soon as it's merged, the problem is fixed. https://github.com/apollographql/graphql-tools/pull/609
The fix was merged and is available in version [email protected].
Thanks everyone for feedback and help to pinpoint this issue 馃檶
This problem still happens while using the managed Graphcool service
@darmie maybe worth opening a new issue?
This problem still happens while using Prisma
any word on this? Still happens when using prisma
I have an issue where the subscriptions are firing multiple times per event when they should only fire once. The number of times the subscriptions fire increases the more requests the server receives.
The issue can be reproduced with this project: https://github.com/howtographql/react-apollo/tree/gc-1.0
@nikolasburk
Hi Nikolas,
I was doing your tutorial with react and apollo on howtographql.com, and I seam to figure out why subscriptions fire multiple times.
It seams to have nothing to do with Prisma or Yoga server, but with
The number of firing doesn't depend on number of requests on server but rather on number of renderings of Query component in LinkList, each time receiving new data from subscription, LinkList component rerender Query and makes new subscription for the same data, and then get it multiple times per request.
I solved this issue with dirty fix by wrapping subscription functions with flags, that prevent Query from subscribing multiple times.
Here is your LinkList code with my fixes.
`import React, { Component } from 'react'
import Link from './Link'
import { Query } from 'react-apollo'
import gql from 'graphql-tag'
export const FEED_QUERY = gql
{
feed {
links {
id
createdAt
url
description
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
}
}
const NEW_LINKS_SUBSCRIPTION = gql
subscription {
newLink {
node {
id
url
description
createdAt
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
}
}
const NEW_VOTES_SUBSCRIPTION = gql
subscription {
newVote {
node {
id
link {
id
url
description
createdAt
postedBy {
id
name
}
votes {
id
user {
id
}
}
}
user {
id
}
}
}
}
class LinkList extends Component {
state = {
subscribedToNewLinks:false,
subscribedToNewVotes:false,
}
_updateCacheAfterVote = (store, createVote, linkId) => {
const data = store.readQuery({ query: FEED_QUERY })
const votedLink = data.feed.links.find(link => link.id === linkId)
votedLink.votes = createVote.link.votes
store.writeQuery({ query: FEED_QUERY, data })
}
_subscribeToNewLinks = subscribeToMore => {
subscribeToMore({
document: NEW_LINKS_SUBSCRIPTION,
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev
const newLink = subscriptionData.data.newLink.node
return Object.assign({}, prev, {
feed: {
links: [newLink, ...prev.feed.links],
count: prev.feed.links.length + 1,
__typename: prev.feed.__typename
}
})
}
})
this.setState({subscribedToNewLinks:true})
}
_subscribeToNewVotes = subscribeToMore => {
subscribeToMore({
document: NEW_VOTES_SUBSCRIPTION
})
this.setState({subscribedToNewVotes:true})
}
render() {
return (
<Query query={FEED_QUERY}>
{({loading, error, data, subscribeToMore }) => {
if (loading) return <div>Fetching</div>
if (error) return <div>Error</div>
if(!this.state.subscribedToNewLinks){
this._subscribeToNewLinks(subscribeToMore)
}
if(!this.state.subscribedToNewVotes){
this._subscribeToNewVotes(subscribeToMore)
}
const linksToRender = data.feed.links
return (
<div>
{linksToRender.map((link, index) => (
<Link
key={link.id}
link={link}
index={index}
updateStoreAfterVote={this._updateCacheAfterVote}/>
))}
</div>
)
}}
</Query>
)
}
}
export default LinkList`
I think that problem is that subscriptions should be registered on mount and unregistered on unmount of the component.
Hope that helps,
Best regards,
Myroshnyk Roman
PS. I opened an issue on react-apollo https://github.com/apollographql/react-apollo/issues/2656
Was able to do it by passing subscribeToMore into a child component and subscribing in componentDidMount
Was able to do it by passing subscribeToMore into a child component and subscribing in componentDidMount
I think that's valid approach, but you should be careful to unregister subscription on componentWillUnmount in case the whole component will be rerendered upon link change or some other scenarios,
It feels for me, all subscriptions are saved somewhere in singleton of react-apollo, and leaving subscription uregistered may lead to multiple mutations of store on one emitted subscription.
Most helpful comment
This problem still happens while using the managed Graphcool service