-
Notifications
You must be signed in to change notification settings - Fork 555
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
Use JsValue
Not String
For DCAR
#27641
Conversation
Lovely stuff! I see the tests have failed, but from a quick look at the logs, maybe the only failing test was
...this is because the test is mocking the frontend/common/test/renderers/DotcomRenderingServiceTest.scala Lines 38 to 55 in 55da434
Incidentally, it was quite hard to search the logs for the failure. Using something like https://github.com/test-summary/action or https://github.com/EnricoMi/publish-unit-test-result-action could make finding failing tests on Frontend much friendlier? |
Updated our test config to output test summary files. Added a step to the `build` workflow in GitHub actions to read from these files and output a summary in the GitHub UI.
Frontend posts the data for articles, fronts, tags pages and so on to DCAR as JSON, using `WSClient`. At the moment the following steps are taken to transform from an instance of a case class in frontend to the format that `WSClient` uses (`BodyWritable`): ``` case class instance -> JsValue -> String -> BodyWritable ``` The final transformation here, `String -> BodyWritable`, is handled by `WSClient`, as it defines an implicit way to get from one type to the other. However, it also defines a way to do this for a `play-json` `JsValue`, so we do not need to convert to a `String` beforehand. We should be able to pass a `JsValue` to `WSClient` directly, removing one of the transformation steps: ``` case class instance -> JsValue -> BodyWritable ``` The way to achieve this is by modifying our methods that use `WSClient.post` to take a `JsValue` payload instead of a `String`. We are then able to update the `toJson` methods on each of our models to remove the `Json.stringify` step. However, aside from `RemoteRender` requests, these `toJson` methods are also used to provide for `JsonFormat` requests via the `renderJson` method, which at the moment requires a `String`. This method, though, makes use of Play's `Writeable`, which also includes an implicit transformation to get from a `play-json` `JsValue`. So we can update it to take a `JsValue` instead, and save the additional `String` transformation step here too. Note that there is one exception where we're using `circe` instead of `play-json`, for crosswords, so in that case we're transforming from one to the other via `String`.
f824ae2
to
dcd3e5c
Compare
Thanks @JamieB-gu and @rtyley this sounds good to me. I'm not fully clued up on the full impact of this change, and it's possible future travellers will want to know, so I was hoping you could answer for the record:
Thanks in advance 🙏 |
Thanks @SiAdcock! To answer the questions:
|
The Playframework hides away the existence
Can't think of any negatives - the code is more strongly-typed, and the copying operations look to be more efficient because they're not doing unnecessary array-copying! |
Seen on ADMIN-PROD (merged by @JamieB-gu 12 minutes and 4 seconds ago)
|
Seen on FRONTS-PROD (merged by @JamieB-gu 13 minutes and 9 seconds ago)
|
I've taken a quick look at the graphs after this got merged at 1:07pm - I was wondering if garbage collection might have noticeably improved due to these changes, and unfortunately there's been no obvious overall change, at least not yet. Still, I think the change is still justified in terms of code clarity! |
Frontend posts the data for articles, fronts, tags pages and so on to DCAR as JSON, using
WSClient
. At the moment the following steps are taken to transform from an instance of a case class in frontend to the format thatWSClient
uses (BodyWritable
):The final transformation here,
String -> BodyWritable
, is handled byWSClient
, as it defines an implicit way to get from one type to the other1. However, it also defines a way to do this for aplay-json
JsValue
2, so we do not need to convert to aString
beforehand. We should be able to pass aJsValue
toWSClient
directly, removing one of the transformation steps:The way to achieve this is by modifying our methods that use
WSClient.post
to take aJsValue
payload instead of aString
. We are then able to update thetoJson
methods on each of our models to remove theJson.stringify
step. However, aside fromRemoteRender
requests, thesetoJson
methods are also used to provide forJsonFormat
requests via therenderJson
method, which at the moment requires aString
. This method, though, makes use of Play'sWriteable
, which also includes an implicit transformation to get from aplay-json
JsValue
3. So we can update it to take aJsValue
instead, and save the additionalString
transformation step here too.Note that there is one exception where we're using
circe
instead ofplay-json
, for crosswords, so in that case we're transforming from one to the other viaString
.Paired with @rtyley
Footnotes
https://www.playframework.com/documentation/3.0.x/api/scala/play/api/libs/ws/WSBodyWritables$.html#writeableOf_String:play.api.libs.ws.BodyWritable[String] ↩
https://www.playframework.com/documentation/3.0.x/api/scala/play/api/libs/ws/WSBodyWritables$.html#writeableOf_JsValue:play.api.libs.ws.BodyWritable[play.api.libs.json.JsValue] ↩
https://www.playframework.com/documentation/3.0.x/api/scala/play/api/http/Writeable$.html#writeableOf_JsValue:play.api.http.Writeable[play.api.libs.json.JsValue] ↩