Skip to content

Commit

Permalink
Fix serialization issues, assembly search
Browse files Browse the repository at this point in the history
elsand committed Aug 31, 2022
1 parent d8173ca commit d19736a
Showing 1 changed file with 47 additions and 37 deletions.
84 changes: 47 additions & 37 deletions Dan.Common/Extensions/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Azure.Core.Serialization;
using Dan.Common.Interfaces;
using Microsoft.Azure.Functions.Worker;
@@ -15,76 +13,88 @@ namespace Dan.Common.Extensions;
public static class HostBuilderExtensions
{
/// <summary>
/// Sets up the isolated worker function with default configuration and wiring with ConfigureFunctionsWorkerDefaults(), handling application insights
/// logging and correct JSON serialization settings. Also adds defaults services; HttpClientFactory with a circuit-breaker enabled named client (use Constants.SafeHttpClient)
/// which should be used for outbound requests to the data source. Also expects to find a service implementing IEvidenceSourceMetadata.
/// Sets up the isolated worker function with default configuration and wiring with ConfigureFunctionsWorkerDefaults(),
/// handling application insights
/// logging and correct JSON serialization settings. Also adds defaults services; HttpClientFactory with a
/// circuit-breaker enabled named client (use Constants.SafeHttpClient)
/// which should be used for outbound requests to the data source. Also expects to find a service implementing
/// IEvidenceSourceMetadata.
/// </summary>
/// <param name="builder">The host builder</param>
/// <returns>The host builder for additional chaining</returns>
/// <exception cref="NotImplementedException">Thrown if IEvidenceSourceMetadata is not implemented in the same assembly</exception>
public static IHostBuilder ConfigureDanPluginDefaults(this IHostBuilder builder)
{
builder.ConfigureFunctionsWorkerDefaults(workerBuilder =>
{
workerBuilder
// Using preview package Microsoft.Azure.Functions.Worker.ApplicationInsights, see https://github.com/Azure/azure-functions-dotnet-worker/pull/944
// Requires APPLICATIONINSIGHTS_CONNECTION_STRING being set. Note that host.json logging settings will have to be replicated to worker.json
.AddApplicationInsights()
.AddApplicationInsightsLogger();
}, options => { options.Serializer = new NewtonsoftJsonObjectSerializer(); })
{
workerBuilder
// Using preview package Microsoft.Azure.Functions.Worker.ApplicationInsights, see https://github.com/Azure/azure-functions-dotnet-worker/pull/944
// Requires APPLICATIONINSIGHTS_CONNECTION_STRING being set. Note that host.json logging settings will have to be replicated to worker.json
.AddApplicationInsights()
.AddApplicationInsightsLogger();
}, options =>
{
options.Serializer = new NewtonsoftJsonObjectSerializer(
// Use Newtonsoft.Json for serializing in order to support TypeNameHandling and other annotations on. This should be ported to System.Text.Json at some point.
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
NullValueHandling = NullValueHandling.Ignore
});
})
.ConfigureServices((context, services) =>
{
services.AddLogging();
services.AddHttpClient();

var openCircuitTimeSeconds = int.TryParse(context.Configuration["DefaultCircuitBreakerOpenCircuitTimeSeconds"], out var result) ? result : 10;
var failuresBeforeTripping = int.TryParse(context.Configuration["DefaultCircuitBreakerFailureBeforeTripping"], out result) ? result : 4;
var openCircuitTimeSeconds =
int.TryParse(context.Configuration["DefaultCircuitBreakerOpenCircuitTimeSeconds"], out var result)
? result
: 10;
var failuresBeforeTripping =
int.TryParse(context.Configuration["DefaultCircuitBreakerFailureBeforeTripping"], out result)
? result
: 4;

var registry = new PolicyRegistry()
var registry = new PolicyRegistry
{
{
Constants.SafeHttpClientPolicy,
HttpPolicyExtensions.HandleTransientHttpError()
.CircuitBreakerAsync(
handledEventsAllowedBeforeBreaking: failuresBeforeTripping,
durationOfBreak: TimeSpan.FromSeconds(openCircuitTimeSeconds))
failuresBeforeTripping,
TimeSpan.FromSeconds(openCircuitTimeSeconds))
}
};
services.AddPolicyRegistry(registry);

var httpClientTimeoutSeconds = int.TryParse(context.Configuration["SafeHttpClientTimeout"], out result) ? result : 30;
var httpClientTimeoutSeconds = int.TryParse(context.Configuration["SafeHttpClientTimeout"], out result)
? result
: 30;

// Client configured with circuit breaker policies
services.AddHttpClient(Constants.SafeHttpClient,
client => { client.Timeout = TimeSpan.FromSeconds(httpClientTimeoutSeconds); })
.AddPolicyHandlerFromRegistry(Constants.SafeHttpClientPolicy);

services.Configure<JsonSerializerOptions>(options =>
{
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.Converters.Add(new JsonStringEnumConverter());
});

// Try to add the first IEvidenceSourceMetadata implementation we can find
// Try to add the first IEvidenceSourceMetadata implementation we can find in the entry assembly
var evidenceSourceMetadataServiceType = typeof(IEvidenceSourceMetadata);
var assembly = Assembly.GetExecutingAssembly();
var assembly = Assembly.GetEntryAssembly();

var implementationType = assembly.GetTypes()
.FirstOrDefault(t => t.GetInterfaces().Any(i => i == evidenceSourceMetadataServiceType));
var implementationType = assembly?.GetTypes()
.FirstOrDefault(t => t.GetInterfaces().Any(i => i == evidenceSourceMetadataServiceType));

if (implementationType == null)
{
throw new NotImplementedException(
$"Missing implementation of {nameof(IEvidenceSourceMetadata)}");
}
$"Missing implementation of {nameof(IEvidenceSourceMetadata)} in entry assembly {assembly?.FullName ?? "(unmanaged assembly)"}");

if (!services.Any(s => s.ServiceType == evidenceSourceMetadataServiceType && s.ImplementationType == implementationType))
{
services.Add(new ServiceDescriptor(evidenceSourceMetadataServiceType, implementationType, ServiceLifetime.Singleton));
}
if (!services.Any(s =>
s.ServiceType == evidenceSourceMetadataServiceType &&
s.ImplementationType == implementationType))
services.Add(new ServiceDescriptor(evidenceSourceMetadataServiceType, implementationType,
ServiceLifetime.Singleton));
});

return builder;
}
}
}

0 comments on commit d19736a

Please sign in to comment.