Skip to content

Commit 483e8e6

Browse files
authored
Merge pull request #34 from granstel/optimize-dialogflow
Set regions for Dialogflow
2 parents 048eaef + 01bd66b commit 483e8e6

File tree

16 files changed

+172
-160
lines changed

16 files changed

+172
-160
lines changed

src/FillInTheTextBot.Api/DI/ConfigurationRegistration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal static void AddAppConfiguration(this IServiceCollection services, IConf
1313
services.AddSingleton(configuration);
1414
services.AddSingleton(configuration.HttpLog);
1515
services.AddSingleton(configuration.Redis);
16-
services.AddSingleton(configuration.DialogflowScopes);
16+
services.AddSingleton(configuration.Dialogflow);
1717
services.AddSingleton(configuration.Tracing);
1818
services.AddSingleton(configuration.Conversation);
1919
}

src/FillInTheTextBot.Api/DI/ExternalServicesRegistration.cs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Reflection;
5-
using FillInTheTextBot.Services;
65
using FillInTheTextBot.Services.Configuration;
76
using Google.Apis.Auth.OAuth2;
87
using Google.Cloud.Dialogflow.V2;
@@ -30,8 +29,26 @@ internal static void AddExternalServices(this IServiceCollection services)
3029
services.AddSingleton(RegisterRedisClient);
3130
services.AddSingleton(RegisterTracer);
3231
services.AddSingleton(RegisterCacheService);
32+
}
33+
34+
private static IEnumerable<ScopeContext> GetScopesContexts(IEnumerable<DialogflowConfiguration> dialogflowConfigurations)
35+
{
36+
var scopeContexts = dialogflowConfigurations
37+
.Where(configuration => !string.IsNullOrEmpty(configuration.ScopeId))
38+
.Select(configuration =>
39+
{
40+
var context = new ScopeContext(configuration.ScopeId, configuration.DoNotUseForNewSessions);
41+
42+
context.TryAddParameter(nameof(configuration.ProjectId), configuration.ProjectId);
43+
context.TryAddParameter(nameof(configuration.JsonPath), configuration.JsonPath);
44+
context.TryAddParameter(nameof(configuration.Region), configuration.Region);
45+
context.TryAddParameter(nameof(configuration.LanguageCode), configuration.LanguageCode);
46+
context.TryAddParameter(nameof(configuration.LogQuery), configuration.LogQuery.ToString());
3347

34-
services.AddSingleton<IScopeBindingStorage, ScopeBindingStorage>();
48+
return context;
49+
});
50+
51+
return scopeContexts;
3552
}
3653

3754
private static ScopesSelector<SessionsClient> RegisterSessionsClientScopes(IServiceProvider provider)
@@ -40,19 +57,22 @@ private static ScopesSelector<SessionsClient> RegisterSessionsClientScopes(IServ
4057

4158
var scopeContexts = GetScopesContexts(configuration);
4259

43-
var storage = provider.GetService<IScopeBindingStorage>();
44-
var balancer = new ScopesSelector<SessionsClient>(storage, scopeContexts, CreateDialogflowSessionsClient);
60+
var selector = new ScopesSelector<SessionsClient>(scopeContexts, CreateDialogflowSessionsClient);
4561

46-
return balancer;
62+
return selector;
4763
}
4864

