Skip to content

fix(runtime)!: configure grain context before construction - #10565

Merged
ReubenBond merged 3 commits into
dotnet:mainfrom
ReubenBond:rb-fix-grain-context-configuration-race
Aug 12, 2026
Merged

ReubenBond merged 3 commits into
dotnet:mainfrom
ReubenBond:rb-fix-grain-context-configuration-race

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 12, 2026

Copy link
Copy Markdown
Member

Fixes #10556

Problem

The built-in activation context creator scheduled grain construction before IConfigureGrainContext actions ran. The activation scheduler could therefore construct a grain against an incompletely configured context.

Solution

Change IGrainContextActivator.CreateContext to receive the resolved IConfigureGrainContext actions. Activators must apply those actions before grain construction begins. The built-in activator now configures the context before enqueueing its existing activation task, deterministically closing the race while retaining asynchronous activation startup.

Stateless workers preserve their existing behavior: configurators apply to the outer stateless-worker context, while inner worker activations receive an empty configuration set.

Breaking change

IGrainContextActivator.CreateContext(GrainAddress) is replaced by CreateContext(GrainAddress, IConfigureGrainContext[]). Custom implementations must accept and apply the supplied configurators before constructing the grain.

Tests

Adds a deterministic configure-before-activate ordering regression and an in-process test proving configured context state is visible during grain construction. Focused stateless-worker coverage also passes on .NET 8 and .NET 10.

Microsoft Reviewers: Open in CodeFlow

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 17:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a race in Orleans runtime activation where IConfigureGrainContext could run after grain construction had already been scheduled, allowing grains to be constructed with an incompletely configured context.

Changes:

  • Adds an internal configuration-aware activation path (IGrainContextActivatorWithConfiguration) so built-in activators can apply configurators before enqueueing activation work.
  • Updates the built-in ActivationDataActivator to apply configurators before scheduling ActivationData.Start(...).
  • Adds regression tests to verify configurators run before activation is started and that configured context state is visible during grain construction.
Show a summary per file
File Description
src/Orleans.Runtime/Activation/IGrainContextActivator.cs Routes activation through a configuration-aware activator path when available and introduces IGrainContextActivatorWithConfiguration.
src/Orleans.Runtime/Activation/ActivationDataActivatorProvider.cs Implements the new configuration-aware path for ActivationDataActivator, applying configurators before scheduling activation.
test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs New unit test validating configurators execute before activation is started (ordering regression).
test/Orleans.Runtime.Tests/GrainActivatorTests.cs Adds an in-process test verifying configured context state is visible to the grain activator at construction time.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs:43

  • The IConfigureGrainContextProvider.TryGetConfigurator contract uses a nullable out parameter annotated with [NotNullWhen(true)]. The current signature omits the attribute and uses a non-nullable out parameter, which can produce nullability-mismatch warnings (often treated as errors in this repo).
        public bool TryGetConfigurator(GrainType grainType, GrainProperties properties, out IConfigureGrainContext configurator)
        {
            configurator = new TestConfigureGrainContext(events);
            return true;
        }
  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread test/Orleans.Runtime.Tests/GrainActivatorTests.cs
Comment thread test/Orleans.Runtime.Tests/GrainActivatorTests.cs Outdated
Comment thread test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs
Copilot AI review requested due to automatic review settings August 12, 2026 18:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Suppressed comments (2)

test/Orleans.Runtime.Tests/GrainActivatorTests.cs:172

  • The assignability check is reversed: grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)) will be false when grainClass is a derived type, so the configurator won't be applied to derived grain implementations. Use typeof(ExplicitlyRegisteredSimpleDIGrain).IsAssignableFrom(grainClass) instead.
                if (grainClassMap.TryGetGrainClass(grainType, out var grainClass)
                    && grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)))
                {

src/Orleans.Runtime/Activation/ActivationDataActivatorProvider.cs:89

  • RunSynchronously will inline the activation task when the scheduler allows it, causing grain construction to happen synchronously during CreateContext instead of being enqueued asynchronously (the prior behavior) and can block the caller for the duration of grain construction. To preserve async activation while still ensuring configurators run first, start the task on the activation scheduler instead of running it synchronously.
                    task.RunSynchronously(context.ActivationTaskScheduler);
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs Outdated
Copilot AI review requested due to automatic review settings August 12, 2026 19:53
@ReubenBond
ReubenBond force-pushed the rb-fix-grain-context-configuration-race branch from d4146a3 to 33dfbd2 Compare August 12, 2026 19:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Suppressed comments (1)

test/Orleans.Runtime.Tests/GrainActivatorTests.cs:172

  • This type check is hard to read and easy to misinterpret: grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)) effectively behaves like an exact-type match given that GrainClassMap returns the concrete implementing type. If the intent is to match only ExplicitlyRegisteredSimpleDIGrain, an explicit equality check is clearer and avoids ambiguity about derived types.
                if (grainClassMap.TryGetGrainClass(grainType, out var grainClass)
                    && grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)))
                {
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

BREAKING CHANGE: IGrainContextActivator.CreateContext now receives the context configuration actions and must apply them before grain construction begins.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 408b1948-f836-4328-9b59-c1a6d9504551
Copilot AI review requested due to automatic review settings August 12, 2026 20:00
@ReubenBond ReubenBond changed the title fix(runtime): configure grain context before construction feat(runtime)!: configure grain context before construction Aug 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Suppressed comments (3)

test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs:30

  • The nullability of the out parameter in this TryGet implementation doesn’t match IGrainContextActivatorProvider.TryGet(..., out IGrainContextActivator?), which can produce CS8767 warnings (and may fail builds if warnings are treated as errors). Update the signature to use a nullable out parameter to match the interface.
        public bool TryGet(GrainType grainType, out IGrainContextActivator result)

test/Orleans.Core.Tests/Runtime/GrainContextActivatorTests.cs:39

  • The nullability of the out parameter in this TryGetConfigurator implementation doesn’t match IConfigureGrainContextProvider.TryGetConfigurator(..., out IConfigureGrainContext?), which can produce CS8767 warnings (and may fail builds if warnings are treated as errors). Update the signature to use a nullable out parameter to match the interface.
        public bool TryGetConfigurator(GrainType grainType, GrainProperties properties, out IConfigureGrainContext configurator)

test/Orleans.Runtime.Tests/GrainActivatorTests.cs:172

  • This IsAssignableFrom check is reversed. grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)) will fail if grainClass is a derived type/proxy of ExplicitlyRegisteredSimpleDIGrain (since derived types are not assignable from their base). Use typeof(ExplicitlyRegisteredSimpleDIGrain).IsAssignableFrom(grainClass) instead to reliably match the intended grain type.
                if (grainClassMap.TryGetGrainClass(grainType, out var grainClass)
                    && grainClass.IsAssignableFrom(typeof(ExplicitlyRegisteredSimpleDIGrain)))
                {
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/Orleans.Runtime/Activation/ActivationDataActivatorProvider.cs Outdated
@ReubenBond ReubenBond changed the title feat(runtime)!: configure grain context before construction fix(runtime)!: configure grain context before construction Aug 12, 2026
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 408b1948-f836-4328-9b59-c1a6d9504551
Copilot AI review requested due to automatic review settings August 12, 2026 20:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 6/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@github-actions github-actions Bot locked and limited conversation to collaborators Sep 12, 2026
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.

Race condition between IConfigureGrainContext and grain class creation.

2 participants