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

feat: allow stringifyResult to return a Promise<string> #7803

Conversation

favna
Copy link
Contributor

@favna favna commented Dec 14, 2023

Previously stringifyResult had to be synchronous, despite only ever being called from the async context of runHttpQuery. This is an issue when the custom stringification function provided by the user through the constructor has to be async, for example when working with very large POJOs one could use json-stream-stringify because JSON.stringify would throw a RangeError with Invalid string length, the implementation using this library would be:

    stringifyResult: async (value) => {
      const stringifyStream = new JsonStreamStringify(value);
      let stringified = '';

      for await (const chunk of stringifyStream) {
        stringified += chunk;
      }

      return `${stringified}\n`;
    }

As can be seen here, this requires an async context within the callback function. @apollo/server can easily support this by awaiting the result of internals.stringifyResult.

Furthermore I also changed errorResponse to use the same internals.stringifyResult for consistency of how the JSON that will be sent to the requester is stringified.

@apollo-cla
Copy link

@favna: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/

Copy link

netlify bot commented Dec 14, 2023

👷 Deploy request for apollo-server-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit d7bf521

Copy link

codesandbox-ci bot commented Dec 14, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit d7bf521:

Sandbox Source
Apollo Server Typescript Configuration
Apollo Server Configuration

Copy link
Member

@trevor-scheer trevor-scheer left a comment

Choose a reason for hiding this comment

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

Overall the change looks good to me. I agree with supporting the async use case here, and we probably should've made it async in the first place. I also agree not updating the errorResponse function was an oversight in the original PR, so I'm comfortable with treating this as a bugfix rather than a breaking change in how stringifyResult works.

I have a couple requests:

  • Please mention the bugfix / change in behavior of errorResponse in the changeset. It would be helpful to note who would be affected and what the expected behavior change is (i.e. "Users who implement the stringifyResult hook can now expect their error responses to be formatted with the hook as well. Please take care when updating to this version to ensure this is desired behavior, or implement the desired behavior accordingly in your stringifyResult hook.")
  • Can you please add a test to exercise the new stringifyResult + error case?

This one's a bit more theoretical and wordy. I think the change to making errorResponse async requires the addition of await at all callsites. While we don't have any tests that catch the issue I'm imagining, I do think there's a change in behavior here if we don't await them. Right now those callsites are wrapped in try/catch blocks. If we return the promise (as we're doing now), we "escape" the try/catch, leaving a promise rejection to be handled elsewhere. If we await those calls, the catch block will execute resulting in no behavior change from what exists now.

I found a blog posts that articulates precisely what I was thinking.
https://jakearchibald.com/2017/await-vs-return-vs-return-await/#return-awaiting

@favna
Copy link
Contributor Author

favna commented Dec 18, 2023

Addressed your review comments @trevor-scheer. In regards to the return await matter for which you linked the Jake Archibald blogpost, luckily I'm well aware of how the JS event loop handles that kinda stuff so I immediately knew what you were referring to :) (bless Jake Archibald btw, absolute genius). I believe I have covered your requests now.

Copy link
Member

@trevor-scheer trevor-scheer left a comment

Choose a reason for hiding this comment

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

Sorry about the cspell, I would've also accepted adding behaviour to the dictionary. Honestly surprised it didn't like that in the first place. Thanks for making those changes, this lgtm. I appreciate the PR!

@favna
Copy link
Contributor Author

favna commented Dec 18, 2023

Haha, no problem at all on the cspell. I actually chuckled to see CircleCI fail there. No need to apologise. Thanks for the approval!

@trevor-scheer
Copy link
Member

Apologise...funny guy 😜

@trevor-scheer trevor-scheer merged commit e9a0d6e into apollographql:main Dec 18, 2023
16 checks passed
@github-actions github-actions bot mentioned this pull request Dec 18, 2023
@favna favna deleted the feat/allow-stringifyresult-to-return-a-promise branch December 18, 2023 22:19
@favna
Copy link
Contributor Author

favna commented Dec 28, 2023

@trevor-scheer Hi there, I would like to ask you about the release schedule for Apollo Server. Specifically, when will 4.10.0 be released so I can use it in my project? The contributing.md file mentions a file roadmap.md but that file no longer exists so I have no information on this topic.

trevor-scheer pushed a commit that referenced this pull request Jan 2, 2024
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @apollo/server-integration-testsuite@4.10.0

### Minor Changes

- [#7786](#7786)
[`869ec98`](869ec98)
Thanks [@ganemone](https://github.com/ganemone)! - Restore missing v1
`skipValidation` option as `dangerouslyDisableValidation`. Note that
enabling this option exposes your server to potential security and
unexpected runtime issues. Apollo will not support issues that arise as
a result of using this option.

### Patch Changes

- [#7740](#7740)
[`fe68c1b`](fe68c1b)
Thanks [@barnisanov](https://github.com/barnisanov)! - Uninstalled
`body-parser` and used `express` built-in `body-parser` functionality
instead(mainly the json middleware)

- Updated dependencies
\[[`869ec98`](869ec98),
[`9bd7748`](9bd7748),
[`63dc50f`](63dc50f),
[`fe68c1b`](fe68c1b),
[`e9a0d6e`](e9a0d6e)]:
    -   @apollo/server@4.10.0

## @apollo/server@4.10.0

### Minor Changes

- [#7786](#7786)
[`869ec98`](869ec98)
Thanks [@ganemone](https://github.com/ganemone)! - Restore missing v1
`skipValidation` option as `dangerouslyDisableValidation`. Note that
enabling this option exposes your server to potential security and
unexpected runtime issues. Apollo will not support issues that arise as
a result of using this option.

- [#7803](#7803)
[`e9a0d6e`](e9a0d6e)
Thanks [@favna](https://github.com/favna)! - allow `stringifyResult` to
return a `Promise<string>`

Users who implemented the `stringifyResult` hook can now expect error
responses to be formatted with the hook as well. Please take care when
updating to this version to ensure this is the desired behavior, or
implement the desired behavior accordingly in your `stringifyResult`
hook. This was considered a non-breaking change as we consider that it
was an oversight in the original PR that introduced `stringifyResult`
hook.

### Patch Changes

- [#7793](#7793)
[`9bd7748`](9bd7748)
Thanks [@bnjjj](https://github.com/bnjjj)! - General availability of
subscription callback protocol

- [#7799](#7799)
[`63dc50f`](63dc50f)
Thanks [@stijnbe](https://github.com/stijnbe)! - Fix type of
ApolloServerPluginUsageReporting reportTimer

- [#7740](#7740)
[`fe68c1b`](fe68c1b)
Thanks [@barnisanov](https://github.com/barnisanov)! - Uninstalled
`body-parser` and used `express` built-in `body-parser` functionality
instead(mainly the json middleware)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@glasser
Copy link
Member

glasser commented Jan 3, 2024

@favna Most of Apollo was on vacation last week, but Trevor has now released this in Apollo Server 4.10.0!

@favna
Copy link
Contributor Author

favna commented Jan 3, 2024

@glasser Totally understandable, I hope you guys had nice holidays and best wishes for the new year. I was pinged by the GitHub bot yesterday so I noticed and I have since updated my application. Many thanks for the Apollo project!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants