/// <summary> /// The method executed server side /// </summary> /// <param name="request"></param> public virtual void ExecuteRemoteAsync(AsyncExecutionRequest request) // this should be executing server side after encryption has been handled { Task.Run(() => { AsyncCallbackService asyncCallback = _proxyFactory.GetProxy <AsyncCallbackService>(request.RespondToHostName, request.RespondToPort, Logger); // This executes server side after the SecureChannel has decrypted and validated, need to set IsInitialized to true to // ensure the request doesn't reinitialize to a state where it believes it is an execution request // targeting SecureChannel since that is what is in the HttpContext.Request.Url ExecutionRequest execRequest = new ExecutionRequest { ClassName = request.ClassName, MethodName = request.MethodName, Ext = "json", ServiceProvider = ServiceProvider, JsonParams = request.JsonParams, IsInitialized = true, Context = HttpContext }; bool success = execRequest.Execute(); AsyncExecutionResponse response = new AsyncExecutionResponse { Success = success, Request = request, Result = execRequest.Result }; asyncCallback.RecieveAsyncExecutionResponse(response); }); }
public virtual void RecieveAsyncExecutionResponse(AsyncExecutionResponse response) // called by the server side to send responses { Args.ThrowIfNull(response, "result"); Args.ThrowIfNull(response.Request, "result.Request"); string cuid = response.Request.Cuid; Action <AsyncExecutionResponse> action = ((r) => { }); if (_pendingRequests.ContainsKey(cuid)) { if (!_pendingRequests.TryRemove(cuid, out action)) { FireEvent(RemovePendingFailed, new AsyncExecutionResponseEventArgs { Response = response }); } } else { Logger.Warning("Received AsyncExecutionResponse with no corresponding request: {0}", response.PropertiesToString()); } Task.Run(() => { SaveResponseData(response); action(response); }); }
/// <summary> /// The method executed server side /// </summary> /// <param name="request"></param> public virtual void ExecuteRemoteAsync(AsyncExecutionRequest request) // this should be executing server side after encryption has been handled { Task.Run(() => { AsyncCallbackService asyncCallback = _proxyFactory.GetProxy <AsyncCallbackService>(request.RespondToHostName, request.RespondToPort); ExecutionRequest execRequest = new ExecutionRequest(request.ClassName, request.MethodName, "json") { ServiceProvider = ServiceProvider, Context = HttpContext, JsonParams = request.JsonParams }; bool success = execRequest.Execute(); AsyncExecutionResponse response = new AsyncExecutionResponse { Success = success, Request = request, Result = execRequest.Result }; if (!success) { if (execRequest?.Result is ValidationResult validation && validation.Success == false) { response.ValidationFailure = new ValidationFailure { Message = validation.Message, Failures = validation.ValidationFailures }; response.Result = null; } } asyncCallback.RecieveAsyncExecutionResponse(response); }); }
public void InvokeAsync(AsyncExecutionRequest request, Action <AsyncExecutionResponse> responseHandler = null) { responseHandler = responseHandler ?? DefaultResponseHandler; if (!request.UseCachedResponse) { CallExecuteRemoteAsync(request, responseHandler); } else { AsyncExecutionResponseData response = CallbackService.GetCachedResponse(request.GetRequestHash()); if (response != null && new Instant(DateTime.UtcNow).DiffInMinutes(response.Created.Value) <= request.ResponseMaxAgeInMinutes) { AsyncExecutionResponse result = response.CopyAs <AsyncExecutionResponse>(); result.Success = true; result.Request = request; result.ResultJson = response.ResultJson; responseHandler(result); } else { if (response != null) { CallbackService.AsyncCallbackRepository.Delete(response); } CallExecuteRemoteAsync(request, responseHandler); } } }
private void SaveResponseData(AsyncExecutionResponse response, int retryCount = 5) { Args.ThrowIfNull(response, "response"); Args.ThrowIfNull(response.Request, "response.Request"); response.ResultJson = response.Result?.ToJson() ?? ""; string responseHash = response.ResultJson.Sha256(); AsyncExecutionData executionData = AsyncCallbackRepository.OneAsyncExecutionDataWhere(c => c.RequestCuid == response.Request.Cuid); if (executionData == null) { Logger.Warning("Recieved response without corresponding ASYNCEXECUTIONDATA entry: \r\n{0}", response.PropertiesToString()); } else { executionData.ResponseCuid = response.Cuid; executionData.Responded = new Instant(DateTime.UtcNow); executionData.ResponseHash = responseHash; executionData.Success = true; AsyncCallbackRepository.Save(executionData); } AsyncExecutionRequestData requestData = AsyncCallbackRepository.OneAsyncExecutionRequestDataWhere(c => c.Cuid == response.Request.Cuid); if (requestData == null) { Thread.Sleep(100); if (retryCount > 0) { Logger.Warning("Received response without corresponding ASYNCEXECUTIONREQUESTDATA entry (retry count={0}): \r\n{1}", retryCount, response.PropertiesToString()); SaveResponseData(response, --retryCount); } return; } AsyncExecutionResponseData responseData = AsyncCallbackRepository.OneAsyncExecutionResponseDataWhere(c => c.Cuid == response.Cuid); if (responseData != null) { Logger.Warning("Received response that has already been recorded: {0}", response.PropertiesToString()); } else { responseData = new AsyncExecutionResponseData { RequestId = requestData.Id, ResultJson = response.ResultJson, ResponseHash = responseHash, RequestHash = requestData.RequestHash }; AsyncCallbackRepository.Save(responseData); } }
public Task <AsyncExecutionResponse> InvokeAsync(string methodName, params object[] arguments) { return(Task.Run(() => { AutoResetEvent blocker = new AutoResetEvent(false); AsyncExecutionResponse result = null; InvokeAsync((r) => { result = r; blocker.Set(); }, methodName, arguments); blocker.WaitOne(AsyncWaitTimeout); return result; })); }