-
Notifications
You must be signed in to change notification settings - Fork 340
allow using custom WebSocket server implementation #374
allow using custom WebSocket server implementation #374
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely see the value in being able to pass a custom websocket server! 💯
The API is kinda awkward, as you end up having to pass socketOptions
even though it's not used since you also pass your own server:
new SubscriptionServer({}, {}, customServer);
What about instead letting the second argument be either socketOptions
or a custom server?
new SubscriptionServer(options: ServerOptions, socket: WebSocket.ServerOptions | WebSocket)
That seems much nicer from the user side: either just pass options and it'll work, or if you need more control you can also pass your own server instead(!).
Hey Max! You are right. Let me tweak this tomorrow morning :) |
…an actual server instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, much better! Now it'd be great if you could add a note about this to the docs and the readme and we should be good to go.
@mxstbr I added some docs and examples - please let me know if this is a good direction. I can continue on this tomorrow. :) Thanks! |
The "works with custom WebSocket implementation" test fails on that latest commit, any clues why? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Readme doc update is 💯, but let's work on the website a bit more.
Currently it's a bit too personal, and also the example code shouldn't be everything that's needed ever, it should only demonstrate the core concepts. (creating a custom websocket server with mock-socket-with-protocol, passing that to the subscription server and writing the test) Mind revising that?
As per the failure.. looks like it's a rare timing issue, looks like 200 ms between firing the events and the assertion that the subscription data came back wasn't enough. I only updated Changelog so that couldn't affect the test. I can increase the timeout a bit. A nicer way of doing this might be to instead of having an assertion in a timeout to check that both subscriptions finished: if (result.data) {
numTriggers += 1;
assert.property(result.data, 'userFiltered'); (..)
if(numTriggers === 2) {
done()
}
} in both of them. This way the test would end the moment both subscriptions came back, instead of waiting a particular amount of time to verify that numOfTriggers is equal 2. I reused the pattern that's been established in the previous tests, but I don't think it's ideal to be honest. Website part - would you rather it not speak about apollo and have a test that's almost a copy paste of the one that I talked about above? I thought that the most typical use case would be nice to cover :) but I could change that into a blog post, and have more minimal info here. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ~what I'd like to see in terms of the example in the docs:
// we are not opening any ports - this example of WebSocket client/server uses string matching to know to what server connect a given client
// we should use different string for every test to not share state
const RANDOM_WS_PORT = Math.floor(Math.random() * 100000);
const customServer = new Server(`ws://localhost:${RANDOM_WS_PORT}`);
// We pass customServer instead of typical configuration of a default WebSocket server
SubscriptionServer.create(
{
schema,
execute,
subscribe
},
customServer
);
const wsLink = new WebSocketLink({
uri: `ws://localhost:${RANDOM_WS_PORT}`,
webSocketImpl: WebSocket
});
return new ApolloClient({
link: wsLink,
cache: new InMemoryCache()
});
};
test(
"subscription",
async done => {
gqClient()
.subscribe({
query: gql`
subscription {
somethingChanged
}
`
})
.subscribe({
next({ data }) {
expect(data.somethingChanged).toEqual("passedId");
done();
},
error(err) {
throw new Error(err);
}
});
setTimeout(() => {
pubsub.publish(SOMETHING_CHANGED_TOPIC, "passedId");
}, 100);
},
1000
);
Maybe?
The text should specify when to even use that code in the first place, rather than the "I" stuff.
I see, thanks for the feedback. I will take a look tomorrow. I get your point. I was torn here, obviously there is a lot of boiler code that's not related to the new functionality and it introduces a lot of noise.. On the other hand this is a piece of code that you can copy/paste and it works (assuming you install all the dependencies, but that's the easy part). Otherwise it might be a bit tricky to understand what all the parts are and how they connect with each other. |
…ki/subscriptions-transport-ws into serverWithCustmWebSocket
…ns-transport-ws into serverWithCustmWebSocket
I finally got some time to clean it up a bit. I hope that's better. On a different note - I'm also tempted to work on the tests, they are slow, and can't be parallelized. In mocha watch mode they take ~25 seconds to run, which is a rather suboptimal developer experience. :-) If it was up to me I'd:
Is this something you guys would consider merging? |
I'd be happy moving to jest as the testing framework. |
Same, I'd love to actually, but please do it in a separate PR! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM, @NeoPhi?
@mxstbr Yes, looks good. |
Ping :-) |
I have people asking me about this, even on apollo slack - is there any reason why this is not merged yet? Is there a different pattern for doing integration testing for subscriptions? |
@lgandecki Fell off the radar. Merging and releasing now. |
* commit '71dd1041242ac20553af0adad8ee001a25edfec3': release 0.9.11 allow using custom WebSocket server implementation (apollographql#374) update changelog header update dependencies (apollographql#427) Fix constructor signature (apollographql#419) Typo (apollographql#423) chore(deps): update dependency meteor-theme-hexo to v1.0.13 chore(deps): update dependency meteor-theme-hexo to v1.0.12 chore(deps): update dependency meteor-theme-hexo to v1.0.10 fix issue with @types/[email protected] chore(deps): update dependency hexo-server to v0.3.2 chore(deps): update dependency meteor-theme-hexo to v1.0.9 # Conflicts: # src/client.ts
Question please, how do you pass in the constant to publish for in
example subsscription server
Im trying to trigger a publish via pubsub but I am not piecing it all together |
Hello, this will allow me to write isolated integration tests for subscriptions.
My next step will be to create apollo-link-schema-with-subscriptions (open to a better name! :) ), so people can simply do:
And be able to use apolloClient as if it was connected to a websocket server (so they can do subscriptions as well)
Currently, with my fork of subscriptions-transport-ws in my test I do:
and it works like a charm :)