Skip to content
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

Ensure All Newsletters page is async #26873

Merged
merged 2 commits into from
Feb 5, 2024

Conversation

cemms1
Copy link
Contributor

@cemms1 cemms1 commented Feb 5, 2024

What is the value of this and can you measure success?

We're getting lots of errors on the facia app since directing the DCR requests for /EmailNewsletters to facia-rendering, so this refactors the code to render the all newsletters page and (hopefully) fixes an issue with a blocking operation.

What does this change?

  • Updates the SignupPageController to be Action.async rather than just Action and as such, swaps the return types to be Future[Result] instead of just Result.
  • Removes Await from the DCR request code, along with the max duration of 3 seconds.
    In the docs for Await it says:

    While occasionally useful, e.g. for testing, it is recommended that you avoid Await whenever possible— instead favoring combinators and/or callbacks. Await's result and ready methods will block the calling thread's execution until they return, which will cause performance degradation, and possibly, deadlock issues.

Comment on lines +104 to +118
def renderNewsletters()(implicit
executionContext: ExecutionContext = this.executionContext,
): Action[AnyContent] =
csrfAddToken {
Action { implicit request =>
if (request.forceDCR || UseDcrNewslettersPage.isSwitchedOn) {
renderDCRNewslettersJson()
} else {
renderNewslettersJson()
Action.async { implicit request =>
val useDCR = request.forceDCR || UseDcrNewslettersPage.isSwitchedOn

request.getRequestFormat match {
case HtmlFormat if useDCR =>
remoteRenderNewslettersPage()
case HtmlFormat =>
localRenderNewslettersPage()
case JsonFormat if useDCR =>
renderDCRNewslettersJson()
case _ => notFoundPage()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function combines request handling for both JSON and HTML requests, removing some duplicated code above and (I believe) making it a bit easier to read.

}
case Left(e) =>
log.error(s"API call to get newsletters failed: $e")
throw new RuntimeException()
}
}

private def renderNewslettersJson()(implicit
private def notFoundPage()(implicit
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Named more appropriately, I think? Might have got the wrong end of the stick though...

Comment on lines -78 to -89
def renderNewslettersPage()(implicit
executionContext: ExecutionContext = this.executionContext,
): Action[AnyContent] =
csrfAddToken {
Action { implicit request =>
if (request.forceDCR || UseDcrNewslettersPage.isSwitchedOn) {
remoteRenderNewslettersPage()
} else {
localRenderNewslettersPage()
}
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved into generic renderNewsletters function at bottom of page which handles both JSON and HTML and DCR / non DCR requests

@cemms1 cemms1 marked this pull request as ready for review February 5, 2024 15:16
@cemms1 cemms1 requested a review from a team as a code owner February 5, 2024 15:16
Comment on lines -64 to -70
Await.result(
remoteRenderer.getEmailNewsletters(
ws = wsClient,
newsletters = newsletters,
page = StaticPages.dcrSimpleNewsletterPage(request.path),
),
3.seconds,
Copy link
Contributor Author

@cemms1 cemms1 Feb 5, 2024

Choose a reason for hiding this comment

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

I think the presence of this extra Await could be the reason why the DCR circuit breaker keeps opening. The DotcomRenderingService has a timeout of 2 seconds so looks like this could be potentially blocking operations for one second after the DCR timeout and before the Await atMost duration of 3 seconds?

@cemms1 cemms1 self-assigned this Feb 5, 2024
@cemms1 cemms1 added this to the Health milestone Feb 5, 2024
Copy link
Contributor

@mxdvl mxdvl left a comment

Choose a reason for hiding this comment

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

This seems a lot more consistent with the other controllers!

} else {
renderNewslettersJson()
Action.async { implicit request =>
val useDCR = request.forceDCR || UseDcrNewslettersPage.isSwitchedOn
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a blocker as this is the current behaviour, but with this logic, it’s impossible to force DCR off when the UseDcrNewslettersPage switch is on.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, yep you're right. I actually wonder if that's intentional as the frontend newsletters page is VERY different to the DCR one 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

🤷

@cemms1 cemms1 merged commit af8c538 into main Feb 5, 2024
2 checks passed
@cemms1 cemms1 deleted the cemms1/refactor-newsletters-page-futures branch February 5, 2024 16:34
@prout-bot
Copy link
Collaborator

Seen on FRONTS-PROD (merged by @cemms1 12 minutes and 14 seconds ago)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants