using MxGateway.Contracts.Proto; namespace MxGateway.Client; public static class MxCommandReplyExtensions { public static MxCommandReply EnsureProtocolSuccess(this MxCommandReply reply) { ArgumentNullException.ThrowIfNull(reply); ProtocolStatusCode code = reply.ProtocolStatus?.Code ?? ProtocolStatusCode.Unspecified; if (code is ProtocolStatusCode.Ok or ProtocolStatusCode.MxaccessFailure) { return reply; } throw CreateProtocolException(reply, code); } public static MxCommandReply EnsureMxAccessSuccess(this MxCommandReply reply) { ArgumentNullException.ThrowIfNull(reply); bool mxAccessFailure = reply.ProtocolStatus?.Code is ProtocolStatusCode.MxaccessFailure; bool hResultFailure = reply.HasHresult && reply.Hresult != 0; bool statusFailure = reply.Statuses.Any(status => !status.IsSuccess()); if (!mxAccessFailure && !hResultFailure && !statusFailure) { return reply; } throw new MxAccessException(CreateMxAccessMessage(reply), reply); } private static MxGatewayException CreateProtocolException( MxCommandReply reply, ProtocolStatusCode code) { string message = CreateProtocolMessage(reply); int? hResult = reply.HasHresult ? reply.Hresult : null; MxStatusProxy[] statuses = reply.Statuses.ToArray(); return code switch { ProtocolStatusCode.SessionNotFound or ProtocolStatusCode.SessionNotReady => new MxGatewaySessionException( message, reply.SessionId, reply.CorrelationId, reply.ProtocolStatus, hResult, statuses), ProtocolStatusCode.WorkerUnavailable => new MxGatewayWorkerException( message, reply.SessionId, reply.CorrelationId, reply.ProtocolStatus, hResult, statuses), _ => new MxGatewayCommandException( message, reply.SessionId, reply.CorrelationId, reply.ProtocolStatus, hResult, statuses), }; } private static string CreateProtocolMessage(MxCommandReply reply) { string statusMessage = string.IsNullOrWhiteSpace(reply.ProtocolStatus?.Message) ? "Gateway protocol failure." : reply.ProtocolStatus.Message; return $"{statusMessage} code={reply.ProtocolStatus?.Code}; session={reply.SessionId}; correlation={reply.CorrelationId}"; } private static string CreateMxAccessMessage(MxCommandReply reply) { string statusSummary = reply.Statuses.Count is 0 ? "no MXSTATUS_PROXY entries" : string.Join("; ", reply.Statuses.Select(status => status.ToDiagnosticSummary())); string hResult = reply.HasHresult ? $"0x{reply.Hresult:X8}" : "none"; return $"MXAccess command failed. kind={reply.Kind}; hresult={hResult}; statuses={statusSummary}"; } }