Skip to content

Conversation

surgupta-msft
Copy link
Contributor

@surgupta-msft surgupta-msft commented Aug 19, 2025

Issue describing the changes in this PR

resolves #10944

Pull request checklist

IMPORTANT: Currently, changes must be backported to the in-proc branch to be included in Core Tools and non-Flex deployments.

  • Backporting to the in-proc branch is not required
    • Otherwise: Link to backporting PR
  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • My changes do not require diagnostic events changes
    • Otherwise: I have added/updated all related diagnostic events and their documentation (Documentation issue linked to PR)
  • I have added all required tests (Unit tests, E2E tests)

Additional information

This pull request introduces changes to decouple language workers from the Host release and enable dynamic worker resolution.

Backlog issues - Link
Design doc - Link

Flows covered in this PR -

  1. Resolving Worker Configurations -
    • Introduced DynamicWorkerConfigurationResolver, which dynamically resolves worker configurations based on -
      • Environment settings and probing paths
      • Host-Worker compatibility check
      • Leveraging Release channel concept to point to a previous version of the worker
      • Fallback to the old flow if worker is not found at the probing path level
      • Ignoring versions of a worker specified via Hosting config
  2. RPCWorkerConfigFactory -
    • Moved some methods to WorkerConfigurationHelper.cs to enable reusing of workers profile evaluation logic between 2 resolvers.
  3. Environment Updates -
    • Added a new feature flag FeatureFlagDisableWorkerProbingPaths to disable dynamic resolution feature by users.
    • Added 2 Hosting config settings
      • To get list of workers available for resolution.
      • To get list of workers versions to be ignored.
  4. WorkerConfigurationResolverOptionsSetup -
    • Configures WorkerConfigurationResolverOptions by getting required values from IConfiguration and IEnvironment such as worker probing paths, release channel, workers available for resolution via hosting config.

Note: The decoupling workers flow is disabled by default in this PR. The flow can be enabled by setting the Hosting config which will be done after completing other relevant backlog items.

@surgupta-msft surgupta-msft changed the base branch from feature/workers-decoupling to dev August 26, 2025 15:35
@Copilot Copilot AI review requested due to automatic review settings August 28, 2025 04:30
Copy link
Contributor

@Copilot Copilot AI left a comment

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 implements a dynamic worker configuration resolver that enables language workers to be decoupled from the Host release by resolving worker configurations from specified probing paths. It introduces a new DynamicWorkerConfigurationResolver that can dynamically discover and resolve worker configurations based on environment settings, compatibility checks, and release channel concepts, with fallback to the existing resolution mechanism.

Key changes include:

  • New dynamic worker configuration resolution system with probing paths support
  • Enhanced worker configuration options with environment-based settings
  • Refactored shared worker configuration logic into helper classes

Reviewed Changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
DynamicWorkerConfigurationResolver.cs Implements the core dynamic resolution logic with probing paths, version selection, and compatibility checks
WorkerConfigurationResolverOptionsSetup.cs Configures resolver options from environment variables and hosting config
WorkerConfigurationResolverOptions.cs Adds new properties for dynamic resolution settings
WorkerConfigurationHelper.cs Extracts shared worker description logic from RpcWorkerConfigFactory
RpcWorkerConfigFactory.cs Refactored to use shared helper methods
WebHostServiceCollectionExtensions.cs Adds service registration logic to choose between resolvers
Various test files Comprehensive test coverage for new functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_functionsHostingConfigOptions = functionsHostingConfigOptions ?? throw new ArgumentNullException(nameof(functionsHostingConfigOptions));
ArgumentNullException.ThrowIfNull(_functionsHostingConfigOptions.Value);
Copy link
Member

Choose a reason for hiding this comment

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

you shouldn't need this -- i don't think this can ever be null (dotnet will always create one when you call .Value)


private static void GetWorkerDescriptionFromAppSettings(RpcWorkerDescription workerDescription, Dictionary<string, string> languageWorkersSettings)
{
if (languageWorkersSettings.TryGetValue($"{RpcWorkerConstants.LanguageWorkersSectionName}:{workerDescription.Language}:{WorkerConstants.WorkerDescriptionDefaultExecutablePath}", out string defaultExecutablePathSetting) && defaultExecutablePathSetting is not null)
Copy link
Member

Choose a reason for hiding this comment

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

If we parse LanguageWorkerSettings elsewhere like i suggested, this gets simpler.

_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
_profileManager = workerProfileManager ?? throw new ArgumentNullException(nameof(workerProfileManager));
_workerConfigurationResolverOptions = workerConfigResolverOptions ?? throw new ArgumentNullException(nameof(workerConfigResolverOptions));
ArgumentNullException.ThrowIfNull(workerConfigResolverOptions.CurrentValue);
Copy link
Member

Choose a reason for hiding this comment

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

don't think this can be null -- likely don't need this

return false;
}

JsonElement workerConfigJson = WorkerConfigurationHelper.GetWorkerConfigJsonElement(workerConfigPath);
Copy link
Member

Choose a reason for hiding this comment

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

I see us calling this from at least 2 places, meaning we're loading and parsing this json config at least twice. We should only be doing this once. Can you refactor this so it's only parsed once? Is this the same thing that's available in LanguageWorkerSettings in the Options object?

/// </summary>
/// <param name="workerConfig"> Worker config: { "hostRequirements": [ "test-capability1", "test-capability2" ] }. </param>
/// <returns> HashSet { "test-capability1", "test-capability2" }. </returns>
private HashSet<string> GetHostRequirementsFromWorker(JsonElement workerConfig)
Copy link
Member

Choose a reason for hiding this comment

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

I don't like that we're operating on JsonElements in here -- I would think that this would be abstracted away somehow and we'd just be given the WorkerConfig as an object to work with.

Copy link
Member

@liliankasem liliankasem left a comment

Choose a reason for hiding this comment

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

leaving initial notes, will continue review this afternoon

private readonly ILogger _logger;
private readonly IWorkerProfileManager _profileManager;
private readonly IFileSystem _fileSystem;
private readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
Copy link
Member

Choose a reason for hiding this comment

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

Do we have global or host wide JsonSerializerOptions we can use? I know PropertyNameCaseInsensitive = true is used a lot throughout the repo so wondering if there is a single one to be shared instead of implementing this every time

}

public void Configure(WorkerConfigurationResolverOptions options)
{
var configuration = GetRequiredConfiguration();
options.WorkersRootDirPath = GetWorkersRootDirPath(configuration);
options.WorkerRuntime = _environment.GetFunctionsWorkerRuntime();
options.ReleaseChannel = _environment.GetPlatformReleaseChannel();
options.IsPlaceholderModeEnabled = _environment.IsPlaceholderModeEnabled();
Copy link
Member

Choose a reason for hiding this comment

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

I thought we were moving away from environment for resolving this, shouldn't this be coming from options? Or am I missing something from the discussion about this change?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants