163 lines
7.0 KiB
C#
163 lines
7.0 KiB
C#
using Hcs.ClientApi.RemoteCaller;
|
||
using System;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
using HouseManagement = Hcs.Service.Async.HouseManagement.v15_7_0_1;
|
||
|
||
namespace Hcs.Service.Async.HouseManagement.v15_7_0_1
|
||
{
|
||
public partial class AckRequestAck : IHcsAck { }
|
||
public partial class getStateResult : IHcsGetStateResult { }
|
||
public partial class Fault : IHcsFault { }
|
||
public partial class HeaderType : IHcsHeaderType { }
|
||
}
|
||
|
||
namespace Hcs.ClientApi.HouseManagementApi
|
||
{
|
||
public class HcsHouseManagementMethod : HcsRemoteCallMethod
|
||
{
|
||
public HcsEndPoints EndPoint => HcsEndPoints.HomeManagementAsync;
|
||
|
||
public HouseManagement.RequestHeader CreateRequestHeader() =>
|
||
HcsRequestHelper.CreateHeader<HouseManagement.RequestHeader>(ClientConfig);
|
||
|
||
public HcsHouseManagementMethod(HcsClientConfig config) : base(config) { }
|
||
|
||
public System.ServiceModel.EndpointAddress RemoteAddress
|
||
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
|
||
|
||
private HouseManagement.HouseManagementPortsTypeAsyncClient NewPortClient()
|
||
{
|
||
var client = new HouseManagement.HouseManagementPortsTypeAsyncClient(_binding, RemoteAddress);
|
||
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
|
||
return client;
|
||
}
|
||
|
||
public async Task<IHcsGetStateResult> SendAndWaitResultAsync(
|
||
object request,
|
||
Func<HouseManagement.HouseManagementPortsTypeAsyncClient, Task<IHcsAck>> sender,
|
||
CancellationToken token)
|
||
{
|
||
while (true)
|
||
{
|
||
token.ThrowIfCancellationRequested();
|
||
|
||
try
|
||
{
|
||
if (CanBeRestarted)
|
||
{
|
||
return await RunRepeatableTaskInsistentlyAsync(
|
||
async () => await SendAndWaitResultAsyncImpl(request, sender, token), token);
|
||
}
|
||
else
|
||
{
|
||
return await SendAndWaitResultAsyncImpl(request, sender, token);
|
||
}
|
||
}
|
||
catch (HcsRestartTimeoutException e)
|
||
{
|
||
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
|
||
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
|
||
}
|
||
}
|
||
}
|
||
|
||
private async Task<IHcsGetStateResult> SendAndWaitResultAsyncImpl(
|
||
object request,
|
||
Func<HouseManagement.HouseManagementPortsTypeAsyncClient, Task<IHcsAck>> sender,
|
||
CancellationToken token)
|
||
{
|
||
if (request == null) throw new ArgumentNullException(nameof(request));
|
||
string version = HcsRequestHelper.GetRequestVersionString(request);
|
||
_config.Log($"Отправляем запрос: {RemoteAddress.Uri}/{request.GetType().Name} в версии {version}...");
|
||
|
||
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
|
||
|
||
IHcsAck ack;
|
||
using (var client = NewPortClient())
|
||
{
|
||
ack = await sender(client);
|
||
}
|
||
|
||
stopWatch.Stop();
|
||
_config.Log($"Запрос принят в обработку за {stopWatch.ElapsedMilliseconds}мс., подтверждение {ack.MessageGUID}");
|
||
|
||
var stateResult = await WaitForResultAsync(ack, true, token);
|
||
|
||
stateResult.Items.OfType<HouseManagement.ErrorMessageType>().ToList().ForEach(x =>
|
||
{
|
||
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
|
||
});
|
||
|
||
return stateResult;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выполняет однократную проверку наличия результата.
|
||
/// Возвращает null если результата еще нет.
|
||
/// </summary>
|
||
protected override async Task<IHcsGetStateResult> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
|
||
{
|
||
using (var client = NewPortClient())
|
||
{
|
||
var requestHeader = HcsRequestHelper.CreateHeader<HouseManagement.RequestHeader>(_config);
|
||
var requestBody = new HouseManagement.getStateRequest { MessageGUID = sourceAck.MessageGUID };
|
||
|
||
var response = await client.getStateAsync(requestHeader, requestBody);
|
||
var resultBody = response.getStateResult;
|
||
|
||
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
|
||
{
|
||
return resultBody;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Разбирает стандартный ответ HCS на операцию импорта с приемом ошибок
|
||
/// </summary>
|
||
protected HouseManagement.getStateResultImportResultCommonResult ParseSingleImportResult(IHcsGetStateResult stateResult)
|
||
{
|
||
return ParseImportResults(stateResult, 1, true).First();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Разбирает стандартный ответ HCS на операцию импорта с приемом ошибок
|
||
/// </summary>
|
||
protected HouseManagement.getStateResultImportResultCommonResult[] ParseImportResults(
|
||
IHcsGetStateResult stateResult, int commonResultRequiredCount, bool checkItemErrors)
|
||
{
|
||
var importResult = RequireSingleItem<HouseManagement.getStateResultImportResult>(stateResult.Items);
|
||
if (IsArrayEmpty(importResult.Items)) throw new HcsException("Пустой ImportResult.Items");
|
||
importResult.Items.OfType<HouseManagement.ErrorMessageType>().ToList()
|
||
.ForEach(error => { throw HcsRemoteException.CreateNew(error.ErrorCode, error.Description); });
|
||
|
||
var commonResults = importResult.Items.OfType<HouseManagement.getStateResultImportResultCommonResult>();
|
||
|
||
foreach (var commonResult in commonResults)
|
||
{
|
||
if (IsArrayEmpty(commonResult.Items)) throw new HcsException("Пустой CommonResult.Items");
|
||
if (checkItemErrors) CheckCommonResultErrors(commonResult);
|
||
}
|
||
|
||
if (commonResults.Count() != commonResultRequiredCount)
|
||
{
|
||
throw new HcsException(
|
||
$"Число результатов {commonResults.Count()} типа CommonResult не равно {commonResultRequiredCount}");
|
||
}
|
||
|
||
return commonResults.ToArray();
|
||
}
|
||
|
||
protected void CheckCommonResultErrors(HouseManagement.getStateResultImportResultCommonResult commonResult)
|
||
{
|
||
commonResult.Items.OfType<HouseManagement.CommonResultTypeError>().ToList()
|
||
.ForEach(error => { throw HcsRemoteException.CreateNew(error.ErrorCode, error.Description); });
|
||
}
|
||
}
|
||
}
|