Skip to content

Commit

Permalink
Revert "Removing host level retry specification"
Browse files Browse the repository at this point in the history
This reverts commit 57a5447.
  • Loading branch information
alrod committed Nov 29, 2021
1 parent 3faaf11 commit f96130b
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 4 deletions.
7 changes: 7 additions & 0 deletions WebJobs.Script.sln
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HttpTrigger-RetryFunctionJs
sample\NodeRetry\HttpTrigger-RetryFunctionJson\index.js = sample\NodeRetry\HttpTrigger-RetryFunctionJson\index.js
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HttpTrigger-RetryHostJson", "HttpTrigger-RetryHostJson", "{CF6D9CDA-2290-46DF-B162-2D422477288A}"
ProjectSection(SolutionItems) = preProject
sample\NodeRetry\HttpTrigger-RetryHostJson\function.json = sample\NodeRetry\HttpTrigger-RetryHostJson\function.json
sample\NodeRetry\HttpTrigger-RetryHostJson\index.js = sample\NodeRetry\HttpTrigger-RetryHostJson\index.js
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.WebJobs.Script.Tests.Benchmarks", "test\Benchmarks\Microsoft.Azure.WebJobs.Script.Tests.Benchmarks.csproj", "{09D16953-A048-4E6B-B366-1E0D7E5EF86E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NodeDrain", "NodeDrain", "{6FE94892-4E58-403D-BA32-4A35C0EE1E46}"
Expand Down Expand Up @@ -460,6 +466,7 @@ Global
{821D5B92-2C3E-44F0-AA92-8B996DCB8E6C} = {9D87C796-7914-4A43-B843-579562393E10}
{EEBAC197-FAD8-4214-9A12-76334BB3021A} = {FF9C0818-30D3-437A-A62D-7A61CA44F459}
{7935A7A4-191A-4A9B-B8DD-173968309EBF} = {EEBAC197-FAD8-4214-9A12-76334BB3021A}
{CF6D9CDA-2290-46DF-B162-2D422477288A} = {EEBAC197-FAD8-4214-9A12-76334BB3021A}
{09D16953-A048-4E6B-B366-1E0D7E5EF86E} = {AFB0F5F7-A612-4F4A-94DD-8B69CABF7970}
{6FE94892-4E58-403D-BA32-4A35C0EE1E46} = {FF9C0818-30D3-437A-A62D-7A61CA44F459}
{1EE80AFE-8B64-4670-9462-3DEA692D4457} = {6FE94892-4E58-403D-BA32-4A35C0EE1E46}
Expand Down
1 change: 0 additions & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<!-- Please add your release notes in the following format:
- My change description (#PR)
-->
- Removing host level retry specification (#7870)

**Release sprint:** Sprint 113
[ [bugs](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+113%22+label%3Abug+is%3Aclosed) | [features](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+113%22+label%3Afeature+is%3Aclosed) ]
18 changes: 18 additions & 0 deletions sample/NodeRetry/HttpTrigger-RetryHostJson/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
22 changes: 22 additions & 0 deletions sample/NodeRetry/HttpTrigger-RetryHostJson/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var errorString = 'An error occurred';
var maxRetries = 2;

module.exports = async function (context, req) {
var retryContext = context.executionContext.retryContext;

if (retryContext.maxRetryCount != maxRetries || (retryContext.retryCount > 0 && !retryContext.exception.message.includes(errorString))) {
debugger;
context.res = {
status: 500
};
} else {
context.log('JavaScript HTTP trigger function processed a request. retryCount: ' + retryContext.retryCount);

if (retryContext.retryCount < maxRetries) {
throw new Error(errorString);
}
context.res = {
body: 'retryCount: ' + retryContext.retryCount
};
}
}
7 changes: 6 additions & 1 deletion sample/NodeRetry/host.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"version": "2.0"
"version": "2.0",
"retry": {
"strategy": "fixedDelay",
"maxRetryCount": 2,
"delayInterval": "00:00:03"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class HostJsonFileConfigurationProvider : ConfigurationProvider
{
private static readonly string[] WellKnownHostJsonProperties = new[]
{
"version", "functionTimeout", "functions", "http", "watchDirectories", "watchFiles", "queues", "serviceBus",
"version", "functionTimeout", "retry", "functions", "http", "watchDirectories", "watchFiles", "queues", "serviceBus",
"eventHub", "singleton", "logging", "aggregator", "healthMonitor", "extensionBundle", "managedDependencies",
"customHandler", "httpWorker", "extensions", "concurrency"
};
Expand Down
5 changes: 5 additions & 0 deletions src/WebJobs.Script/Config/ScriptJobHostOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ public string RootScriptPath
/// </summary>
public bool IsSelfHost { get; set; }

/// <summary>
/// Gets or sets retry options to use on function executions on function invocation failures.
/// </summary>
public RetryOptions Retry { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the filesystem is read-only.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/WebJobs.Script/Config/ScriptJobHostOptionsSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public void Configure(ScriptJobHostOptions options)
{
options.FileLoggingMode = fileLoggingMode.Value;
}
Utility.ValidateRetryOptions(options.Retry);
}

// FunctionTimeout
Expand Down
10 changes: 10 additions & 0 deletions src/WebJobs.Script/Host/ScriptHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,16 @@ internal static Collection<CustomAttributeBuilder> CreateTypeAttributes(ScriptJo
var timeoutBuilder = CustomAttributeBuilderUtility.GetTimeoutCustomAttributeBuilder(scriptConfig.FunctionTimeout.Value);
customAttributes.Add(timeoutBuilder);
}
// apply retry settings for function execution
if (scriptConfig.Retry != null)
{
// apply the retry settings from host.json
var retryCustomAttributeBuilder = CustomAttributeBuilderUtility.GetRetryCustomAttributeBuilder(scriptConfig.Retry);
if (retryCustomAttributeBuilder != null)
{
customAttributes.Add(retryCustomAttributeBuilder);
}
}

return customAttributes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ public async Task HttpTrigger_RetryFunctionJson_Get_Succeeds()
Assert.Equal("retryCount: 4", body);
}

[Fact]
public async Task HttpTrigger_RetryHostJson_Get_Succeeds()
{
var response = await SamplesTestHelpers.InvokeHttpTrigger(_fixture, "HttpTrigger-RetryHostJson");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
Assert.Equal("retryCount: 2", body);
}

public class TestFixture : EndToEndTestFixture
{
static TestFixture()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.WebJobs.Script.Configuration;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Xunit;
Expand Down Expand Up @@ -150,6 +151,83 @@ public void Configure_AppliesTimeout()
Assert.Equal(TimeSpan.FromSeconds(30), options.FunctionTimeout);
}

[Theory]
[InlineData("fixedDelay", "3", "00:00:05", false)]
[InlineData("invalid", "3", "00:00:05", true)]
[InlineData("fixedDelay", "3", null, true)]
[InlineData("fixedDelay", "3", "-10000000000", true)]
[InlineData("fixedDelay", "3", "10000000000:00000000:40000", true)]
[InlineData("fixedDelay", null, "00:00:05", true)]
[InlineData("fixedDelay", "-1", "00:00:05", false)]
[InlineData("fixedDelay", "-4", "00:00:05", true)]
public void Configure_AppliesRetry_FixedDelay(string expectedStrategy, string maxRetryCount, string delayInterval, bool throwsError)
{
var settings = new Dictionary<string, string>
{
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "strategy"), expectedStrategy },
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "maxRetryCount"), maxRetryCount },
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "delayInterval"), delayInterval }
};
if (string.IsNullOrEmpty(delayInterval) || string.IsNullOrEmpty(maxRetryCount))
{
Assert.Throws<ArgumentNullException>(() => GetConfiguredOptions(settings));
return;
}
if (throwsError)
{
if (int.Parse(maxRetryCount) <= 0)
{
Assert.Throws<ArgumentOutOfRangeException>(() => GetConfiguredOptions(settings));
return;
}
Assert.Throws<InvalidOperationException>(() => GetConfiguredOptions(settings));
return;
}
var options = GetConfiguredOptions(settings);
Assert.Equal(RetryStrategy.FixedDelay, options.Retry.Strategy);
Assert.Equal(int.Parse(maxRetryCount), options.Retry.MaxRetryCount.Value);
Assert.Equal(TimeSpan.Parse(delayInterval), options.Retry.DelayInterval);
}

[Theory]
[InlineData("ExponentialBackoff", "3", "00:00:05", "00:30:00", false)]
[InlineData("ExponentialBackoff", "sdfsdfd", "00:00:05", "00:30:00", true)]
[InlineData("ExponentialBackoff", "5", "00:35:05", "00:30:00", true)]
[InlineData("ExponentialBackoff", "5", null, "00:30:00", true)]
[InlineData("ExponentialBackoff", "5", "00:35:05", null, true)]
public void Configure_AppliesRetry_ExponentialBackOffDelay(string expectedStrategy, string maxRetryCount, string minimumInterval, string maximumInterval, bool throwsError)
{
var settings = new Dictionary<string, string>
{
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "strategy"), expectedStrategy },
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "maxRetryCount"), maxRetryCount },
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "minimumInterval"), minimumInterval },
{ ConfigurationPath.Combine(ConfigurationSectionNames.JobHost, "retry", "maximumInterval"), maximumInterval }
};
if (string.IsNullOrEmpty(minimumInterval) || string.IsNullOrEmpty(maximumInterval))
{
Assert.Throws<ArgumentNullException>(() => GetConfiguredOptions(settings));
return;
}
var minIntervalTimeSpan = TimeSpan.Parse(minimumInterval);
var maxIntervalTimeSpan = TimeSpan.Parse(maximumInterval);
if (throwsError)
{
if (minIntervalTimeSpan > maxIntervalTimeSpan)
{
Assert.Throws<ArgumentException>(() => GetConfiguredOptions(settings));
return;
}
Assert.Throws<InvalidOperationException>(() => GetConfiguredOptions(settings));
return;
}
var options = GetConfiguredOptions(settings);
Assert.Equal(RetryStrategy.ExponentialBackoff, options.Retry.Strategy);
Assert.Equal(int.Parse(maxRetryCount), options.Retry.MaxRetryCount);
Assert.Equal(minIntervalTimeSpan, options.Retry.MinimumInterval);
Assert.Equal(maxIntervalTimeSpan, options.Retry.MaximumInterval);
}

[Fact]
public void Configure_TimeoutDefaultsNull_IfNotDynamic()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void ReadFunctionMetadata_With_Retry_Succeeds()
var workerConfigs = TestHelpers.GetTestWorkerConfigs();
var functionMetadatas = metadataProvider.GetFunctionMetadataAsync(workerConfigs, false).Result;

Assert.Equal(1, functionMetadatas.Length);
Assert.Equal(2, functionMetadatas.Length);

var functionMetadataWithRetry = functionMetadatas.Where(f => f.Name.Contains("HttpTrigger-RetryFunctionJson", StringComparison.OrdinalIgnoreCase));
Assert.Single(functionMetadataWithRetry);
Expand All @@ -57,6 +57,10 @@ public void ReadFunctionMetadata_With_Retry_Succeeds()
Assert.Equal(RetryStrategy.FixedDelay, retry.Strategy);
Assert.Equal(4, retry.MaxRetryCount);
Assert.Equal(TimeSpan.Parse("00:00:03"), retry.DelayInterval);

var functionMetadata = functionMetadatas.Where(f => !f.Name.Contains("HttpTrigger-RetryFunctionJson", StringComparison.OrdinalIgnoreCase));
Assert.Single(functionMetadataWithRetry);
Assert.Null(functionMetadata.FirstOrDefault().Retry);
}

private bool AreRequiredMetricsEmitted(TestMetricsLogger metricsLogger)
Expand Down

0 comments on commit f96130b

Please sign in to comment.