Skip to content
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

Using hostMetadataProvider for CreateOrUpdate call in FunctionController #10678

Merged
merged 4 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
- My change description (#PR)
-->

- Setting force refersh to false for CreateOrUpdate call (#10668)
- Using hostMetadataProvider for CreateOrUpdate call in FunctionController (#10678)
38 changes: 31 additions & 7 deletions src/WebJobs.Script.WebHost/Management/WebFunctionsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Azure;
using Azure.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Azure.WebJobs.Script.Management.Models;
using Microsoft.Azure.WebJobs.Script.WebHost.Extensions;
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
Expand All @@ -27,8 +31,11 @@ public class WebFunctionsManager : IWebFunctionsManager
private readonly IFunctionsSyncManager _functionsSyncManager;
private readonly HostNameProvider _hostNameProvider;
private readonly IFunctionMetadataManager _functionMetadataManager;
private readonly IHostFunctionMetadataProvider _hostFunctionMetadataProvider;
private readonly IOptionsMonitor<LanguageWorkerOptions> _languageWorkerOptions;

public WebFunctionsManager(IOptionsMonitor<ScriptApplicationHostOptions> applicationHostOptions, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, ISecretManagerProvider secretManagerProvider, IFunctionsSyncManager functionsSyncManager, HostNameProvider hostNameProvider, IFunctionMetadataManager functionMetadataManager)
public WebFunctionsManager(IOptionsMonitor<ScriptApplicationHostOptions> applicationHostOptions, ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory, ISecretManagerProvider secretManagerProvider, IFunctionsSyncManager functionsSyncManager, HostNameProvider hostNameProvider, IFunctionMetadataManager functionMetadataManager, IHostFunctionMetadataProvider hostFunctionMetadataProvider,
IOptionsMonitor<LanguageWorkerOptions> languageWorkerOptions)
{
_applicationHostOptions = applicationHostOptions;
_logger = loggerFactory?.CreateLogger(ScriptConstants.LogCategoryHostGeneral);
Expand All @@ -37,6 +44,8 @@ public WebFunctionsManager(IOptionsMonitor<ScriptApplicationHostOptions> applica
_functionsSyncManager = functionsSyncManager;
_hostNameProvider = hostNameProvider;
_functionMetadataManager = functionMetadataManager;
_hostFunctionMetadataProvider = hostFunctionMetadataProvider;
_languageWorkerOptions = languageWorkerOptions;
}

public async Task<IEnumerable<FunctionMetadataResponse>> GetFunctionsMetadata(bool includeProxies)
Expand Down Expand Up @@ -144,12 +153,21 @@ await functionMetadata
await FileUtility.WriteAsync(dataFilePath, functionMetadata.TestData);
}

// Using HostFunctionMetadataProvider instead of IFunctionMetadataManager. More details logged here https://github.com/Azure/azure-functions-host/issues/10691
var metadata = (await _hostFunctionMetadataProvider.GetFunctionMetadataAsync(_languageWorkerOptions.CurrentValue.WorkerConfigs, true))
.FirstOrDefault(metadata => Utility.FunctionNamesMatch(metadata.Name, name));

bool success = false;
FunctionMetadataResponse functionMetadataResult = null;
if (metadata != null)
{
functionMetadataResult = await GetFunctionMetadataResponseAsync(metadata, hostOptions, request);
success = true;
}
soninaren marked this conversation as resolved.
Show resolved Hide resolved

// we need to sync triggers if config changed, or the files changed
await _functionsSyncManager.TrySyncTriggersAsync();

// Setting force refresh to false as host restart causes a refersh already
(var success, var functionMetadataResult) = await TryGetFunction(name, request, false);

return (success, configChanged, functionMetadataResult);
}

Expand Down Expand Up @@ -179,9 +197,8 @@ await functionMetadata

if (functionMetadata != null)
{
string routePrefix = await GetRoutePrefix(hostOptions.RootScriptPath);
var baseUrl = $"{request.Scheme}://{request.Host}";
return (true, await functionMetadata.ToFunctionMetadataResponse(hostOptions, routePrefix, baseUrl));
var functionMetadataResponse = await GetFunctionMetadataResponseAsync(functionMetadata, hostOptions, request);
return (true, functionMetadataResponse);
}
else
{
Expand Down Expand Up @@ -228,6 +245,13 @@ private void DeleteFunctionArtifacts(FunctionMetadataResponse function)
}
}

private static async Task<FunctionMetadataResponse> GetFunctionMetadataResponseAsync(FunctionMetadata functionMetadata, ScriptJobHostOptions hostOptions, HttpRequest request)
{
string routePrefix = await GetRoutePrefix(hostOptions.RootScriptPath);
var baseUrl = $"{request.Scheme}://{request.Host}";
return await functionMetadata.ToFunctionMetadataResponse(hostOptions, routePrefix, baseUrl);
}

// TODO : Due to lifetime scoping issues (this service lifetime is longer than the lifetime
// of HttpOptions sourced from host.json) we're reading the http route prefix anew each time
// to ensure we have the latest configured value.
Expand Down
2 changes: 1 addition & 1 deletion src/WebJobs.Script/Host/FunctionMetadataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ internal ImmutableArray<FunctionMetadata> LoadFunctionMetadata(bool forceRefresh

ImmutableArray<FunctionMetadata> immutableFunctionMetadata;

immutableFunctionMetadata = _functionMetadataProvider.GetFunctionMetadataAsync(workerConfigs, _environment, forceRefresh).GetAwaiter().GetResult();
immutableFunctionMetadata = _functionMetadataProvider.GetFunctionMetadataAsync(workerConfigs, forceRefresh).GetAwaiter().GetResult();

var functionMetadataList = new List<FunctionMetadata>();
_functionErrors = new Dictionary<string, ICollection<string>>();
Expand Down
10 changes: 5 additions & 5 deletions src/WebJobs.Script/Host/FunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public FunctionMetadataProvider(ILogger<FunctionMetadataProvider> logger, IWorke

public ImmutableDictionary<string, ImmutableArray<string>> FunctionErrors { get; private set; }

public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment, bool forceRefresh = false)
public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, bool forceRefresh = false)
mathewc marked this conversation as resolved.
Show resolved Hide resolved
{
bool workerIndexing = Utility.CanWorkerIndex(workerConfigs, _environment, _functionsHostingConfigOptions);
if (!workerIndexing)
{
return await GetMetadataFromHostProvider(workerConfigs, environment, forceRefresh);
return await GetMetadataFromHostProvider(workerConfigs, forceRefresh);
}

_logger.LogInformation("Worker indexing is enabled");
Expand All @@ -48,15 +48,15 @@ public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEn
if (functionMetadataResult.UseDefaultMetadataIndexing)
{
_logger.LogDebug("Fallback to host indexing as worker denied indexing");
return await GetMetadataFromHostProvider(workerConfigs, environment, forceRefresh);
return await GetMetadataFromHostProvider(workerConfigs, forceRefresh);
}

return functionMetadataResult.Functions;
}

private async Task<ImmutableArray<FunctionMetadata>> GetMetadataFromHostProvider(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment, bool forceRefresh = false)
private async Task<ImmutableArray<FunctionMetadata>> GetMetadataFromHostProvider(IEnumerable<RpcWorkerConfig> workerConfigs, bool forceRefresh = false)
{
var functions = await _hostFunctionMetadataProvider?.GetFunctionMetadataAsync(workerConfigs, environment, forceRefresh);
var functions = await _hostFunctionMetadataProvider?.GetFunctionMetadataAsync(workerConfigs, forceRefresh);
FunctionErrors = _hostFunctionMetadataProvider.FunctionErrors;
return functions;
}
Expand Down
2 changes: 1 addition & 1 deletion src/WebJobs.Script/Host/HostFunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public HostFunctionMetadataProvider(IOptionsMonitor<ScriptApplicationHostOptions
public ImmutableDictionary<string, ImmutableArray<string>> FunctionErrors
=> _functionErrors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray());

public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment, bool forceRefresh)
public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, bool forceRefresh)
{
_functions = default(ImmutableArray<FunctionMetadata>);

Expand Down
2 changes: 1 addition & 1 deletion src/WebJobs.Script/Host/IFunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public interface IFunctionMetadataProvider
{
ImmutableDictionary<string, ImmutableArray<string>> FunctionErrors { get; }

Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment, bool forceRefresh = false);
Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, bool forceRefresh = false);
}
}
4 changes: 2 additions & 2 deletions src/WebJobs.Script/Host/IHostFunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ namespace Microsoft.Azure.WebJobs.Script
/// <summary>
/// Defines an interface for fetching function metadata from function.json files
/// </summary>
internal interface IHostFunctionMetadataProvider
public interface IHostFunctionMetadataProvider
soninaren marked this conversation as resolved.
Show resolved Hide resolved
{
ImmutableDictionary<string, ImmutableArray<string>> FunctionErrors { get; }

/// <summary>
/// Reads function metadata from function.json files present along with each function
/// </summary>
Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment, bool forceRefresh = false);
Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEnumerable<RpcWorkerConfig> workerConfigs, bool forceRefresh = false);
}
}
Loading
Loading