Add resource supply contract export by its guid
This commit is contained in:
@ -130,38 +130,15 @@ namespace Hcs.Client.Api.Request
|
||||
{
|
||||
try
|
||||
{
|
||||
if (request == null)
|
||||
if (CanBeRestarted)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
return await RunRepeatableTaskInsistentlyAsync(
|
||||
async () => await ExecuteSendAndWaitResultAsync(request, sender, token), token);
|
||||
}
|
||||
|
||||
var version = RequestHelper.GetRequestVersionString(request);
|
||||
client.TryLog($"Executing request {RemoteAddress.Uri}/{request.GetType().Name} of version {version}...");
|
||||
|
||||
TAck ack;
|
||||
|
||||
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
using (var asyncClient = CreateAsyncClient())
|
||||
else
|
||||
{
|
||||
ack = await sender(asyncClient);
|
||||
return await ExecuteSendAndWaitResultAsync(request, sender, token);
|
||||
}
|
||||
stopWatch.Stop();
|
||||
|
||||
client.TryLog($"Request executed in {stopWatch.ElapsedMilliseconds} ms, result GUID is {ack.MessageGUID}");
|
||||
|
||||
var result = await WaitForResultAsync(ack, true, token);
|
||||
if (result is IQueryable queryableResult)
|
||||
{
|
||||
queryableResult.OfType<TErrorMessage>().ToList().ForEach(x =>
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
});
|
||||
}
|
||||
else if (result is TErrorMessage x)
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (RestartTimeoutException e)
|
||||
{
|
||||
@ -175,6 +152,108 @@ namespace Hcs.Client.Api.Request
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Для запросов к серверу которые можно направлять несколько раз, разрешаем
|
||||
/// серверу аномально отказаться. Предполагается, что здесь мы игнорируем
|
||||
/// только жесткие отказы серверной инфраструктуры, которые указывают
|
||||
/// что запрос даже не был принят в обработку. Также все запросы на
|
||||
/// чтение можно повторять в случае их серверных системных ошибок.
|
||||
/// </summary>
|
||||
protected async Task<TRepeatableResult> RunRepeatableTaskInsistentlyAsync<TRepeatableResult>(
|
||||
Func<Task<TRepeatableResult>> func, CancellationToken token)
|
||||
{
|
||||
var afterErrorDelaySec = 120;
|
||||
for (var attempt = 1; ; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
if (CanIgnoreSuchException(e, out string marker))
|
||||
{
|
||||
client.TryLog($"Ignoring error of attempt #{attempt} with type [{marker}]");
|
||||
client.TryLog($"Waiting {afterErrorDelaySec} sec until next attempt...");
|
||||
|
||||
await Task.Delay(afterErrorDelaySec * 1000, token);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e is RestartTimeoutException)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (e is RemoteException)
|
||||
{
|
||||
throw RemoteException.CreateNew(e as RemoteException);
|
||||
}
|
||||
|
||||
throw new System.Exception("Cannot ignore this exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanIgnoreSuchException(System.Exception e, out string resultMarker)
|
||||
{
|
||||
foreach (var marker in ignorableSystemErrorMarkers)
|
||||
{
|
||||
var found = Util.EnumerateInnerExceptions(e).Find(
|
||||
x => x.Message != null && x.Message.Contains(marker));
|
||||
if (found != null)
|
||||
{
|
||||
resultMarker = marker;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resultMarker = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<TResult> ExecuteSendAndWaitResultAsync(
|
||||
object request,
|
||||
Func<TAsyncClient, Task<TAck>> sender,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
var version = RequestHelper.GetRequestVersionString(request);
|
||||
client.TryLog($"Executing request {RemoteAddress.Uri}/{request.GetType().Name} of version {version}...");
|
||||
|
||||
TAck ack;
|
||||
|
||||
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
using (var asyncClient = CreateAsyncClient())
|
||||
{
|
||||
ack = await sender(asyncClient);
|
||||
}
|
||||
stopWatch.Stop();
|
||||
|
||||
client.TryLog($"Request executed in {stopWatch.ElapsedMilliseconds} ms, result GUID is {ack.MessageGUID}");
|
||||
|
||||
var result = await WaitForResultAsync(ack, true, token);
|
||||
if (result is IQueryable queryableResult)
|
||||
{
|
||||
queryableResult.OfType<TErrorMessage>().ToList().ForEach(x =>
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
});
|
||||
}
|
||||
else if (result is TErrorMessage x)
|
||||
{
|
||||
throw RemoteException.CreateNew(x.ErrorCode, x.Description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private TAsyncClient CreateAsyncClient()
|
||||
{
|
||||
var asyncClient = (TAsyncClient)Activator.CreateInstance(typeof(TAsyncClient), binding, RemoteAddress);
|
||||
@ -340,68 +419,5 @@ namespace Hcs.Client.Api.Request
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Для запросов к серверу которые можно направлять несколько раз, разрешаем
|
||||
/// серверу аномально отказаться. Предполагается, что здесь мы игнорируем
|
||||
/// только жесткие отказы серверной инфраструктуры, которые указывают
|
||||
/// что запрос даже не был принят в обработку. Также все запросы на
|
||||
/// чтение можно повторять в случае их серверных системных ошибок.
|
||||
/// </summary>
|
||||
protected async Task<TRepeatableResult> RunRepeatableTaskInsistentlyAsync<TRepeatableResult>(
|
||||
Func<Task<TRepeatableResult>> func, CancellationToken token)
|
||||
{
|
||||
var afterErrorDelaySec = 120;
|
||||
for (var attempt = 1; ; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await func();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
if (CanIgnoreSuchException(e, out string marker))
|
||||
{
|
||||
client.TryLog($"Ignoring error of attempt #{attempt} with type [{marker}]");
|
||||
client.TryLog($"Waiting {afterErrorDelaySec} sec until next attempt...");
|
||||
|
||||
await Task.Delay(afterErrorDelaySec * 1000, token);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e is RestartTimeoutException)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (e is RemoteException)
|
||||
{
|
||||
throw RemoteException.CreateNew(e as RemoteException);
|
||||
}
|
||||
|
||||
throw new System.Exception("Cannot ignore this exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanIgnoreSuchException(System.Exception e, out string resultMarker)
|
||||
{
|
||||
foreach (var marker in ignorableSystemErrorMarkers)
|
||||
{
|
||||
var found = Util.EnumerateInnerExceptions(e).Find(
|
||||
x => x.Message != null && x.Message.Contains(marker));
|
||||
if (found != null)
|
||||
{
|
||||
resultMarker = marker;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resultMarker = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user