diff --git a/website/src/docs/hotchocolate/v16/migrating/migrate-from-15-to-16.md b/website/src/docs/hotchocolate/v16/migrating/migrate-from-15-to-16.md index 3d600f0626a..4c5f952bbd3 100644 --- a/website/src/docs/hotchocolate/v16/migrating/migrate-from-15-to-16.md +++ b/website/src/docs/hotchocolate/v16/migrating/migrate-from-15-to-16.md @@ -236,6 +236,60 @@ public class CustomRequestMiddleware } ``` +## IRequestExecutorResolver split into provider, events, and manager + +The single `IRequestExecutorResolver` interface from v15 has been removed and its responsibilities split across three more focused abstractions in `HotChocolate.Execution.Abstractions`: + +| v15 (`IRequestExecutorResolver`) | v16 | +| ------------------------------------- | ------------------------------------------------------------------------------ | +| `GetRequestExecutorAsync(schemaName)` | `IRequestExecutorProvider.GetExecutorAsync(schemaName)` | +| `Events` (`IObservable<…>`) | `IRequestExecutorEvents` (which itself is `IObservable`) | +| `EvictRequestExecutor(schemaName)` | `IRequestExecutorManager.EvictExecutor(schemaName)` | + +`IRequestExecutorManager` derives from `IRequestExecutorProvider`, so inject the manager when you need both lookup and eviction, the provider when you only need lookup, and `IRequestExecutorEvents` when you only need to react to executor lifecycle events: + +```diff +-public class MyService(IRequestExecutorResolver resolver) ++public class MyService( ++ IRequestExecutorManager executors, ++ IRequestExecutorEvents events) + { +- public ValueTask GetExecutorAsync(CancellationToken ct) +- => resolver.GetRequestExecutorAsync(cancellationToken: ct); ++ public ValueTask GetExecutorAsync(CancellationToken ct) ++ => executors.GetExecutorAsync(cancellationToken: ct); + +- public void EvictDefault() => resolver.EvictRequestExecutor(); ++ public void EvictDefault() => executors.EvictExecutor(); + +- public IDisposable Subscribe(IObserver observer) +- => resolver.Events.Subscribe(observer); ++ public IDisposable Subscribe(IObserver observer) ++ => events.Subscribe(observer); + } +``` + +The `IServiceProvider.GetRequestExecutorAsync(...)` extension method has been kept as a convenience and now resolves `IRequestExecutorProvider` from the container internally, so call sites such as `services.GetRequestExecutorAsync()` continue to compile unchanged. + +The legacy `RequestExecutorEvicted` event (already marked obsolete in v15) has been removed; subscribe to `IRequestExecutorEvents` and filter on `RequestExecutorEventType.Evicted` instead. + +## RequestExecutorProxy + +`RequestExecutorProxy` still exists and serves the same purpose, giving you a long-lived handle to the executor for a particular schema that is hot-swapped automatically when the schema is rebuilt. Two things have changed: + +**Constructor signature.** The proxy no longer takes an `IRequestExecutorResolver`; it now takes the new provider and events abstractions explicitly: + +```diff +-var proxy = new RequestExecutorProxy(resolver, "Schema"); ++var proxy = new RequestExecutorProxy(executorProvider, executorEvents, "Schema"); +``` + +**The proxy now implements `IRequestExecutor`.** You can pass a `RequestExecutorProxy` directly anywhere an `IRequestExecutor` is expected, without first calling `GetRequestExecutorAsync()`. `ExecuteAsync` and `ExecuteBatchAsync` resolve the current executor internally. + +The CLR events `ExecutorUpdated` and `ExecutorEvicted` have been removed. If you need to react to swaps, derive from `RequestExecutorProxy` and override `OnConfigureRequestExecutor(newExecutor, oldExecutor)` (runs under the proxy's lock, before `CurrentExecutor` is replaced) or `OnAfterRequestExecutorSwapped(newExecutor, oldExecutor)` (runs after the swap, outside the lock). + +The separate `AutoUpdateRequestExecutorProxy` helper has been removed; the base `RequestExecutorProxy` now subscribes to executor events on construction and updates `CurrentExecutor` automatically. + ## Schema.DefaultName moved to ISchemaDefinition.DefaultName The `Schema.DefaultName` constant is no longer available in v16.