-
-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathMachineServiceCollectionExtensions.cs
More file actions
117 lines (111 loc) · 5.09 KB
/
MachineServiceCollectionExtensions.cs
File metadata and controls
117 lines (111 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#nullable disable warnings
using System;
using System.Net;
using System.Net.Http;
using Duende.IdentityModel.Client;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Polly;
using Polly.CircuitBreaker;
using Polly.Retry;
using Polly.Timeout;
using Serval.Client;
using SIL.XForge.Configuration;
using SIL.XForge.Scripture.Models;
using SIL.XForge.Scripture.Services;
namespace Microsoft.Extensions.DependencyInjection;
public static class MachineServiceCollectionExtensions
{
public static IServiceCollection AddSFMachine(
this IServiceCollection services,
IConfiguration configuration,
IWebHostEnvironment env
)
{
// Set up the Machine API
var servalOptions = configuration.GetOptions<ServalOptions>();
services.AddDistributedMemoryCache();
services
.AddClientCredentialsTokenManagement()
.AddClient(
MachineApi.TokenClientName,
client =>
{
client.TokenEndpoint = servalOptions.TokenUrl;
client.ClientId = servalOptions.ClientId;
client.ClientSecret = servalOptions.ClientSecret;
client.Parameters = new Parameters { { "audience", servalOptions.Audience } };
}
);
services
.AddClientCredentialsHttpClient(
MachineApi.HttpClientName,
MachineApi.TokenClientName,
configureClient: client => client.BaseAddress = new Uri(servalOptions.ApiServer)
)
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
if (env.IsDevelopment() || env.IsEnvironment("Testing"))
{
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
}
return handler;
});
services
.AddHttpClient(MachineApi.HttpClientName)
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy())
.AddPolicyHandler(GetTimeoutPolicy());
services.AddSingleton<ITranslationEnginesClient, TranslationEnginesClient>(sp =>
{
// Instantiate the translation engines client with our named HTTP client
var factory = sp.GetService<IHttpClientFactory>();
var httpClient = factory.CreateClient(MachineApi.HttpClientName);
return new TranslationEnginesClient(httpClient);
});
services.AddSingleton<ITranslationEngineTypesClient, TranslationEngineTypesClient>(sp =>
{
// Instantiate the translation engines client with our named HTTP client
var factory = sp.GetService<IHttpClientFactory>();
var httpClient = factory.CreateClient(MachineApi.HttpClientName);
return new TranslationEngineTypesClient(httpClient);
});
services.AddSingleton<IDataFilesClient, DataFilesClient>(sp =>
{
// Instantiate the data files client with our named HTTP client
var factory = sp.GetService<IHttpClientFactory>();
var httpClient = factory.CreateClient(MachineApi.HttpClientName);
return new DataFilesClient(httpClient);
});
services.AddSingleton<ICorporaClient, CorporaClient>(sp =>
{
// Instantiate the corpora client with our named HTTP client
var factory = sp.GetService<IHttpClientFactory>();
var httpClient = factory.CreateClient(MachineApi.HttpClientName);
return new CorporaClient(httpClient);
});
services.AddSingleton<IMachineApiService, MachineApiService>();
services.AddSingleton<IMachineProjectService, MachineProjectService>();
services.AddSingleton<IPreTranslationService, PreTranslationService>();
services.AddSingleton<ITrainingDataService, TrainingDataService>();
return services;
}
private static AsyncRetryPolicy<HttpResponseMessage> GetRetryPolicy() =>
Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.OrResult(r => r.StatusCode >= HttpStatusCode.InternalServerError)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
private static AsyncCircuitBreakerPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() =>
Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.OrResult(r => r.StatusCode >= HttpStatusCode.InternalServerError)
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
private static AsyncTimeoutPolicy<HttpResponseMessage> GetTimeoutPolicy() =>
// NOTE: The Serval Get Build endpoint has a long polling timeout of 40 seconds,
// so ensure any timeout values support this
Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMinutes(5), TimeoutStrategy.Pessimistic);
}