strawberry
strawberry copied to clipboard
Defer
Another attempt :D
Summary by Sourcery
Implement experimental incremental execution in the GraphQL schema to support deferred and streamed responses. Refactor the async run method to handle incremental execution results. Add end-to-end tests for Apollo and Relay clients, and introduce a new CI workflow for running these tests.
New Features:
- Introduce experimental incremental execution support in the GraphQL schema, allowing for deferred and streamed responses.
Enhancements:
- Refactor the async run method to handle GraphQLIncrementalExecutionResults, enabling streaming responses for incremental execution.
CI:
- Add a new GitHub Actions workflow for running end-to-end tests using Playwright.
Documentation:
- Add a README file for the e2e directory, providing setup and configuration instructions for React, TypeScript, and Vite.
Tests:
- Add end-to-end tests for GraphQL queries using Apollo and Relay clients, including tests for deferred and streamed responses.
Reviewer's Guide
Integrates experimental incremental GraphQL execution by switching to graphql-coreβs experimental_execute_incrementally when enabled; adds multipart streaming support in the async HTTP view; extends schema definitions and printer to include @defer and @stream directives; introduces Streamable annotations; and adds comprehensive incremental tests and E2E suites with a dedicated CI workflow.
Sequence diagram for incremental execution and streaming HTTP response
sequenceDiagram
participant Client
participant AsyncBaseView
participant Schema
participant experimental_execute_incrementally
participant GraphQLIncrementalExecutionResults
Client->>AsyncBaseView: HTTP GraphQL request
AsyncBaseView->>Schema: execute(...)
Schema->>experimental_execute_incrementally: execute if incremental enabled
experimental_execute_incrementally-->>Schema: GraphQLIncrementalExecutionResults
Schema-->>AsyncBaseView: GraphQLIncrementalExecutionResults
AsyncBaseView->>AsyncBaseView: stream() (yields multipart chunks)
AsyncBaseView-->>Client: multipart/mixed streaming response
ER diagram for BlogPost, Comment, and Author (E2E test schema)
erDiagram
BLOGPOST ||--o{ COMMENT : has
COMMENT }o--|| AUTHOR : written_by
BLOGPOST {
ID id
STRING title
STRING content
}
COMMENT {
ID id
STRING content
}
AUTHOR {
ID id
STRING name
}
Class diagram for Streamable and related types
classDiagram
class StrawberryStreamable
class Streamable {
<<Annotated[AsyncGenerator[T, None], StrawberryStreamable()]>>
}
class AsyncGenerator
class T
Streamable --|> AsyncGenerator : Annotated
Streamable --* StrawberryStreamable : Annotated
Streamable ..> T : generic
Class diagram for incremental execution integration in Schema
classDiagram
class Schema {
+execute(...)
+execute_sync(...)
+_handle_execution_result(...)
+_parse_and_validate_async(...)
-_schema
-config
}
class StrawberryConfig {
+enable_experimental_incremental_execution: bool
}
class GraphQLIncrementalExecutionResults
class experimental_execute_incrementally
Schema --> StrawberryConfig : config
Schema ..> GraphQLIncrementalExecutionResults : uses
Schema ..> experimental_execute_incrementally : uses
File-Level Changes
| Change | Details | Files |
|---|---|---|
| Implement HTTP streaming of incremental GraphQL results |
|
strawberry/http/async_base_view.pystrawberry/http/__init__.py |
| Integrate experimental incremental execution into schema execution |
|
strawberry/schema/schema.py |
| Introduce Streamable annotation support |
|
strawberry/streamable.pystrawberry/annotation.pystrawberry/schema/_graphql_core.py |
| Extend schema printer to include defer and stream directives |
|
strawberry/printer/printer.py |
| Add end-to-end and incremental test suites with CI workflow |
|
.github/workflows/e2e-tests.ymle2e/tests/http/incremental/ |
Possibly linked issues
- #2567: The PR implements first-class support for @stream/@defer, matching the issue's main requirements and initial steps.
- #3082: The PR implements support for @stream and @defer, directly addressing the issue's request for these features.
Tips and commands
Interacting with Sourcery
- Trigger a new review: Comment
@sourcery-ai reviewon the pull request. - Continue discussions: Reply directly to Sourcery's review comments.
- Generate a GitHub issue from a review comment: Ask Sourcery to create an
issue from a review comment by replying to it. You can also reply to a
review comment with
@sourcery-ai issueto create an issue from it. - Generate a pull request title: Write
@sourcery-aianywhere in the pull request title to generate a title at any time. You can also comment@sourcery-ai titleon the pull request to (re-)generate the title at any time. - Generate a pull request summary: Write
@sourcery-ai summaryanywhere in the pull request body to generate a PR summary at any time exactly where you want it. You can also comment@sourcery-ai summaryon the pull request to (re-)generate the summary at any time. - Generate reviewer's guide: Comment
@sourcery-ai guideon the pull request to (re-)generate the reviewer's guide at any time. - Resolve all Sourcery comments: Comment
@sourcery-ai resolveon the pull request to resolve all Sourcery comments. Useful if you've already addressed all the comments and don't want to see them anymore. - Dismiss all Sourcery reviews: Comment
@sourcery-ai dismisson the pull request to dismiss all existing Sourcery reviews. Especially useful if you want to start fresh with a new review - don't forget to comment@sourcery-ai reviewto trigger a new review!
Customizing Your Experience
Access your dashboard to:
- Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.
Getting Help
- Contact our support team for questions or feedback.
- Visit our documentation for detailed guides and information.
- Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.
Apollo Federation Subgraph Compatibility Results
| Federation 1 Support | Federation 2 Support | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Learn more:
Codecov Report
Attention: Patch coverage is 57.49235% with 139 lines in your changes missing coverage. Please review.
Project coverage is 94.40%. Comparing base (
6f5c600) to head (bf42f98).
Additional details and impacted files
@@ Coverage Diff @@
## main #3819 +/- ##
==========================================
- Coverage 94.76% 94.40% -0.36%
==========================================
Files 520 527 +7
Lines 33971 34230 +259
Branches 1760 1785 +25
==========================================
+ Hits 32193 32316 +123
- Misses 1497 1625 +128
- Partials 281 289 +8
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
CodSpeed Performance Report
Merging #3819 will not alter performance
Comparing feature/defer (bf42f98) with main (6f5c600)
Summary
β
26 untouched benchmarks
Pre-release
:wave:
Pre-release 0.276.0.dev.1752831589 [830ca949678760ed2e883a7768bc7fa97351cee9] has been released on PyPi! :rocket: You can try it by doing:
poetry add strawberry-graphql==0.276.0.dev.1752831589
/pre-release
β‘οΈ Codeflash found optimizations for this PR
π 100% (1.00x) speedup for process_result in strawberry/http/__init__.py
β±οΈ Runtime : 1.78 millisecond β 892 microseconds (best of 28 runs)
I created a new dependent PR with the suggested changes. Please review:
-
#3827
If you approve, it will be merged into this PR (branch feature/defer).
/pre-release
Did a quick test on this and fairly sure I've got the following crash. Its possible I've misconfigured something, but this is best understanding on how to enable it
This PR is now faster! π @patrick91 accepted my optimizations from:
- #3827
This PR is now faster! π codeflash-ai[bot] accepted my code suggestion above.
@matclayton sorry, I totally missed that message! do you know if you can write a small reproduction? or was that fixed with GraphQL-core 3.3.0a7?
Sorry I didn't follow up here, this is fixed in GraphQL core 3.3.0va7, btw we're running GraphQL-core 3.3.0v7 in prod now, and not seen a single issue so far. Need to still confirm the other bits of this PR, I'm hoping the team can take it off me the next week or so.
/pre-release
this doesn't render/print the directives (to double check)
worth checking if those directive should be printed, since we don't print directives like @include and @skip
/pre-release
/pre-release
We've managed to get this up and running in django 5.1, Channels and with granian in our codebase by the way. Works fantastically. We haven't managed to update the Relay Network to make use of it yet (we have quite a complex setup there) but its looking nice! @millar is who's been looking at it on our end.
Just tried the pre release and i found a small bug: If you use MaskErrors it checks for result.errors. In a defer response this is nested in result.initial_result.errors
We've fully integrated this into our stack now without any issues!
@millar @Speedy1991 thank you both! I'll see if I can update the extension!
Also, I think that would work only on the first response? I'll double check
@patrick91 maybe it would be better to fix https://github.com/strawberry-graphql/strawberry/issues/3844 first? This would avoid errors in other extensions too?
Any chance of another pre release of this with all the latest changes in please?
/pre-release
β‘οΈ Codeflash found optimizations for this PR
π 12% (0.12x) speedup for process_result in strawberry/http/__init__.py
β±οΈ Runtime : 100 microseconds β 89.8 microseconds (best of 153 runs)
I created a new dependent PR with the suggested changes. Please review:
-
#3938
If you approve, it will be merged into this PR (branch feature/defer).
Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:
This release adds experimental support for GraphQL's @defer and @stream directives, enabling incremental delivery of response data.
Note: this only works when using Strawberry with graphql-core>=3.3.0a9.
Features
@deferdirective: Allows fields to be resolved asynchronously and delivered incrementally@streamdirective: Enables streaming of list fields using the newstrawberry.Streamabletypestrawberry.Streamable[T]: A new generic type for defining streamable fields that work with@stream
Configuration
To enable these experimental features, configure your schema with:
from strawberry.schema.config import StrawberryConfig
schema = strawberry.Schema(
query=Query, config=StrawberryConfig(enable_experimental_incremental_execution=True)
)
Here's the tweet text:
π Release (next) is out! Thanks to @patrick91 for the PR π
This release adds experimental support for GraphQL's @defer and @stream directives, enabling incremental delivery of response data! π
Get it here π https://strawberry.rocks/release/(next)
/pre-release
β‘οΈ Codeflash found optimizations for this PR
π 24% (0.24x) speedup for type in strawberry/experimental/pydantic/object_type.py
β±οΈ Runtime : 182 microseconds β 146 microseconds (best of 9 runs)
I created a new dependent PR with the suggested changes. Please review:
-
#3948
If you approve, it will be merged into this PR (branch feature/defer).