-
Notifications
You must be signed in to change notification settings - Fork 464
Refactor code to move the current logic to search for WorkerConfigs to a default worker configuration resolver #11229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
…workerconfigs by using resolver Options
There was a problem hiding this 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 refactors the worker configuration resolution logic by extracting it from RpcWorkerConfigFactory
into a dedicated DefaultWorkerConfigurationResolver
class. The refactoring introduces the Options pattern for configuration management and enables easier extension with additional resolvers in the future.
Key changes include:
- Extract worker configuration discovery logic into a new resolver pattern
- Implement Options pattern for worker configuration resolver settings
- Update dependency injection to support the new resolver architecture
Reviewed Changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
File | Description |
---|---|
IWorkerConfigurationResolver.cs |
New interface defining worker configuration resolution contract |
DefaultWorkerConfigurationResolver.cs |
New implementation that handles worker config path discovery from workers directory |
WorkerConfigurationResolverOptions.cs |
Options class for resolver configuration with JSON serialization support |
WorkerConfigurationResolverOptionsSetup.cs |
Setup class for configuring resolver options using Options pattern |
RpcWorkerConfigFactory.cs |
Refactored to use the new resolver instead of inline logic |
Various test files | Updated to accommodate new dependency injection requirements |
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptions.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptions.cs
Outdated
Show resolved
Hide resolved
test/WebJobs.Script.Tests/Workers/Rpc/WorkerConfigurationResolverTestsHelper.cs
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
var workerConfigurationResolverOptions = p.GetService<IOptionsMonitor<WorkerConfigurationResolverOptions>>(); | ||
var loggerFactory = p.GetService<ILoggerFactory>(); | ||
return new DefaultWorkerConfigurationResolver(loggerFactory, workerConfigurationResolverOptions); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DI of WorkerConfigurationResolverOptionsSetup
has been done similar to LanguageWorkerOptionsSetup
because the ultimate purpose of both is to get WorkerConfigs and LanguageWorkerOptionsSetup
uses WorkerConfigurationResolverOptions
as input.
if (_workerConfigResolverOptionsChangeTokenSource is HostBuiltChangeTokenSource<WorkerConfigurationResolverOptions> { } hostBuiltChangeToken) | ||
{ | ||
hostBuiltChangeToken.TriggerChange(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 385-388 are implemented similarly to lines 390-393
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I filed #11208 to make this easier in the future.
var workerResolverOptions = applicationHostOptions.RootServiceProvider.GetService<IOptionsMonitor<WorkerConfigurationResolverOptions>>(); | ||
services.AddSingleton(workerResolverOptions); | ||
services.AddSingleton<IOptions<WorkerConfigurationResolverOptions>>(s => new OptionsWrapper<WorkerConfigurationResolverOptions>(workerResolverOptions.CurrentValue)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 342-345 are implemented similarly to lines 347-350
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you remove this, does it work? I think we did this with the LanguageWorkerOptions below b/c it was a complex setup. This new one is not. I think the registration will be copied to the child container automatically and all just work.
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Show resolved
Hide resolved
{ | ||
WorkersDirPath = workersDirectorySection.Value; | ||
} | ||
WorkersDirPath = _workerConfigurationResolverOptions.CurrentValue.WorkersDirPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 51-57 and lines 71-84 moved to WorkerConfigurationResolverOptionsSetup
class.
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/DefaultWorkerConfigurationResolver.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolutionInfo.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptions.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptions.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptions.cs
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolverOptionsSetup.cs
Outdated
Show resolved
Hide resolved
src/WebJobs.Script/Workers/Rpc/Configuration/WorkerConfigurationResolutionInfo.cs
Show resolved
Hide resolved
private readonly JsonSerializerOptions _jsonSerializerOptions = new() | ||
{ | ||
PropertyNameCaseInsensitive = true | ||
}; | ||
|
||
private Dictionary<string, RpcWorkerConfig> _workerDescriptionDictionary = new Dictionary<string, RpcWorkerConfig>(); | ||
private WorkerConfigurationResolutionInfo _workerConfigurationResolutionInfo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this. It's not really needed.
|
||
foreach (var workerConfig in workerConfigs) | ||
{ | ||
AddProvider(workerConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass the root worker dir path into this method instead of storing it in a field.
@@ -122,13 +106,15 @@ internal void AddProvider(string workerDir) | |||
{ | |||
try | |||
{ | |||
string workersDirPath = _workerConfigurationResolutionInfo.WorkersDirPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this. It should be passed in instead of being a field.
public readonly string WorkersDirPath => WorkersDirectoryPath; | ||
|
||
public readonly IReadOnlyList<string> WorkerConfigPaths => WorkerConfigPathsList; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure you don't need these properties. Records auto-generate properties based on the constructor params. This (note that I also removed struct
) generates what we want, for example (init-only properties are auto-created):
internal record WorkerConfigurationResolutionInfo(string WorkersDirectoryPath, IReadOnlyList<string> WorkerConfigPathsList);
/// <summary> | ||
/// Gets or sets the workers directory path within the Host or defined by IConfiguration. | ||
/// </summary> | ||
public string WorkersDirPath { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think renaming this to WorkersPathRoot
would be clearer for what this is giving us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I prefer WorkerRootDir
- multiple workers is already implied
/// </summary> | ||
internal interface IWorkerConfigurationResolver | ||
{ | ||
WorkerConfigurationResolutionInfo GetWorkerConfigPaths(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to GetConfigurationInfo()
? -- also maybe drop the Resolution
from that record to make it a little shorter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also prefer WorkerConfigurationInfo
here
|
||
namespace Microsoft.Azure.WebJobs.Script.Workers.Rpc.Configuration | ||
{ | ||
internal record struct WorkerConfigurationResolutionInfo(string WorkersDirectoryPath, IReadOnlyList<string> WorkerConfigPathsList) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd name the first parameter here WorkersPathRoot
. Secone one WorkerConfigurationFiles
? I think it's giving us the actual full file paths, right?
@@ -217,6 +219,7 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi | |||
services.ConfigureOptions<ScriptApplicationHostOptionsSetup>(); | |||
services.AddSingleton<IOptionsChangeTokenSource<ScriptApplicationHostOptions>, ScriptApplicationHostOptionsChangeTokenSource>(); | |||
services.ConfigureOptions<StandbyOptionsSetup>(); | |||
services.ConfigureOptions<WorkerConfigurationResolverOptionsSetup>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this (or the next line, actually) are required. If you look at what ConfigureOptionsWithChangeTokenSource
does -- it does this already.
var workerResolverOptions = applicationHostOptions.RootServiceProvider.GetService<IOptionsMonitor<WorkerConfigurationResolverOptions>>(); | ||
services.AddSingleton(workerResolverOptions); | ||
services.AddSingleton<IOptions<WorkerConfigurationResolverOptions>>(s => new OptionsWrapper<WorkerConfigurationResolverOptions>(workerResolverOptions.CurrentValue)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you remove this, does it work? I think we did this with the LanguageWorkerOptions below b/c it was a complex setup. This new one is not. I think the registration will be copied to the child container automatically and all just work.
private static readonly Action<ILogger, string, Exception> _defaultWorkersDirectoryPath = | ||
LoggerMessage.Define<string>(LogLevel.Debug, | ||
new EventId(343, nameof(DefaultWorkersDirectoryPath)), | ||
"Workers Directory set to: {workersDirPath}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested change
"Workers Directory set to: {workersDirPath}");
"Worker directory set to: {workerDirPath}");
Use “Worker Directory” — in noun–noun phrases, the first noun is usually singular unless it’s a fixed name, so “worker” is grammatically cleaner than “workers” here. I know its named "workers" because multiple workers would be found here, but "Worker directory” means “a directory for workers” — the fact that it holds multiple workers is already implied.
{ | ||
AddProvider(workerDir); | ||
} | ||
_logger.LogTrace("No worker configs found."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens upstream if no worker configs are found? We just return here so I am wondering if we should throw, is this a bad state?
/// </summary> | ||
internal interface IWorkerConfigurationResolver | ||
{ | ||
WorkerConfigurationResolutionInfo GetWorkerConfigPaths(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also prefer WorkerConfigurationInfo
here
/// <summary> | ||
/// Gets or sets the workers directory path within the Host or defined by IConfiguration. | ||
/// </summary> | ||
public string WorkersDirPath { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I prefer WorkerRootDir
- multiple workers is already implied
Issue describing the changes in this PR
resolves #11218
Pull request checklist
IMPORTANT: Currently, changes must be backported to the
in-proc
branch to be included in Core Tools and non-Flex deployments.in-proc
branch is not requiredrelease_notes.md
Additional information
Additional PR information
Refactor code to move the current logic to search for WorkerConfigs to a default worker configuration resolver. The current logic finds workerConfigs by scanning workers directory within the Host. This resolver should use Options pattern to get the required input values.
These changes should make it easier to add a new Resolver in future which will resolve workerConfigs from specified worker probing paths.