apollographql / graphql-subscriptions Goto Github PK
View Code? Open in Web Editor NEW:newspaper: A small module that implements GraphQL subscriptions for Node.js
License: MIT License
:newspaper: A small module that implements GraphQL subscriptions for Node.js
License: MIT License
so npmjs package doesn't have the link to here :(
I've been trying to trace a subscription_failed error for hours without any success. The data sent to the client on failure is {"type":"subscription_fail","id":0,"payload":{"errors":[{"message":"Cannot read property 'forEach' of undefined"}]}}
.
There is nothing logged to the console of the server. I've also checked the application code and there is no use of forEach
so I suspect it's rooted in graphql-subscriptions
or subscriptions-transport-ws
. Both the client and server are using the latest releases of the Apollo stack.
Subscriptions were working flawlessly up until I resumed development today. I'm going to check out the master branch and see if it the error is still happening. I'll also attempt a clean install.
I couldn't find an issue similar to this one so I'm opening this in hope of some direction. Any help is much appreciated.
I use JWT auth for authentication and no problems with apollo client authentication because http://dev.apollodata.com/core/network.html#networkInterfaceMiddleware even when token refreshes, but I have the issue with graphql subscriptions authentication. According to https://github.com/apollographql/graphql-subscriptions/blob/master/.designs/authorization.md and https://github.com/apollographql/tools-docs/blob/master/tools/graphql-subscriptions/authentication.md token sets once only (connectionParams: {token: 'some string'}
and lazy: true
) on initialisation SubscriptionClient and it works fine, but not when token refreshes.
Technologies/libs which I use in my project:
vue
vue-auth
vue-apollo
expressjs
graphql-subscriptions
subscriptions-transport-ws
graphql
I was following the tutorial in the README file. I noticed if I use
// publish to the channel
pubsub.publish('newCommentsChannel', {
id: 123,
content: 'Test',
repoFullName: 'apollostack/GitHunt-API',
posted_by: 'helfer',
});
I will get
{
data: {
commentAdded: null
}
}
But if I publish with the subscription name in the object
// publish to the channel
pubsub.publish('newCommentsChannel', {
commentAdded: {
id: 123,
content: 'Test',
repoFullName: 'apollostack/GitHunt-API',
posted_by: 'helfer',
}
});
Then I will get the result as in the README.
Am I missing something from the document?
Hello,
I would like to know if it is possible to use graphql-mqtt-subscriptions
along with this package. More precisely, I'd like someone to explain how to wrap a pubsub with an AsyncIterator
since the apollo client needs one for the subscription to be effective.
My final goal is to use a MQTT broker to handle subscriptions instead of the in-memory pubsub engine provided by your package.
Thank you for your help.
Let's discuss how a possible Meteor livequery
integration could look like.
Advantages
Livequery integration would allow the full expressiveness of the mongo query syntax (limited by the minimongo
limitations). Especially the ability to sort & limit queries seems interesting to me. This makes subscriptions possible like: give me updates on the top 3 voted posts. This would be hard to implement in a traditional pubsub system.
Disadvantages
Hard to extend to other DB's beyond mongo
(but maybe postgres
and rethink
).
Only as scalable as livequery is (although no merge box required?)
Possible approach with the current system
The current system doesn't seem particularly well fit, but one could imagine something like:
const subscriptionManager = new SubscriptionManager({
schema,
pubsub,
setupFunctions: {
topComments: (options, args) => ({
someName: {
channelOptions: {
cursor: Comments.find({reponame: args.repoFullName},{sort:{votes:-1},limit:3}),
added: true,
changed: true,
removed: true
}
},
}),
},
});
The pubsub system could then add an observer on the cursor and trigger the changes the user indicated it wants to listen to (added
, changed
and/or `removed).
Problems with this approach
It's quite obvious that it's quite hacky, the current system doesn't seem well fit. E.g. the channel name (someName
) has no meaning.
It's also not really a pubsub system. We're only subscribing, but can't publish.
Unable to work with latest Node, now when adding graphql
and graphql-subscriptions
as dependencies - I get duplicate of graphql
:
node_modules
graphql
graphql-subscriptions
node_modules
graphql
Temporary workaround is to remove graphql
dependency, and then NPM flatten the need for graphql
and install it under the root node_modules
.
What I am using:
react-native: 0.42.3
react-apollo: 1.0.0-rc.3
apollo-client: 1.0.0-rc.6
subscriptions-transport-ws: 0.5.5-alpha.0
graphql-subscriptions: ^0.3.1
I have the following schema:
type Episode {
id: Int!
number: String!
title: String!
cover: String!
}
type CastQueueItem {
itemId: Int!
episode: Episode!
}
type CastStatus {
queueItems: [CastQueueItem]!
}
type Subscription {
castStatus: CastStatus!
}
schema {
query: Query # not included
mutation: Mutation # not included
subscription: Subscription
}
This is my Subscription to which I subscribe in my react-native application:
subscription castStatus {
castStatus {
queueItems {
itemId
episode {
id
title
cover
}
}
}
}
Somewhere in my javascript I publish the CastStatus:
const castStatus = {
queueItems: [
{ itemId: 1, episode: { id: 1, title: '1', },
{ itemId: 2, episode: { id: 2, title: '2', },
],
}
pubsub.publish(`castStatus`, { castStatus })
The cover field has a resolver that exists on the schema I passed to the SubscriptionManager constructor.
I am expecting the cover field to be resolved trough my schema - but it seems not to work. I am getting no updates from the server as long as I the cover field is listed in my subscription. Also, I am not getting any error message :(
I wanted to ask if this behavior is on purpose and if so why SubscriptionManager does not resolve field via the schema.
I was wondering what a good pattern would be for receiving an initial subscription payload?
let me try to explain with the help of some contrived examples:
if we run the code from the docs ...
// hooking up subscription resolvers etc., simplified
const resolvers = {
Subscription: {
getReport: {
subscribe: () => ....
// ...
// then run ...
pubsub.publish( 'somethingChanged', { getReport: { id: "1" }});
then the subscription query would not receive any payload:
subscription {
getReport {
id
}
}
... unless we are triggering publish, e.g. through a Mutation.
function publish() {
pubsub.publish( 'somethingChanged', { getReport: { id: "1" }});
}
const resolvers = {
Mutation: {
triggerReport: () => publish()
e.g. we could also make it work this way - just to have a (bad) example:
setInterval( () =>
pubsub.publish( 'somethingChanged', { getReport: { id: "1" }})
), 1000 );
My understanding is that one would usually use a Mutation in order to trigger publish.
I was wondering how could one receive the initial payload without a trigger?
Unless subscriptions are only meant to be published through some sort of trigger?
Or would one get the initial payload through an ordinary graphql query?
query {
getReport {
id
}
}
Thanks in advance for any advice!
I was trying to use filtering explained in the official documentation but it fails with the "Subscription must return Async Iterable" error.
Here is my example for my Subscription resolver
:
This doesn't work:
Subscription: {
errorChanged: {
subscribe: () => withFilter(
() => pubsub.asyncIterator("errorChanged"),
(payload, variables) => {
return true;
},
),
},
}
This works:
Subscription: {
errorChanged: {
subscribe: () => pubsub.asyncIterator("errorChanged")
},
}
Am I doing something wrong?
Using version: 0.4.4
The problem is when publishing a value it will return null on the subscribe method
export const subscriptions = model => ({
[model]: {
resolve(payload) {
console.log({...payload[model]})
return {...payload[model]}
},
subscribe: withFilter(() => pubsub.asyncIterator(
['CREATED','UPDATED', 'DELETED']
.map(mutation => `${model.toUpperCase()}_${mutation}`)),
(payload,variables) => {
return payload.id === variables.id
})
}
})
And publishing it like this
[`update${model}`]: async(_, { id, ...args }, { models }, info) => {
let result = await models[model].findById(id)
await result.update(args)
pubsub.publish(`${model.toUpperCase()}_UPDATED`, {
[model]: args
})
return result
},
this is what i get received from the Subscription resolve
[nodemon] starting `babel-node src`
Server started at 0.0.0.0:8080
express deprecated req.host: Use req.hostname instead src/server.js:97:88
{ name: 'testerssas',
description: 'test',
slug: 'testerssas',
fee: 0 }
POST /graphql 200 59.101 ms - -
and getting this error
Noticed that [object Object] is an error
Hi guys,
In file README
, currently we have the demo code to publish events:
pubsub.publish(SOMETHING_CHANGED_TOPIC, { somethingChanged: { id: "123" }});
I tried to use the template above but in clients, I've got nothing. All fields are set to null
. But if I modify it a little bit like this:
pubsub.publish(SOMETHING_CHANGED_TOPIC, { id: "123" });
It works as expected. So is there any thing wrong with the documentation?
How can we use graphql-subscriptions with a serverless backend like AWS Lambda? In this case, transport using web sockets won't work since a lambda function can't run for long time.
I have followed the Readme and tried to follow along with this Medium post and the GitHunt API example.
Unfortunately my pubsub doesn't seem to be publishing my updates. Interestingly when I try to subscribe directly through my node server I am getting the Error: Must provide schema
, which I do not understand. Not sure if you can see anything wrong with this setup:
// subscribe.js
import { PubSub, SubscriptionManager } from 'graphql-subscriptions';
import schema from './schema';
const pubsub = new PubSub();
const subManger = new SubscriptionManager({
schema,
pubsub,
setupFunctions: {
todoAdded: (options, args) => ({
todoAdded: (todo) => {
return true;
},
}),
},
});
subManger.subscribe({
query: `subscription todos($completed:Boolean) {
todoAdded(completed:$completed){
id
title
completed
}
}`,
variables: {
completed: null
},
context: {},
callback: (err, data) => console.log(data)
});
pubsub.publish('todoAdded', {
id: 123,
title: 'testing graphql subscriptions',
completed: false
});
export { subManger, pubsub };
// schema.js
import Resolvers from './resolvers';
import Schema from './schema.graphql';
import { makeExecutableSchema } from 'graphql-tools';
const executableSchema = makeExecutableSchema({
typeDefs: Schema,
resolvers: Resolvers,
allowUndefinedInResolve: true,
resolverValidationOptions: {
requireResolversForNonScalar: false
},
printErrors: process.env.NODE_ENV !== 'production',
});
export default executableSchema;
// schema.graphql
type Todo {
id: ID
createdAt: String
updatedAt: String
title: String
completed: Boolean
}
type Query {
todos(completed: Boolean): [Todo]
todoAdded(completed: Boolean): Todo
}
type Mutation {
addTodo(title: String!): Todo
editTodo(id: Int!, title: String, completed: Boolean): Todo
deleteTodo(id: Int!): String
}
type Subscription {
todoAdded(completed: Boolean): Todo
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
it would be really nice to have an apollo and a relay example of usage of this package
I have a graphql server and I'm attempting to trigger an event whenever the status of an entity is updated. I have a mutation for updating the entity, which uses graphql-subscriptions to publish the update for the subscriber to listen to. However, pubsub.subscribe(EVENT_NAME) picked up the change, but when I integrate that into the subscription resolver, it doesn't trigger the update.
I've redacted parts of the code not relevant to the issue for brevity.
My resolver:
Mutation: {
updateStatus(_, { id, status, hash }) {
return repository.updateStatus(id, status, hash);
}
},
Subscription: {
updatedStatus: {
subscribe: () => pubsub.asyncIterator('updatedStatus'),
}
},
My repository:
export const updateStatus = async function(id: String, status: String, hash: String) {
try {
const res = await fetch(`${baseURL}/article/${id}/status?publish_hash=${hash}`, {
headers,
method: 'PATCH',
body: JSON.stringify({ status })
});
const article = await fetchSingleArticle(id, 'XML', headers.channel, false);
await pubsub.publish('updatedStatus', article);
return article;
} catch (e) {
console.log(e.message);
}
}
My schema:
type Mutation {
updateStatus(id: ID!, status: PublishingStatus = PUBLISHING, hash: String): Article
}
type Subscription {
updatedStatus(id: ID!): Article
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
To test this, I'm just using graphiql, which is picking up the websocket connection fine.
I've attempted the publish using both article (as shown) and { updatedStatus: article }, neither seem to get picked up.
As mentioned previously pubsub.subscribe('updatedStatus') does pick up the change. So the issue seems to be related to the Subscription resolver.
I'm going off the following docs: http://dev.apollodata.com/tools/graphql-subscriptions/setup.html#setup
It seems that SubscriptionManager[@deprecated]
was meant for that so I'm a bit lost ๐บ
I've got a foobarUpdated
subscription, but I need to authorize the users who subscribe to it as well as validate the variable (if the given id is not a valid foobar id, subscription doesn't make sense).
Is there a way to deny/cancel a subscription? I'm using withFilter
but that only works for filtering after the subscription has been initiated.
Hi,
Actually, if I'm not mistaken, for each subscription, when there is new data available the schema of each listener query is executed against the GraphQL Schema. Am I right ?
This seems rather inefficient.
I think it would be doable to merge all listeners query into one, execute it against the schema and then dispatch only the queried data for each listener.
What do you think ?
I have found a difficulty compiling my Typescript code and it turns out that inside many files in graphql-subscriptions and subscriptions-transport-ws, the AsyncIterator iterator type interface is treated as defined, but the Typescript compiler doesn't agree with that. here is the list of errors:
node_modules/graphql-subscriptions/dist/pubsub-engine.d.ts(5,52): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/graphql-subscriptions/dist/pubsub.d.ts(12,52): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/graphql-subscriptions/dist/with-filter.d.ts(2,94): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/graphql-subscriptions/dist/with-filter.d.ts(3,58): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/subscriptions-transport-ws/dist/server.d.ts(5,41): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/subscriptions-transport-ws/dist/server.d.ts(29,58): error TS2304: Cannot find name 'AsyncIterator'.
node_modules/subscriptions-transport-ws/dist/server.d.ts(32,31): error TS2304: Cannot find name 'AsyncIterator'.
I had found a temporary solution to bypass the errors by defining AsyncIterator type interface in every file involved in node_modules, here is the definition:
interface AsyncIterator<T> {
next(value?: any): Promise<IteratorResult<T>>;
return?(value?: any): Promise<IteratorResult<T>>;
throw?(e?: any): Promise<IteratorResult<T>>;
}
Hello,
I got this error when I tried to execute this code. Do you have any idea?
src/index.ts(40,49): error TS2345: Argument of type '{ typeDefs: string; resolvers: { Query: { addCell: (: any, { type }: { type: any; }) => Prom...' is not assignable to parameter of type 'IExecutableSchemaDefinition'.
Types of property 'resolvers' are incompatible.
Type '{ Query: { addCell: (: any, { type }: { type: any; }) => Promise; }; Subscription: ...' is not assignable to type 'IResolvers'.
Property 'Subscription' is incompatible with index signature.
Type '{ newCell: { subscribe: (: any, { type }: { type: any; }) => AsyncIterator<{}>; }; }' is not assignable to type 'GraphQLScalarType | IResolverObject | (() => any)'.
Type '{ newCell: { subscribe: (: any, { type }: { type: any; }) => AsyncIterator<{}>; }; }' is not assignable to type '() => any'.
Type '{ newCell: { subscribe: (_: any, { type }: { type: any; }) => AsyncIterator<{}>; }; }' provides no match for the signature '(): any'.
import { PubSub } from 'graphql-subscriptions';
const pubsub = new PubSub();
export const typeDefs = `
type Subscription {
newCell: Cell
}
type Query {
addCell(type: CellType!): Cell
}
schema {
query: Query
subscription: Subscription
}
`
export const resolvers = {
Query: {
addCell: async (_, { type }) => {
let cell = new Cell();
cell.type = type;
pubsub.publish('newCell', { newCell: cell });
return cell;
},
},
Subscription: {
newCell: {
subscribe: () =>
pubsub.asyncIterator('newCell')
}
}
};
I'm trying to create a Subscription to tell when a new post is created. My issue is that the type Post
have an author: User!
and I don't know how to pass the User to the Post on the mutation. I can pass the id, title, and description without issues but not the User
.
Subscription:
https://github.com/KadoBOT/musical-memory/blob/master/src/components/Posts/index.js
Schema and Resolver:
https://github.com/KadoBOT/musical-memory/tree/master/server/schema
Can someone help me?
I tried to integrate graphql-subscriptions
and it worked out pretty good, But it broke the app (which i can fix easily.. but i don't think that's the right decision)
Subscriptions sends the updates
for everything i am subscribed to, But when i create a new item, The store is already updated from the mutation i just ran, but Subscription kicks in and runs the logic which updates the store again.. And i get the duplicate key warning.
I can and have fixed this by checking if a record already exists and then handling the update., But this means that the updates are still sent to all the subscribed clients who want to be notified of the changes.
Is there any way to send updates to all the subscribed clients, Except the one making the changes/operations (CRUD), without writing lot of codes?
Ofcourse i can use setupFunctions filter but if the same user has opened the app in different tabs, this will not work out.
What do you recommend, How should i move forward with this.
I've hacked your code so it does
// 3. subscribe and keep the subscription id
const subsPromise = this.pubsub.subscribe(triggerName, onMessage, channelOptions, options.variables);
rather than..
// 3. subscribe and keep the subscription id
const subsPromise = this.pubsub.subscribe(triggerName, onMessage, channelOptions);
this means I can implement pubsub so it subscribes to an external event source (dont worry about details):
const valueSubscriptions = {};
class MyPubSub extends PubSub {
subscribe(trigger, onMessage, channelOptions, variables){
const ret = super.subscribe(trigger, onMessage);
if (trigger === 'value') {
ret.then(f => valueSubscriptions[f] = opcObserver(variables.id).subscribe(v => pubsub.publish('value', v)));
}
return ret;
}
unsubscribe(subid) {
if (valueSubscriptions[subid]) {
valueSubscriptions[subid].unsubscribe();
delete valueSubscriptions[subid];
}
return super.unsubscribe(subid);
}
}
would this make sense for you to incorporate?
graphql-subscriptions
no longer compile with Typescript. AsyncIterator from @types/async requires 2 type arguments.
I'm using [email protected]
.
Had to manualy add the second type in *.d.ts
files from graphql-subscriptions
to make it work.
I use withFilter to validate payload and got an infinite loop when there are no subscribers left (payload is resolved immediately with {value: undefined, done: true}
).
const getNextPromise = () => {
return asyncIterator
.next()
.then(payload => Promise.all([
payload,
Promise.resolve(filterFn(payload.value, args, context, info)).catch(() => false),
]))
.then(([payload, filterResult]) => {
if (filterResult === true) {
return payload;
}
// Skip the current value and wait for the next one
return getNextPromise();
});
};
This function recursively calls itself even if payload.done is true and it leads to infinite call. Adding check for payload.done before return getNextPromise();
fixes this problem or am I missing something?
How one want to publish shouldn't matter to the SubscriptionManager, as the correct way to publish messages is through the onMessage callback.
I think the publish methods on PubSub and SubscriptionManager are confusing, as you can implement a correct (for now) server without them.
E.g. I implemented a PubSub based on Observables:
pubsub: {
subscribe(triggerName, onMessage, channelOptions) {
return Promise.resolve(channelOptions.resolve$.subscribe(onMessage, console.error))
},
unsubscribe(subscription) {
subscription.unsubscribe()
}
},
No need for publish (and I wouldn't know how to implement it if I wanted to).
It's fine for the default in-memory-event-based-pubsub-implementation to have a publish method, but it shouldn't be in the interface or wrapped in SubscriptionManager.
Thx.
You should have another property besides filter for trigger map which could clean the rootValue before executing on graphql and submitting to the client, a suggestion would be a promisable (!) format
or even a resolve
property.
On file pubsub.ts
on line 197,
In my case this is important because I need to remove private values on an object type when the client authorized is not eligible to see it.
The following is an example of how I would be able to use it.
I want to validate the subscription params with an async function. If I return a promise from the subscription resolver on the server the client errors with Subscription must return Async Iterable
.
Can I submit a PR to allow an async subscribe function? And where should I look to make those changes?
newCommentsChannel: {
filter: comment => comment.repository_name === args.repoFullName,
},
Hi, I was wondering about the snippet above, would it scale to a large number of subscriptions? Since each subscription is doing a filter check, that would be o(n). Alternatively, is there a way to declare that variable upfront, for example newComments_${postId}
as the channel name. Currently, the setupFunctions
method seems to be mapping each distinct channel. A way to use a pattern would be helpful. Would love to understand more about optimizing subscriptions. Cheers :)
Hello guys!
Sorry for the level on this. But I havnt found any better place to ask this, and i'm new to nodejs and graphql. I have been looking for an easy way to make use of rethinkdb changefeeds in my subscription, and just found out of this solution and was wondering what you guys think of it:
Subscription: {
changefeedTest: {
subscribe: () => {
const feedUuid = uuid()
r.table('people').filter({ maybeSomethingUniqueHereForEachUser }).changes().run().then((feed) => {
feed.each((error, change) => {
console.log('publishing data to user')
pubsub.publish(feedUuid, { changefeedTest: change.new_val })
})
})
return pubsub.asyncIterator(feedUuid)
}
}
}
Any thoughts of this approach? With this code I skip the generic pubsub topics and create a unique one for each subscription query against the DB. This way I think i'm certain that each user will just get the data it should have since they will only get the unique topic.
Only problem I have right now, is that the changefeed keeps running after the user disconnects. So after a while testing I have X (one more each time) "publishing data to user" as soon as i open a new connection. I am thinking of saving a reference to the feed to an array, and close them in the onDisconnect hook on subscriptionserver. I would however either save them somehow on a session specific variable (i dont know how to do this in node), or save it in a big array grouped on session id.
feedsToDisconnect[uniqueSessionId].push(feed)
and then inside the onDisconnect:
feedsToDisconnect[uniqueSessionId].map((feed) => { feed.close() }) and kill of the group.
It seems that my resolver when responding to a subscription doesn't have access to the context variable, that are typically available with a non-subscription request. In my case I'm trying to push as many request that I can through a data loader.
Heres my resolver:
resolve: (source, args, { loaders }) => {
if (source.user.length === 0) {
return {};
}
return loaders.users.load(source.user);
},
Currently, I have something like this setup for standard graphql requests
router.post('/graphql', graphqlKoa({
schema,
formatParams(params) {
return params;
},
context: { loaders: {
users: Loader(r.table('users'), 'id')
} },
}));
How might I set something like this with subscriptions?
On file pubsub.ts
on line 162, the setupFunction should be handling the errors thrown in the function. That is important because we can decline and authorize subscriptions directly in the setupFunction itself. And by having this in mind you should make the setupFunction promisable for security async operations, like the onSubscribe
method.
In my case this is important because I have different authorization methods, and one can be invalid depending on the subscription.
Here's an example of how I would be able to use it.
Hey,
This line (https://github.com/apollostack/graphql-subscriptions/blob/master/src/validation.ts#L22) throws an error if the subscription query does not have a name. It looks like it would be okay to default the operationName to '' if no name is provided.
Hi, I have a task to display all connected clients on client side.
Ex:
Name1 (email)
Name2 (email)
...
NameN (email)
I know that I have to store some information on server and should use onConnect
, but how?
With SocketIO I can use rooms, but how I can realize the same with graphql-subscriptions?
I try to create subscriptions schema. but hard for me.
Do you have example code for create subscriptions with express-graphql ?
Thank you
This little change will enable PubSub to access query itself.
Seems to be the necessary step if we want to implement things like subscribing to RethinkDB changefeeds which itself can trigger publish events.
Without this information we can only hardcode some changefeeds without arguments.
Just little change in SubscriptionManager, I am TS disabled, so no PR :-(
// 3. subscribe and keep the subscription id
const subsPromise = this.pubsub.subscribe(triggerName, handler, options);
subsPromise.then(id => this.subscriptions[externalSubscriptionId].push(id));
SubscriptionManager::subscriptions
maps is never cleaned up from subscription tracking and leaks their references.
I assume it should be cleaned up on unsubscribe ?
I've struggled for a couple hours last night to get this but I couldn't.
Snippet 1
subscription($repoName: String!) {
commentAdded(repoName: $repoName) { # <-- `commentAdded` is the subscription name
id
content
}
}
Snippet 2
const subscriptionManager = new SubscriptionManager({
schema,
pubsub,
setupFunctions: {
commentAdded: (options, args) => ({
commentAdded: {
filter: comment => comment.repository_name === args.repoFullName,
},
}),
},
});
Snippet 3
pubsub.publish('commentAdded', payload);
I have a couple questions
In the 1st snippet commentAdded
is the subscription name and in the 3rd snippet commentAdded
is the event name. Are those the same thing?
Why commentAdded
appears twice in setupFunctions
of the 2nd snippet? Wouldn't this be enough?
const subscriptionManager = new SubscriptionManager({
schema,
pubsub,
setupFunctions: {
commentAdded: (options, args) =>
payload => payload.repository_name === args.repoFullName,
},
});
The example from the main readme of this repo confused me even more. The subscription name is commentAdded
but the event name is newCommentsChannel
. How is the event name constructed? Do you simply append Channel
to the end of the operation name (newComments
in this case)? Isn't the operation name optional?
subscription newComments($repoName: String!){
commentAdded(repoName: $repoName) { # <-- this is the subscription name
id
content
createdBy {
username
}
}
}
Hello,
When defining setup functions like this :
setupFunctions: {
commentAdded: (options, args) => ({
newCommentsChannel: {
filter: comment => comment.repository_name === args.repoFullName,
},
}),
},
I might be wrong here, since I'm not really familiar with graphql-subscriptions
but I assume args
represents the graphql arguments passed into the subscription query.
Considering this query :
subscription CommentAdded {
commentAdded(feed: 1234) {
...
}
}
args
will be properly set to the expected value :
{ feed: 1234 }
However, when default arguments are defined in the schema like this :
type RootSubscription {
commentAdded(
feed: Int = 10
): Comment!
}
args
will not be set to { feed: 10 }
as one would expect.
args
is set to
{}
args
set to
{ feed: 10 }
I forked and created a failing test case demonstrating the issue. See here : kouak@820101a
Let me know if you want me to submit a PR with this failing test case.
In Readme - Payload Manipulation writing You can also manipulate the published payload.
But if I not set resolve method. There is a warning show me Resolve function missing for "Subscription.commentAdded". To disable this warning check https://github.com/apollostack/graphql-tools/issues/131
To resolve this I must set a passthrough function.
commentAdded: {
resolve: root => root,
subscribe: () => pubsub.asyncIterator('commentAdded')
}
Is this a bug or change readme to You must manipulate the published payload, by adding resovle methods to your subscription
Maybe I missed it, but it would be nice to see all the relevant pieces of the example, namely what the schema looks like.
Hi, I have warnings like
backend | [1] bk-app-dev | (node:2449) Warning: a promise was created in a handler at var/www/backend/node_modules/graphql-subscriptions/src/pubsub.ts:190:19 but was not returned from it, see http://goo.gl/rRqMUw
, but I can't figure out where throwed error.
Im using withFilter in my code
watchDevice: {
resolve: (payload) => payload,
subscribe: withFilter(() => pubsub.asyncIterator('updateDeviceLocation'), (payload, args) => {
console.log('---------P', payload)
console.log('---------A', args)
return payload.id === args.id;
}),
},
but the filter function is not being called, any idea?
Hi, for example - chat with rooms and private messages...
Also how to get all subscribers in the room?
Versions used :
When a subscription is created, event handlers are created and registered through the underlying EventEmitter class.
However, these event handlers are never removed leading to a memory leak.
Now, I don't know whether the bug lies in this repo or in subscriptions-transport-ws
as I'm not familiar enough with this codebase yet.
However, I managed to reproduce the issue in the Githunt-API example implementation.
My only change is to console.log
registered event handlers in the underlying EventEmitter object every 5 seconds.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.