Skip to content
This repository has been archived by the owner on Nov 27, 2017. It is now read-only.

Use the new Server Side Event support in ipaas-rest to automatically reload updated entity lists. #186

Merged
merged 1 commit into from Feb 28, 2017

Conversation

chirino
Copy link
Contributor

@chirino chirino commented Feb 22, 2017

Works in conjunction with the following PR:
syndesisio/syndesis-rest#115

@jimmibot
Copy link

@chirino, thanks! @kahboom, please review this.

@jimmidyson
Copy link
Contributor

@dsimansk @jludvice Stuff like this EventSource usage highlights the need for cross-browser test suites... Please have a think about how we can do that.

@chirino
Copy link
Contributor Author

chirino commented Feb 23, 2017

retest this please

@jimmidyson
Copy link
Contributor

Does EventSource support authorization headers? Our REST API currently only authenticates via validation of JWT contained in authorization header...

@chirino
Copy link
Contributor Author

chirino commented Feb 23, 2017

@jimmidyson Looks we have to pass it via cookies.. is that a deal breaker for SSE?

Copy link
Contributor

@kahboom kahboom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chirino That'd be a no-go for IE support out of the box (this is pretty useful for determining what you can use), but check out this polyfill. Honestly, I say we get rid of the WS (WSS preferably), use SSE from the REST API and a really nice service in the UI to update the model on an as-needed basis via regular HTTP requests.

Basically, I think we only really need one or the other, not both. And if I had to choose, I'd normally go with Websockets, but in this case SSEs may make more sense. It's not without its caveats though. On the Java side, SSE allows you to override the header, but JS side you can't. A way around that is to use query parameters. Not my best idea, but, hey.

SSE does use regular HTTP, so the polyfill may be worth looking into. If we went with Websockets we'd really not be taking advantage of client > server communication because we don't need to (unless we of course decide to add a chat or something of that nature). As much as I like working with Websockets and its quirky complexities I don't see the benefit of dealing with it in this case. We'd mostly be looking for responses from the server, not bi-directional communication in realtime.

An example of what we need is that the client be notified when we delete a connection or integration, which could take a while for a 'delete completed' response from the server. Again, I'd usually opt for Websockets for specific events like this, not something like arbitrarily updating the server on any model change. And with the polyfill we just don't need it.

For most client > server model updates (e.g. creating a connection) we can just send manual HTTP requests, not leaving connections open as with Websockets, constantly checking for connection/disconnection. This will also be a pain when it comes to checking user inactivity later on. SSEs offer a ton of relevant things that WebSockets don't by design, like automatic reconnection, event IDs, and the ability to send arbitrary events.

Keep in mind that I'm more comfortable using Websockets, but I mean, it should be more about the right tool for the job I think? WDYT @chirino @jimmidyson ?


get resource() { return this._current.asObservable(); }
get resource() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this was you or ts-lint.json, but either way, ty.

@kahboom
Copy link
Contributor

kahboom commented Feb 23, 2017

If something doesn't make sense in my comment, just know I'm running on 3 hours of sleep, which may or may not be relevant. ;D

@kahboom
Copy link
Contributor

kahboom commented Feb 23, 2017

Even better, a Node.js implementation that can be used to override headers from the "JS side", polyfill included: eventsource

@chirino
Copy link
Contributor Author

chirino commented Feb 23, 2017

@kahboom, @jimmidyson I think SSE security should be sorted now without needing to do the cookie thing. Basically I first do a POST to request a event stream ID, at that point the user is associated with the stream, and then then we setup the SSE connection against that registered stream id (a random UUID) which does not get re-used.

I kind like the SSE first then fallback to WS scenario, since if we ever move to HTTP2, then we are using the preferred strategy to begin with.

also take a peek at:
http://caniuse.com/#feat=eventsource
http://caniuse.com/#feat=websockets

Notice we would be using SSE on most browsers except IE and Edge, and both have good WebSocket support.

@kahboom
Copy link
Contributor

kahboom commented Feb 23, 2017

Yeah Websockets have the advantage of wider browser support. I'm not opposed to falling back on WS, or at least don't feel strongly about it. @jimmidyson I'd like to hear your thoughts on this. @chirino once tests are resolved I'll approve it, then merge based on what Jimmi prefers.

@jimmidyson
Copy link
Contributor

add to whitelist

// , fallback to using a WebSocket
let wsurl = config.getSettings().apiEndpoint;
// I know hacky! need to figure out how to put the wsevents resource under the apiEndpoint
wsurl = wsurl.replace( /^https?/, 'ws' ).replace( /\/api\/v\d+$/, '/wsevents' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would always fall back to insecure ws rather than wss if https is used

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we'd absolutely need WSS considering we'd be opening connections quite frequently if it's to update models on any change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix in a bit.

@kahboom
Copy link
Contributor

kahboom commented Feb 24, 2017

Providing Websocket support as a fallback means we would need to maintain it along with the SSE implementation as the application scales, otherwise it'd be for naught. Just something to consider, but again, not opposed to it at all.

Copy link
Contributor

@jimmidyson jimmidyson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, minor issues need updating. Will probably need tweaking once we start using it properly.

@@ -0,0 +1,90 @@
import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import {UUID} from 'angular2-uuid';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep.. don't need the uuid anymore. hangover from previous iteration.

@jimmidyson
Copy link
Contributor

Can't remember if the server side even supports websockets right now - @chirino?

@kahboom
Copy link
Contributor

kahboom commented Feb 24, 2017

@jimmidyson - Now it does I believe, see syndesisio/syndesis-rest#115. More specifically.

@kahboom kahboom added this to In Progress in Syndesis UI Feb 24, 2017
@kahboom
Copy link
Contributor

kahboom commented Feb 24, 2017

Also of relevance #114 .

@kahboom kahboom added this to the Sprint 9 milestone Feb 24, 2017
@chirino
Copy link
Contributor Author

chirino commented Feb 24, 2017

Squashed and rebased off master.

@chirino
Copy link
Contributor Author

chirino commented Feb 24, 2017

@kahboom, @jimmidyson: yep ipaas-reset supports both SSE and WebSockets.

// , fallback to using a WebSocket
let wsurl = config.getSettings().apiEndpoint;
// I know hacky! need to figure out how to put the wsevents resource under the apiEndpoint
wsurl = wsurl.replace( /^http/, 'ws' ).replace( /\/api\/v\d+$/, '/wsevents' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this is a bit pants and means we need to set up another subpath route in openshift. what's the problem putting it under the API endpoint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that's what I initially tried but the websocket handler would not trigger if not at a top level path. Not sure why yet. Perhaps if I use a different WS handling strategy it might work better (I'm currently using the SB abstractions).

…matically reload updated entity lists.

(cherry picked from commit a000eb5)
@jimmidyson
Copy link
Contributor

@kahboom Are you happy with this? LGTM

Copy link
Contributor

@kahboom kahboom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for fixing the tests. 👍

@kahboom kahboom merged commit 81d4fbc into syndesisio:master Feb 28, 2017
@kahboom kahboom moved this from In Progress to Sprint 9 Release Candidate/Complete in Syndesis UI Mar 1, 2017
@kahboom kahboom removed this from Sprint 9 Release Candidate/Complete in Syndesis UI Oct 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants