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

Add fail-over support to config provider. #319

Merged
merged 31 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d4f97b0
Changes from geo-replication branch
Apr 21, 2022
2640652
FailOver mechanism with the new design
Apr 27, 2022
8852d6f
Small refractoring of tests
Apr 29, 2022
55b6355
Resolve feedback comments
May 6, 2022
8cad9e0
Fix broken unit tests
May 6, 2022
e0cd066
Add separate example for multi-endpoint scenario
May 6, 2022
136c2bc
Add back unit tests, fix updateCacheExpiration behavior
May 9, 2022
4a6548e
Add back randomized exponential backoff interval for retry after failure
May 9, 2022
8d0ac88
Resolve feedback comments
May 10, 2022
b5502bf
Resolve feedback
May 11, 2022
8801d9a
Revert pipeline change
May 11, 2022
f541f16
downgrade project to .NET5 again
May 11, 2022
c522785
Update comment, prevent against NRE on innerException
May 12, 2022
486f8b9
Resolve few feedback comments
May 13, 2022
a445b64
Make workflows execute on a single configuration client
May 19, 2022
7d14fb1
Add reset state mechanism
May 19, 2022
5bdeea8
Change the mechanism to persist data only when all requests are succe…
May 25, 2022
fe4c371
Resolve feedback comments
Jun 2, 2022
851c1d5
Resolve feedback comments
Jun 2, 2022
28dbae3
fix
Jun 3, 2022
6b5b885
change warning message, remove refreshAttempts
Jun 3, 2022
f792924
Pass `cancellationToken`
pratiksanglikar Jun 3, 2022
a1b3037
Remove cancellationToken
Jun 3, 2022
25c4a1a
Merge branch 'dev/ps/failover' of https://github.com/Azure/AppConfigu…
Jun 3, 2022
5985715
Resolve feedback comments
Jun 7, 2022
a4db608
Resolve comments
Jun 9, 2022
92dc241
Make GetAvailableClients only return non-backed off clients
Jun 9, 2022
f3845d0
Fix the breached contract for funcToExecute
Jun 10, 2022
dacc753
Pass available clients to InitializeAsync()
Jun 10, 2022
25958b1
Backoff all clients when non-failverable exception is thrown
Jun 13, 2022
fd74990
Add comment for SetData calls
Jun 14, 2022
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
10 changes: 8 additions & 2 deletions Microsoft.Extensions.Configuration.AzureAppConfiguration.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29920.165
# Visual Studio Version 17
VisualStudioVersion = 17.3.32503.460
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Configuration.AzureAppConfiguration", "src\Microsoft.Extensions.Configuration.AzureAppConfiguration\Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj", "{7B793D44-EC46-4C12-B71F-3A5005290C75}"
EndProject
Expand All @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.AppConfigur
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.AzureAppConfiguration.Functions.Worker", "tests\Tests.AzureAppConfiguration.Functions.Worker\Tests.AzureAppConfiguration.Functions.Worker.csproj", "{A9287214-6689-479F-A9F8-D0C02DE433F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleAppWithFailOver", "examples\ConsoleAppWithFailOver\ConsoleAppWithFailOver.csproj", "{A6C611F1-D687-4262-8904-828C239CF2E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -57,6 +59,10 @@ Global
{A9287214-6689-479F-A9F8-D0C02DE433F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9287214-6689-479F-A9F8-D0C02DE433F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9287214-6689-479F-A9F8-D0C02DE433F0}.Release|Any CPU.Build.0 = Release|Any CPU
{A6C611F1-D687-4262-8904-828C239CF2E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6C611F1-D687-4262-8904-828C239CF2E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6C611F1-D687-4262-8904-828C239CF2E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6C611F1-D687-4262-8904-828C239CF2E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
24 changes: 24 additions & 0 deletions examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
pratiksanglikar marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.5.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Extensions.Configuration.AzureAppConfiguration\Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
52 changes: 52 additions & 0 deletions examples/ConsoleAppWithFailOver/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//

using Azure.Identity;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Examples.ConsoleApplicationWithFailOver
{
class Program
{
static IConfiguration Configuration { get; set; }

static void Main(string[] args)
{
Configure();

Console.WriteLine($"The AppName is: {Configuration?["AppName"]}.");
}

private static void Configure()
{
var builder = new ConfigurationBuilder();

// Load a subset of the application's configuration from a json file and environment variables
builder.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();

IConfiguration configuration = builder.Build();

IConfigurationSection endpointsSection = configuration.GetSection("AppConfig:Endpoints");
IEnumerable<Uri> endpoints = endpointsSection.GetChildren().Select(endpoint => new Uri(endpoint.Value));

if (endpoints == null || !endpoints.Any())
{
Console.WriteLine("Endpoints not found.");
Console.WriteLine("Please set the array 'Appconfig:Endpoints' in appsettings.json with valid Azure App Configuration replica endpoints and re-run this example.");
return;
}

// Augment the configuration builder with Azure App Configuration
builder.AddAzureAppConfiguration(options =>
{
options.Connect(endpoints, new DefaultAzureCredential());
});

Configuration = builder.Build();
}
}
}
6 changes: 6 additions & 0 deletions examples/ConsoleAppWithFailOver/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"AppName": "Azure App Configuration Console App with FailOver support",
"AppConfig": {
"Endpoints": [ ]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,5 @@ public static IServiceCollection AddAzureAppConfiguration(this IServiceCollectio
services.AddSingleton<IConfigurationRefresherProvider, AzureAppConfigurationRefresherProvider>();
return services;
}

internal static IConfigurationBuilder AddAzureAppConfiguration(
this IConfigurationBuilder configurationBuilder,
Action<AzureAppConfigurationOptions> action,
IConfigurationClientFactory configurationClientFactory)
{
return configurationBuilder.Add(new AzureAppConfigurationSource(action, optional: false, configurationClientFactory));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ public class AzureAppConfigurationOptions
internal string ConnectionString { get; private set; }

/// <summary>
/// The endpoint of the Azure App Configuration.
/// The list of endpoints of an Azure App Configuration store.
/// If this property is set, the <see cref="Credential"/> property also needs to be set.
/// </summary>
internal Uri Endpoint { get; private set; }
internal IEnumerable<Uri> Endpoints { get; private set; }

/// <summary>
/// The connection string to use to connect to Azure App Configuration.
/// If this property is set, the <see cref="Endpoint"/> property also needs to be set.
/// The credential used to connect to the Azure App Configuration.
/// If this property is set, the <see cref="Endpoints"/> property also needs to be set.
/// </summary>
internal TokenCredential Credential { get; private set; }

Expand Down Expand Up @@ -83,9 +83,10 @@ internal IEnumerable<IKeyValueAdapter> Adapters
internal IEnumerable<string> KeyPrefixes => _keyPrefixes;

/// <summary>
/// An optional client that can be used to communicate with Azure App Configuration. If provided, the connection string property will be ignored.
/// An optional configuration client manager that can be used to provide clients to communicate with Azure App Configuration.
/// </summary>
internal ConfigurationClient Client { get; set; }
/// <remarks>This property is used only for unit testing.</remarks>
internal IConfigurationClientManager ClientManager { get; set; }

/// <summary>
/// Options used to configure the client used to communicate with Azure App Configuration.
Expand Down Expand Up @@ -256,7 +257,7 @@ public AzureAppConfigurationOptions Connect(string connectionString)
throw new ArgumentNullException(nameof(connectionString));
}

Endpoint = null;
Endpoints = null;
Credential = null;
ConnectionString = connectionString;
return this;
Expand All @@ -279,9 +280,30 @@ public AzureAppConfigurationOptions Connect(Uri endpoint, TokenCredential creden
throw new ArgumentNullException(nameof(credential));
}

return Connect(new List<Uri>() { endpoint }, credential);
}

/// <summary>
/// Connect the provider to an Azure App Configuration store and its replicas using a list of endpoints and a token credential.
/// </summary>
/// <param name="endpoints">The list of endpoints of an Azure App Configuration store and its replicas to connect to.</param>
/// <param name="credential">Token credential to use to connect.</param>
public AzureAppConfigurationOptions Connect(IEnumerable<Uri> endpoints, TokenCredential credential)
{
if (endpoints == null || !endpoints.Any())
{
throw new ArgumentNullException(nameof(endpoints));
}

if (endpoints.Distinct(new EndpointComparer()).Count() != endpoints.Count())
{
throw new ArgumentException($"All values in '{nameof(endpoints)}' must be unique.");
}

Credential = credential ?? throw new ArgumentNullException(nameof(credential));

Endpoints = endpoints;
ConnectionString = null;
Endpoint = endpoint;
Credential = credential;
return this;
}

Expand Down
Loading