UpdateTracter to reconnect and and re-subscribe on close events #30
UpdateTracter to reconnect and and re-subscribe on close events #30
Conversation
First basic implementation of re-subscribing to resources when connection closes resubscribe with five attempts with 1 second backoff now with exponential backoff removed console log messages code style issues removed Increased to 6 attempts, also reset backoff times if connection succeeded Code style issue removed
Pull Request Test Coverage Report for Build 163
💛 - Coveralls |
src/UpdateTracker.js
Outdated
subscribers[url].delete(this.subscriber); | ||
delete subscribers[url]; | ||
delete webSockets[new URL(url).host]; |
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.
There is an issue here if there are multiple subscribed resources under the same domain. I'll change this to only delete if its the last resource with the domain.
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.
Hi @jholleran, thanks for the effort on this, especially the detailed unit tests.
The overall picture seems good, but I have some concerns here and there, which I have indicated with comments.
.gitignore
Outdated
@@ -3,3 +3,5 @@ dist | |||
lib | |||
module | |||
node_modules | |||
.idea/ | |||
*.iml |
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.
Would suggest to keep those in a personal .gitignore
.
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.
Reverted this change.
src/UpdateTracker.js
Outdated
subscribers[url].delete(this.subscriber); | ||
delete subscribers[url]; |
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.
The above will cause issues when there are multiple UpdateTracker
instances. The idea is that subscribers[url]
is shared across all UpdateTracker
instances, representing a set of all subscribed UpdateTracker
s. When unsubcribe
is on a single instance, it should subscribe only that instance.
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.
Reverted this change.
src/UpdateTracker.js
Outdated
subscribers[url].delete(this.subscriber); | ||
delete subscribers[url]; | ||
delete webSockets[new URL(url).host]; |
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 seems to cause issues when an UpdateTracker
is subscribed to two URLs from the same host, and we are only unsubscribing from one.
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.
Yeah I agree this was incorrect and I've reverted it.
src/UpdateTracker.js
Outdated
@@ -57,11 +60,17 @@ function trackResource(url) { | |||
if (!webSocket) { | |||
const socketUrl = `${protocol.replace('http', 'ws')}//${host}/`; | |||
webSockets[host] = webSocket = new WebSocket(socketUrl); | |||
const backOffDelay = delay || 1000; |
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.
Should we just call the function parameter backOffDelay
instead of delay
.
We can also initialize it as trackResource(url, retryAttempt = 0, backOffDelay = 1000)
.
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.
Done. I've moved the default initialization to the setBackoff function as trackResource is called in a number of places already.
src/UpdateTracker.js
Outdated
} | ||
|
||
webSocket.resources.push(url); // Storing URL of resouce that will be subscribed to |
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.
Typo; can we put the comment above the line, and perhaps clarify that we keep track of resources so we can resubscribe if needed?
Also, might want to make webSocket.resources
a Set
to avoid multiple subscriptions.
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.
Done.
src/UpdateTracker.js
Outdated
Object.assign(webSocket, { enqueue, onmessage, | ||
ready: new Promise(resolve => (webSocket.onopen = resolve)), | ||
onclose: oncloseFor(host), | ||
resources: [], |
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.
Might want to make resources
a Set
to avoid multiple re-subscriptions.
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.
Done.
src/UpdateTracker.js
Outdated
function setUpBackOff(webSocket, retryAttempt, backOffDelay) { | ||
Object.assign(webSocket, { | ||
delay: backOffDelay, | ||
backoff: new Promise(resolve => (setTimeout(resolve, backOffDelay))), |
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.
Given that backoff
always seems to wait delay
seconds, is it necessary to assign this as a function to the socket? Could we just do the waiting directly here https://github.com/solid/react-components/pull/30/files#diff-b2ffa2da88905c291381e2f58b66eb35R115 ?
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.
Yes. This is a lot clearer moving it out of here.
256c9de
to
12fce38
Compare
Hi @jholleran, I spent some time with the code, and simplified it down to 341ec20. However, while doing so, I noticed this case: 12fce38 I think this is an error in the tests, but wanted to verify with you. |
Yes, this is an error in the tests. If you run the two failing tests individually they will pass but when the full UpdateTracker-test suite runs they will fail. The problem here is the webSocket array that is used in the test will hold the created WebSockets from the previous tests. If the webSockets array is cleared before each test then there would be no WS to call the This was one thing that I struggled with writing them tests. It would be great to tidy this up a bit and have the test totally isolated. That was the reason that I was removing WS's on unsubscribe so that I could remove all and test on a clean slate (but this caused a bigger problem as I shouldn't have been deleting them). |
Got it, thanks. Will add a reset function for testing purposes. |
12fce38
to
11de002
Compare
8333fb6
to
b7e8cad
Compare
b7e8cad
to
c67e3ff
Compare
c67e3ff
to
6ba0506
Compare
Thanks @jholleran! |
Resolves: #29
Kind of change
Proposed changes
Resubscribing to resources when Websocket connection closes. It will make 6 retry attempts with a exponential back-off time (1, 2, 4, 8, 16, 32 seconds) in between each attempt.
Also, as part of this PR it fixes an issue when unsubscribing from resources it will now allow the same resources to be fully subscribed again.
Relevant issues
Breaking change?
Requirements check
Additional info