-
Notifications
You must be signed in to change notification settings - Fork 280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comet Rehydration #1770
Comet Rehydration #1770
Conversation
…g the toWatch directly from the HTML
…ence the browser will not attempt to run any scripts
I vote for marking codacy's complaint about cyclomatic complexity as |
Hey @joescii - what are your thoughts on the stability of this? Is this something that could potentially be included in 3.1 or nah? |
Going to drop the milestone here. We can restore it when timelines are a little clearer, I think. |
@joescii I see you've been periodically merging master here. LMK When you think it's ready for review/ testing |
if (!dataType) { | ||
dataType = "script"; | ||
} | ||
|
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.
@Shadowfiend This is the change I was talking about in this ML thread https://groups.google.com/forum/#!topic/liftweb/KdH4kgZ-5ug
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.
Because Javascript, this change is backward compatible. I don't think we have to worry too much about this change so long as the dataType
check works as we expect.
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.
Have some changes to request, but it looks promising!
iframe.appendChild(doc); | ||
doc.innerHTML = html; | ||
|
||
toWatch = {}; |
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.
Is this attached to window or a lift object on the window?
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.
It's declared up at the top at line 20
restartComet(); | ||
|
||
// Under the impression that a parentless node needn't be deleted. | ||
// It should be a candidate for GC after it goes out of scope |
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 think this is right. We should be able to remove this comment.
} | ||
function onFailure(err) { | ||
// Try again?? | ||
settings.logError(err); |
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.
Could we fall back to the classic comet refresh method? (Reloading the page?)
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.
Do you think we should hard code a refresh here, or make it a LiftRules
setting?
cometActor.parentTag.copy(child = cometHtml) % ("id" -> containerId) | ||
private [this] def buildContainer(cometHtml: NodeSeq, cometActor: LiftCometActor, containerId: String): NodeSeq = { | ||
val cometVersion = http.S.requestCometVersions.is | ||
.collectFirst { case CometVersionPair(guid, ver) if guid == cometActor.uniqueId => ver } |
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.
Please break this into multiple lines for readability.
.collectFirst { case CometVersionPair(guid, ver) if guid == cometActor.uniqueId => ver } | ||
.getOrElse("") | ||
|
||
cometActor.parentTag.copy(child = cometHtml) % ("id" -> containerId) % ("data-lift-comet-version" -> cometVersion) |
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.
Please break this into multiple lines for readability.
var iframe = document.createElement("iframe"); | ||
var doc = document.createElement("html"); | ||
iframe.appendChild(doc); | ||
doc.innerHTML = html; |
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.
Just a reminder to be very careful about where the html
value in this method comes from. My understanding is that our risk here is pretty minor as doc
andiframe
are never attached to the page, but whenever I see it in a PR I gotta mention it.
(Old habits die hard.)
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, this is fundamental to the design of this feature. Essentially we reload the page from Lift, and steal all of the comet IDs from the resulting HTML.
if (!dataType) { | ||
dataType = "script"; | ||
} | ||
|
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.
Because Javascript, this change is backward compatible. I don't think we have to worry too much about this change so long as the dataType
check works as we expect.
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 took this out for a spin and it worked like a charm!
How would you feel about providing a helper in LiftRules
that makes the correct changes to the configuration? Something like...
LiftRules.enableCometRehydration()
What do you think?
Side note: I'd love to ship this next month as a part of 3.2.0-RC1 if you feel comfortable with it.
❗️ |
@farmdawgnation I dig that idea. So basically something like
|
Yup! |
@joescii Bump! We have about 10 days to get this in for the RC! :) |
LiftRules.redirectAsyncOnSessionLoss = false | ||
LiftRules.noCometSessionCmd.default.set(() => JsCmds.Run("lift.rehydrateComets()")) | ||
} | ||
|
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.
@farmdawgnation @Shadowfiend I feel like the hardest part to get right here is the comment...
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 think that the comment strikes the right chord overall. The one guidance we might add would be to say that you should code applications depending on this behavior to be able to reconstruct comet state from cookies or from information available from the client (e.g. JS state, state stores, etc)
If you feel like that would be a good addition I say add it. Otherwise, I'm going to approve this 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.
Comment updated
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.
As discussed on this ML thread, comet rehydration is another step towards supporting Lift server instance failover.
This feature is DISABLED by default. It can be enabled with these two lines in
Boot
:Rehydrating comets works by refetching the html from the Lift server. The html is slapped into an
iframe
and scraped for the comet GUID and version pairs. ThetoWatch
is replaced with the new comet pairs effectively allowing the newly created comets to take over.As with the LiftRules.putAjaxFnsInContainerSession PR, this feature can be exercised with this project but using the
/comet
page.