diff --git a/dictionary.txt b/dictionary.txt index e3547b0375b..50f18a303ff 100644 --- a/dictionary.txt +++ b/dictionary.txt @@ -136,6 +136,12 @@ websockets winget Wunder xunit +inspectable +debuggable +colocated +esque +frontends +evolvability # Command line options -Lsfo diff --git a/website/src/blog/2024-08-30-hot-chocolate-14/2024-08-30-hot-chocolate-14.md b/website/src/blog/2024-08-30-hot-chocolate-14/2024-08-30-hot-chocolate-14.md new file mode 100644 index 00000000000..ea870e85391 --- /dev/null +++ b/website/src/blog/2024-08-30-hot-chocolate-14/2024-08-30-hot-chocolate-14.md @@ -0,0 +1,997 @@ +--- +path: "/blog/2024/08/30/hot-chocolate-14" +date: "2024-08-30" +title: "What's new for Hot Chocolate 14" +tags: ["hotchocolate", "graphql", "dotnet", "aspnetcore"] +featuredImage: "hot-chocolate-14.png" +author: Michael Staib +authorUrl: https://github.com/michaelstaib +authorImageUrl: https://avatars1.githubusercontent.com/u/9714350?s=100&v=4 +--- + +We are almost ready to release a new major version of Hot Chocolate, and with it come many new exciting features. We have been working on this release for quite some time, and we are thrilled to share it with you. In this blog post, we will give you a sneak peek at what you can expect with Hot Chocolate 14. + +I will be focusing mainly on the Hot Chocolate server, but we have also been busy working on Hot Chocolate Fusion and the Composite Schema Specification. We will be releasing more information on these projects in the coming weeks. + +## Ease of Use + +We have focused on making Hot Chocolate easier to use and more intuitive. To achieve this, we have added many new features that will simplify your workflow. This will be apparent right from the start when you begin using Hot Chocolate 14. One major area where you can see this improvement is in dependency injection. Hot Chocolate 13 was incredibly flexible in this area, allowing you to specify which services are multi-thread capable, which services are pooled resources, or which services must be synchronized. While this was a powerful feature, it could be somewhat complex to use, especially for newcomers to our platform. + +You either ended up with lengthy configuration code that essentially re-declared all services, or you ended up with very cluttered resolvers. + +With Hot Chocolate 14, we have simplified this process by putting dependency injection on auto-pilot. Now, when you write your resolvers, you can simply inject services without the need to explicitly tell Hot Chocolate that they are services or what kind of services they are. + +```csharp +public static IQueryable GetSessions( + ApplicationDbContext context) + => context.Sessions.OrderBy(s => s.Title); +``` + +This leads to dramatically clearer code that is more understandable and easier to maintain. For instance, the resolver above injects the `ApplicationDbContext`. There is no need to tell Hot Chocolate that this is a service or what characteristics this service has; it will just work. This is because we have simplified the way Hot Chocolate interacts with the dependency injection system. + +In GraphQL, we essentially have two execution algorithms. The first, used for queries, allows for parallelization to optimize data fetching. This enables us to enqueue data fetching requests transparently and execute them in parallel. The second algorithm, used for mutations, is a sequential algorithm that executes one mutation after another. + +So, how is this related to DI? In Hot Chocolate 14, if we have an async resolver that requires services from the DI container, we create a service scope around it, ensuring that the services you use in the resolver are not used concurrently used by other resolvers. Since query resolvers are, by specification, defined as side-effect-free, this is an excellent default behavior where you as the developer can just focus on writing code without concerning yourself with concurrency between resolver instances. + +For mutations, the situation is different, as mutations inherently cause side effects. For instance, you might want to use a shared DbContext between two mutations. When executing a mutation Hot Chocolate will use the default request scope as it's guaranteed by the execution algorithm that there will only ever be a single mutation resolver executed at the same time for a request. + +While the new default execution behavior is much more opinionated, it leads to a dramatically easier experience when implementing resolvers. However, we recognize that there are reasons you may want to use the request scope everywhere. That's why you can change the default configuration with the default schema options. + +```csharp +builder + .AddGraphQL() + .AddTypes() + .ModifyOptions(o => + { + o.DefaultQueryDependencyInjectionScope = DependencyInjectionScope.Resolver; + o.DefaultMutationDependencyInjectionScope = DependencyInjectionScope.Request; + }); +``` + +Also, you can override the defaults configured in the schema options, on a per resolver basis. + +```csharp +[UseRequestScope] +[UsePaging] +public static async Task> GetBrandsAsync( + PagingArguments pagingArguments, + BrandService brandService, + CancellationToken cancellationToken) + => await brandService + .GetBrandsAsync(pagingArguments, cancellationToken) + .ToConnectionAsync(); +``` + +> We have applied the same DI handling to source generated DataLoader which by default will now use an explicit service scope for each DataLoader fetch. + +## Query Inspection + +