4965
private static SessionsClient CreateDialogflowSessionsClient(ScopeContext context)
5066
{
51-
var credential = GoogleCredential.FromFile(context.Parameters["JsonPath"]).CreateScoped(SessionsClient.DefaultScopes);
67+
context.TryGetParameterValue(nameof(DialogflowConfiguration.JsonPath), out string jsonPath);
68+
var credential = GoogleCredential.FromFile(jsonPath).CreateScoped(SessionsClient.DefaultScopes);
69+
70+
var endpoint = GetEndpoint(context, SessionsClient.DefaultEndpoint);
5271

5372
var clientBuilder = new SessionsClientBuilder
5473
{
55-
ChannelCredentials = credential.ToChannelCredentials()
74+
ChannelCredentials = credential.ToChannelCredentials(),
75+
Endpoint = endpoint
5676
};
5777

5878
var client = clientBuilder.Build();
@@ -66,47 +86,44 @@ private static ScopesSelector<ContextsClient> RegisterContextsClientScopes(IServ
6686

6787
var contexts = GetScopesContexts(configuration);
6888

69-
var storage = provider.GetService<IScopeBindingStorage>();
70-
var balancer = new ScopesSelector<ContextsClient>(storage, contexts, CreateDialogflowContextsClient);
71-
72-
return balancer;
89+
var selector = new ScopesSelector<ContextsClient>(contexts, CreateDialogflowContextsClient);
90+
91+
return selector;
7392
}
74-
93+
7594
private static ContextsClient CreateDialogflowContextsClient(ScopeContext context)
7695
{
77-
var credential = GoogleCredential.FromFile(context.Parameters["JsonPath"]).CreateScoped(ContextsClient.DefaultScopes);
96+
context.TryGetParameterValue(nameof(DialogflowConfiguration.JsonPath), out string jsonPath);
97+
var credential = GoogleCredential.FromFile(jsonPath).CreateScoped(ContextsClient.DefaultScopes);
98+
99+
var endpoint = GetEndpoint(context, ContextsClient.DefaultEndpoint);
78100

79101
var clientBuilder = new ContextsClientBuilder
80102
{
81-
ChannelCredentials = credential.ToChannelCredentials()
103+
ChannelCredentials = credential.ToChannelCredentials(),
104+
Endpoint = endpoint
82105
};
83106

84107
var client = clientBuilder.Build();
85108

86109
return client;
87110
}
88111

89-
private static ICollection<ScopeContext> GetScopesContexts(DialogflowConfiguration[] dialogflowScopes)
112+
private static string GetEndpoint(ScopeContext context, string defaultEndpoint)
90113
{
91-
var scopeContexts = dialogflowScopes.Where(i => !string.IsNullOrEmpty(i.ProjectId))
92-
.Select(i =>
93-
{
94-
var context = new ScopeContext(i.ProjectId);
95-
96-
context.Parameters.Add("ProjectId", i.ProjectId);
97-
context.Parameters.Add("JsonPath", i.JsonPath);
98-
context.Parameters.Add("LogQuery", i.LogQuery.ToString());
99-
context.Parameters.Add("LanguageCode", i.LanguageCode);
114+
context.TryGetParameterValue(nameof(DialogflowConfiguration.Region), out string region);
100115

101-
return context;
102-
})
103-
.ToList();
116+
if (string.IsNullOrWhiteSpace(region))
117+
{
118+
return defaultEndpoint;
119+
}
104120

105-
return scopeContexts;
121+
return $"{region}-{defaultEndpoint}";
106122
}
107123

108124
private static IDatabase RegisterRedisClient(IServiceProvider provider)
109125
{
126+
// TODO: get config as parameter
110127
var configuration = provider.GetService<RedisConfiguration>();
111128

112129
var redisClient = ConnectionMultiplexer.Connect(configuration.ConnectionString);
@@ -119,6 +136,7 @@ private static IDatabase RegisterRedisClient(IServiceProvider provider)
119136
private static ITracer RegisterTracer(IServiceProvider provider)
120137
{
121138
var env = provider.GetService<IWebHostEnvironment>();
139+
// TODO: get config as parameter
122140
var configuration = provider.GetService<TracingConfiguration>();
123141

124142
var serviceName = env.ApplicationName;

src/FillInTheTextBot.Api/FillInTheTextBot.Api.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>1.20.0</Version>
6-
<PackageReleaseNotes>net6.0</PackageReleaseNotes>
75
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
6+
<Version>1.21.0</Version>
7+
<PackageReleaseNotes>Optimized interaction with Dialogflow</PackageReleaseNotes>
88
</PropertyGroup>
99

1010
<ItemGroup>
1111
<PackageReference Include="Jaeger" Version="1.0.3" />
1212
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
13-
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
13+
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
1414
<PackageReference Include="NLog" Version="5.0.1" />
1515
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" />
1616
<PackageReference Include="OpenTracing" Version="0.12.1" />

src/FillInTheTextBot.Api/appsettings.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
"ExcludeBodiesWithWords": [ "ping", "pong" ],
1414
"IncludeEndpoints": [ "sber", "marusia" ]
1515
},
16-
"DialogflowScopes": [
16+
"Dialogflow": [
1717
{
18-
"ProjectId": "%FITB-DF-PROJECTID-0%",
19-
"LanguageCode": "ru",
20-
"JsonPath": "%FITB-DF-JSONPATH-0%",
21-
"LogQuery": false
18+
"ScopeId": "",
19+
"ProjectId": "",
20+
"JsonPath": "",
21+
"Region": "",
22+
"LogQuery": false,
23+
"DoNotUseForNewSessions": false
2224
}
2325
],
2426
"Redis": {

src/FillInTheTextBot.Messengers.Sber/SberService.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ protected override Models.Request Before(Request input)
3333

3434
request.NextTextIndex = Convert.ToInt32(userState?.NextTextIndex ?? 0);
3535

36+
request.ScopeKey = userState?.ScopeKey;
37+
3638
var contexts = GetContexts(input);
3739
request.RequiredContexts.AddRange(contexts);
3840

@@ -47,10 +49,13 @@ protected override async Task<Response> AfterAsync(Request input, Models.Respons
4749

4850
output = input.FillResponse(output);
4951

52+
// TODO: ScopeKey должен меняться с сессией, надо сделать SessionState. И использовать его
53+
// в других мессенджерах вместе с UserState
5054
var userState = new Models.UserState
5155
{
5256
IsOldUser = true,
53-
NextTextIndex = response.NextTextIndex
57+
NextTextIndex = response.NextTextIndex,
58+
ScopeKey = response.ScopeKey
5459
};
5560

5661
var userStateCacheKey = GetCacheKey(input.Uuid?.Sub ?? input.Uuid?.UserId);
@@ -66,6 +71,7 @@ private string TryGetSessionIdAsync(bool? newSession, string userHash)
6671

6772
_cache.TryGet(cacheKey, out string sessionId);
6873

74+
// TODO: создавать новую сессию не в этом методе (get)
6975
if (newSession == true || string.IsNullOrEmpty(sessionId))
7076
{
7177
sessionId = Guid.NewGuid().ToString("N");

src/FillInTheTextBot.Messengers.Yandex/YandexService.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,14 @@ public class YandexService : MessengerService<InputModel, OutputModel>, IYandexS
1414
private const string PingCommand = "ping";
1515
private const string PongResponse = "pong";
1616

17-
private readonly Stopwatch _stopwatch;
18-
1917
public YandexService(
2018
ILogger<YandexService> log,
2119
IConversationService conversationService) : base(log, conversationService)
2220
{
23-
_stopwatch = new Stopwatch();
2421
}
2522

2623
protected override Models.Request Before(InputModel input)
2724
{
28-
_stopwatch.Start();
29-
3025
var request = input.ToRequest();
3126

3227
input.TryGetFromUserState(Models.Request.IsOldUserKey, out bool isOldUser);
@@ -76,13 +71,6 @@ protected override Task<OutputModel> AfterAsync(InputModel input, Models.Respons
7671

7772
output.AddToSessionState(Models.Response.ScopeStorageKey, response.ScopeKey);
7873

79-
_stopwatch.Stop();
80-
81-
if (_stopwatch.ElapsedMilliseconds > 1000)
82-
{
83-
output.AddAnalyticsEvent("ElapsedTime", new Dictionary<string, object> { { "ElapsedMilliseconds", _stopwatch.ElapsedMilliseconds } });
84-
}
85-
8674
output.AddAnalyticsEvent(Models.Response.ScopeStorageKey, new Dictionary<string, object> { { Models.Response.ScopeStorageKey, response.ScopeKey } });
8775

8876
return Task.FromResult(output);

src/FillInTheTextBot.Models/FillInTheTextBot.Models.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
8+
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
99
</ItemGroup>
1010

1111
</Project>

src/FillInTheTextBot.Models/UserState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ public class UserState
55
public bool IsOldUser { get; set; }
66

77
public int NextTextIndex { get; set; }
8+
9+
public string ScopeKey { get; set; }
810
}
911
}

src/FillInTheTextBot.Services/Configuration/AppConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public class AppConfiguration
44
{
55
public HttpLogConfiguration HttpLog { get; set; }
66

7-
public DialogflowConfiguration[] DialogflowScopes { get; set; }
7+
public DialogflowConfiguration[] Dialogflow { get; set; }
88

99
public RedisConfiguration Redis { get; set; }
1010

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
11
namespace FillInTheTextBot.Services.Configuration
22
{
3-
public class DialogflowConfiguration : Configuration
3+
public class DialogflowConfiguration
44
{
5-
private string _projectId;
6-
public virtual string ProjectId
7-
{
8-
get => _projectId;
9-
set => _projectId = ExpandVariable(value);
10-
}
5+
public virtual string ScopeId { get; set; }
116

12-
private string _languageCode;
13-
public virtual string LanguageCode
14-
{
15-
get => _languageCode;
16-
set => _languageCode = ExpandVariable(value);
17-
}
7+
public virtual string ProjectId { get; set; }
188

19-
private string _jsonPath;
20-
public virtual string JsonPath
21-
{
22-
get => _jsonPath;
23-
set => _jsonPath = ExpandVariable(value);
24-
}
9+
public virtual string JsonPath { get; set; }
10+
11+
public virtual string Region { get; set; }
12+
13+
public virtual string LanguageCode => "ru";
2514

2615
public bool LogQuery { get; set; }
16+
17+
public bool DoNotUseForNewSessions { get; set; }
2718
}
2819
}

src/FillInTheTextBot.Services/ConversationService.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task<Response> GetResponseAsync(Request request)
6060

6161
response.Buttons = GetButtonsFromPayload(response.Buttons, dialog?.Payload, request.Source);
6262

63-
response = await TryGetAnswerForCancelsSlotFilling(dialog?.CancelsSlotFilling, response, request.SessionId);
63+
response = await TryGetAnswerForCancelsSlotFilling(dialog?.CancelsSlotFilling, response, request.SessionId, request.ScopeKey);
6464
response.Text = GetResponseText(request.Appeal, response.Text);
6565

6666
var texts = TryAddReplacementsFromPayload(dialog?.Payload, request.Source, response.Text);
@@ -69,7 +69,7 @@ public async Task<Response> GetResponseAsync(Request request)
6969

7070
response.Emotions = GetEmotions(dialog);
7171

72-
TrySetSavedText(request.SessionId, dialog, texts);
72+
TrySetSavedText(request.SessionId, request.ScopeKey, dialog, texts);
7373

7474
return response;
7575
}
@@ -117,9 +117,7 @@ private async Task<Response> GetText(Request request, string startText, string t
117117
{
118118
using (Tracing.Trace(operationName: "Get texts from cache"))
119119
{
120-
_cache.TryGet($"Texts-{request.Source}", out string[] texts);
121-
122-
if (texts?.Any() != true && !_cache.TryGet("Texts", out texts))
120+
if (!_cache.TryGet("Texts", out string[] texts))
123121
{
124122
response.Text = "Что-то у меня не нашлось никаких текстов...";
125123

@@ -133,7 +131,7 @@ private async Task<Response> GetText(Request request, string startText, string t
133131
var eventName = $"event:{textKey}";
134132

135133

136-
var dialog = await _dialogflowService.GetResponseAsync(eventName, request.SessionId, textKey);
134+
var dialog = await _dialogflowService.GetResponseAsync(eventName, request.SessionId, request.ScopeKey);
137135

138136

139137
var textName = dialog?.GetParameters("text-name")?.FirstOrDefault();
@@ -274,7 +272,7 @@ private ICollection<Button> GetButtonsFromPayload(ICollection<Button> responseBu
274272
}
275273
}
276274

277-
private void TrySetSavedText(string sessionId, Dialog dialog, Texts texts)
275+
private void TrySetSavedText(string sessionId, string scopeKey, Dialog dialog, Texts texts)
278276
{
279277
if (dialog?.ParametersIncomplete != true && string.Equals(dialog?.Action ?? string.Empty, "saveToRepeat", StringComparison.InvariantCultureIgnoreCase))
280278
{
@@ -284,7 +282,7 @@ private void TrySetSavedText(string sessionId, Dialog dialog, Texts texts)
284282
{ "alternativeText", texts.AlternativeText }
285283
};
286284

287-
_dialogflowService.SetContextAsync(sessionId, "savedText", 5, parameters).Forget();
285+
_dialogflowService.SetContextAsync(sessionId, scopeKey, "savedText", 5, parameters).Forget();
288286
}
289287
}
290288

@@ -299,7 +297,7 @@ private Request ResetContextsWhenHelpOrExitRequest(Request request)
299297
}
300298

301299
private async Task<Response> TryGetAnswerForCancelsSlotFilling(bool? isCancelsSlotFilling, Response response,
302-
string sessionId)
300+
string sessionId, string scopeKey)
303301
{
304302
if (isCancelsSlotFilling is not true)
305303
{
@@ -308,7 +306,7 @@ private async Task<Response> TryGetAnswerForCancelsSlotFilling(bool? isCancelsSl
308306

309307
const string eventName = $"event:CancelsSlotFilling";
310308

311-
var cancelsSlotFillingDialog = await _dialogflowService.GetResponseAsync(eventName, sessionId);
309+
var cancelsSlotFillingDialog = await _dialogflowService.GetResponseAsync(eventName, sessionId, scopeKey);
312310

313311
response.Text = $"{response.Text} {cancelsSlotFillingDialog.Response}";
314312
response.Buttons = cancelsSlotFillingDialog.Buttons;

0 commit comments

Comments
 (0)