1- using BotSharp . Abstraction . Graph ;
2- using BotSharp . Abstraction . Graph . Models ;
3- using BotSharp . Abstraction . Graph . Options ;
4- using BotSharp . Abstraction . Models ;
5- using BotSharp . Abstraction . Options ;
6- using BotSharp . Abstraction . Utilities ;
7- using BotSharp . Plugin . Membase . Interfaces ;
8- using Microsoft . Extensions . Logging ;
9- using System . Text . Json ;
1+ using Polly ;
2+ using Polly . Timeout ;
3+ using Refit ;
104
115namespace BotSharp . Plugin . Membase . GraphDb ;
126
@@ -28,6 +22,33 @@ public MembaseGraphDb(
2822
2923 public string Provider => "membase" ;
3024
25+ private const int RetryCount = 3 ;
26+
27+ private AsyncPolicy BuildRetryPolicy ( )
28+ {
29+ var settings = _services . GetRequiredService < MembaseSettings > ( ) ;
30+ var timeoutSeconds = ( double ) settings . TimeoutSecond / RetryCount ;
31+
32+ var timeoutPolicy = Policy . TimeoutAsync ( TimeSpan . FromSeconds ( timeoutSeconds ) ) ;
33+
34+ var retryPolicy = Policy
35+ . Handle < HttpRequestException > ( )
36+ . Or < TaskCanceledException > ( )
37+ . Or < TimeoutRejectedException > ( )
38+ . Or < ApiException > ( ex => ex . StatusCode == HttpStatusCode . ServiceUnavailable )
39+ . WaitAndRetryAsync (
40+ retryCount : RetryCount ,
41+ sleepDurationProvider : retryAttempt => TimeSpan . FromSeconds ( Math . Pow ( 2 , retryAttempt ) ) ,
42+ onRetry : ( ex , timespan , retryAttempt , _ ) =>
43+ {
44+ _logger . LogWarning ( ex ,
45+ "CypherQueryAsync retry {RetryAttempt}/{MaxRetries} after {Delay}s. Exception: {Message}" ,
46+ retryAttempt , RetryCount , timespan . TotalSeconds , ex . Message ) ;
47+ } ) ;
48+
49+ return Policy . WrapAsync ( retryPolicy , timeoutPolicy ) ;
50+ }
51+
3152 public async Task < GraphQueryResult > ExecuteQueryAsync ( string query , GraphQueryExecuteOptions ? options = null )
3253 {
3354 if ( string . IsNullOrEmpty ( options ? . GraphId ) )
@@ -36,14 +57,17 @@ public async Task<GraphQueryResult> ExecuteQueryAsync(string query, GraphQueryEx
3657 }
3758
3859 var args = options ? . Arguments ?? new ( ) ;
60+ var argLogs = JsonSerializer . Serialize ( args , BotSharpOptions . defaultJsonOptions ) ;
3961
4062 try
4163 {
42- var response = await _membaseApi . CypherQueryAsync ( options ! . GraphId , new CypherQueryRequest
43- {
44- Query = query ,
45- Parameters = args
46- } ) ;
64+ var retryPolicy = BuildRetryPolicy ( ) ;
65+ var response = await retryPolicy . ExecuteAsync ( ( ) =>
66+ _membaseApi . CypherQueryAsync ( options ! . GraphId , new CypherQueryRequest
67+ {
68+ Query = query ,
69+ Parameters = args
70+ } ) ) ;
4771
4872 return new GraphQueryResult
4973 {
@@ -52,10 +76,14 @@ public async Task<GraphQueryResult> ExecuteQueryAsync(string query, GraphQueryEx
5276 Result = JsonSerializer . Serialize ( response . Data )
5377 } ;
5478 }
79+ catch ( ApiException ex )
80+ {
81+ _logger . LogError ( $ "Error when executing query in { Provider } graph db:\r \n { ex . Content } \r \n { query } \r \n { argLogs } ") ;
82+ throw ;
83+ }
5584 catch ( Exception ex )
5685 {
57- var argLogs = args . Select ( x => ( new KeyValue ( x . Key , x . Value . ConvertToString ( BotSharpOptions . defaultJsonOptions ) ) ) . ToString ( ) ) ;
58- _logger . LogError ( ex , $ "Error when executing query in { Provider } graph db. (Query: { query } ), (Argments: \r \n { string . Join ( "\r \n " , argLogs ) } )") ;
86+ _logger . LogError ( ex , $ "Error when executing query in { Provider } graph db. (Query: { query } ), (Argments: \r \n { argLogs } )") ;
5987 throw ;
6088 }
6189 }
0 commit comments