private async Task <CallOpenApiWorkerMethodResponse> CallResult(RemoteJsOpenApiDocs remoteApi, CallOpenApiWorkerMethod requestModel) { var responseRecord = await HttpClient.PostAsync(remoteApi.Description.HostUrl, remoteApi.Description.Name, HttpPaths.HandleCall, requestModel); ExecutionContext.ExecutionLogs.Add(new JsExecutionLog { EventIdName = EventIds.CallRemoteApi.CallLogged, Message = "Логгирование удаленного запроса", DataJson = ZooSerializer.Serialize(responseRecord) }); try { //Task<RemoteApiResponseRecord> PostAsync<TRequest>(string hostUrl, string hostName, string path, TRequest request) return(responseRecord.GetResult <CallOpenApiWorkerMethodResponse>()); } catch (Exception ex) { ExecutionContext.ExecutionLogs.Add(new JsExecutionLog { EventIdName = EventIds.CallRemoteApi.ResponseDeserializationError, Message = "Ошибка при дессериализации", DataJson = ZooSerializer.Serialize(responseRecord) }); return(new CallOpenApiWorkerMethodResponse { IsSucceeded = false, ExcepionData = ExcepionData.Create(ex) }); } }
public async Task Test1() { var serviceCollcetion = new ServiceCollection(); var script = $"var t = api.Call(\"{ProductGroupJsWorker.WorkerName}\"," + " \"AddProductToGroup\", { ProductGroupId: \"d8c8cf9b-1d9b-4199-a85e-615edd64b4d7\", ProductId: 1 });"; script += "\n console.log('Result', t)"; new JsExecutorBuilder(serviceCollcetion) .AddJsWorker(new ProductGroupJsWorker()) .Build(); var srvProvider = serviceCollcetion.BuildServiceProvider(); var executor = srvProvider.GetRequiredService <JsExecutor>(); var result = await executor.RunScriptDetaiiled(script); Assert.IsTrue(result.IsSucceeded); Assert.AreEqual(1, result.ConsoleLogs.Count); var log = result.ConsoleLogs.First(); var json = ZooSerializer.Serialize(ProductGroupJsWorker.AddProductToGroup(null)); Assert.AreEqual(log.SerializedVariables.Last().DataJson, json); }
/// <summary> /// Вызвать внутренний метод сервис /// </summary> /// <param name="workerName">название класса рабочего который нужно вызвать</param> /// <param name="method">метод который нужно вызвать у данного рабочего</param> /// <param name="methodParams">Параметры метода</param> public string Call(string workerName, string method, params dynamic[] methodParams) { var worker = Components.GetJsWorker(workerName, ExecutionContext); var res = worker.HandleCall(method, ServiceProvider, new JsWorkerMethodCallParameters(methodParams), ExecutionContext, Logger).Result; return ZooSerializer.Serialize(res); }
public T GetParameter <T>() { var param = _parameters[_currentIndex]; _currentIndex++; var json = ZooSerializer.Serialize(param); return(ZooSerializer.Deserialize <T>(json)); }
/// <summary> /// Вызвать внешний сервис, определенный через Js /// </summary> /// <param name="remoteName"></param> /// <param name="workerName"></param> /// <param name="methodName"></param> /// <param name="methodParams"></param> /// <returns></returns> public async Task <string> CallRemoteWorkerMethod(string remoteName, string workerName, string methodName, params dynamic[] methodParams) { if (!RemoteDocs.ContainsKey(remoteName)) { throw WriteLogAndGetException(new JsExecutionLog { EventIdName = EventIds.CallRemoteApi.RemoteApiNotFound, Message = $"В системе нет зарегистрированного внешнего апи с именем '{remoteName}'", DataJson = null }); } var remoteApi = RemoteDocs[remoteName]; var worker = remoteApi.Docs.Workers.FirstOrDefault(x => x.WorkerName == workerName); if (worker == null) { throw WriteLogAndGetException(new JsExecutionLog { EventIdName = EventIds.CallRemoteApi.NoWorkerWithNameFound, Message = $"Во внешнем апи '{remoteName}' не зарегистрирован рабочий класс с именем '{workerName}'", DataJson = null }); } var method = worker.Methods.FirstOrDefault(x => x.MethodName == methodName); if (method == null) { throw new InvalidOperationException($"Во внешнем апи '{remoteName}' в рабочем классе с именем '{workerName}' не обнаружен метож '{methodName}'"); } var requestModel = new CallOpenApiWorkerMethod { WorkerName = workerName, MethodName = methodName, SerializedParameters = methodParams?.Select(ZooSerializer.Serialize).ToArray() ?? Array.Empty <string>() }; var callResult = await CallResult(remoteApi, requestModel); if (!callResult.IsSucceeded) { throw WriteLogAndGetException(new JsExecutionLog { EventIdName = EventIds.CallRemoteApi.CallNotSucceeded, Message = "Ошибка при выполнении удалленного запроса", DataJson = ZooSerializer.Serialize(callResult) }); } return(callResult.ResponseJson); }
/// <inheritdoc /> public Task <HttpResponseRecord> PostAsync <TRequest>(string hostUrl, string hostName, string path, TRequest request) { var json = ZooSerializer.Serialize(request); var url = $"{hostUrl}{path}"; var result = new HttpResponseRecord { HostName = hostName, HostUrl = hostUrl, RequestUrl = url, Request = json, RequestMethod = "POST" }; return(CallInner(result, httpClient => HttpClient.PostAsync(url, new StringContent(json, Encoding.UTF8, "application/json")))); }
private JsSerializedVariable ToJsSerializedVariable(object obj) { if (obj == null) { return(new JsSerializedVariable { DataJson = "null", TypeFullName = null }); } return(new JsSerializedVariable { DataJson = ZooSerializer.Serialize(obj), TypeFullName = obj.GetType().FullName }); }
/// <summary> /// /// </summary> /// <param name="componentName"></param> /// <param name="methodName"></param> /// <param name="methodPayLoad"></param> /// <returns></returns> private async Task<string> CallExternalUnSafe(string componentName, string methodName, object methodPayLoad) { var component = await Components.GetExternalComponent(componentName, ExecutionContext); var uid = $"n{Guid.NewGuid()}".Replace("-", "_"); var payloadJson = ZooSerializer.Serialize(methodPayLoad); var variableScript = $"{uid} = {payloadJson};"; var engine = ExecutionContext.CreateEngine(); var variable = engine.Execute(variableScript).GetValue(uid); var methodExpr = engine.Execute(component.Script).GetValue(methodName); if (methodExpr.Type == Jint.Runtime.Types.Undefined) { throw new Exception($"Метод '{methodName}' не найден в компоненте '{componentName}'"); } var resultJson = ZooSerializer.Serialize(methodExpr.Invoke(variable).ToObject()); ExecutionContext.ExecutionLogs.Add(new JsExecutionLog { EventIdName = EventIds.JsExecutorComponents.CallExternalComponentOnResult, Message = "Завершен вызов внешнего компонента", DataJson = JsonConvert.SerializeObject(new { ComponentName = componentName, MethodName = methodName, PayloadJson = payloadJson, ResultJson = resultJson }) }); return resultJson; }
/// <summary> /// Вызвать метод рабочего класса. /// <para></para> /// Данный метод не возвращает исключений. Его нужно испльзовать как внешюю точку доступа. /// </summary> /// <param name="requestModel"></param> /// <returns></returns> public CallOpenApiWorkerMethodResponse CallWorkerMethod(CallOpenApiWorkerMethod requestModel) { if (requestModel == null) { return(new CallOpenApiWorkerMethodResponse { IsSucceeded = false, ExcepionData = ExcepionData.Create(new Exception("request is null onjcet")) }); } var parameters = new JsWorkerMethodCallParametersFromSerialized(requestModel.SerializedParameters); try { var jsContext = GetContext(); using var scope = ServiceProvider.CreateScope(); var result = Components .GetJsWorker(requestModel.WorkerName, jsContext) .HandleCall(requestModel.MethodName, scope.ServiceProvider, parameters, jsContext, Logger); return(new CallOpenApiWorkerMethodResponse { IsSucceeded = true, ResponseJson = ZooSerializer.Serialize(result.Result) }); } catch (Exception ex) { Logger.LogError(ex, "CallWorkerMethod.Error"); return(new CallOpenApiWorkerMethodResponse { IsSucceeded = false, ExcepionData = ExcepionData.Create(ex) }); } }
public void TestCall(int param1, int param2, double expectedResult) { var services = new ServiceCollection(); new JsExecutorBuilder(services) .AddJsWorker(new CalculatorJsWorker()) .Build(); var srvProvider = services.BuildServiceProvider(); var jsExecutor = srvProvider.GetRequiredService <JsExecutor>(); var result = jsExecutor.CallWorkerMethod(new Models.OpenApi.CallOpenApiWorkerMethod { WorkerName = "Calculator", MethodName = "Divide", SerializedParameters = new string[] { param1.ToString(), param2.ToString() } }); Assert.IsTrue(result.IsSucceeded); var expetedDataResult = ZooSerializer.Serialize(expectedResult); Assert.AreEqual(expetedDataResult, result.ResponseJson); }
/// <summary> /// Вызвать внешний сервис, определенный через Js /// </summary> /// <param name="componentName"></param> /// <param name="methodName"></param> /// <param name="methodPayLoad"></param> /// <returns></returns> public string CallExternal(string componentName, string methodName, object methodPayLoad) { try { var result = CallExternalUnSafe(componentName, methodName, methodPayLoad).GetAwaiter().GetResult(); return result; } catch (Exception ex) { var mes = $"Произошла ошибка при вызове внешнего компонента. Название внешнего компонента = '{componentName}'.\n " + $"Название метода = '{methodName}'.\n"; if (methodPayLoad != null) { mes += $"Параметр метода = {ZooSerializer.Serialize(methodPayLoad)}.\n "; } else { mes += $"Параметр метода = [Метод был вызван без параметра].\n "; } throw new Exception(mes + ex.Message); } }