private void WaitActionLockPendingCompletations(ref SocketRequest request, ref IController controller, ref string actionName) { if (!ActionLocker.ActionHasLock(controller, actionName)) { return; } SingleThreaded actionLock = method.GetCustomAttribute <SingleThreaded>(); if (actionLock == null) { return; } for (int i = 0; i < actionLock.WaitingAttempts; i++) { if (ActionLocker.ActionHasLock(controller, actionName)) { if ((i + 1) >= actionLock.WaitingAttempts) { throw new LockedActionException("The action does not allow simultaneous access and the maximum number of waiting attempts has been exceeded. Try to access the resource again later."); } Thread.Sleep(actionLock.WaitingInterval); } else { return; } } }
public override object DoInBackGround(int p) { SocketRequest request = null; try { request = GetRequestSocket(); if (request == null) { return(null); } if (HasRequestErros(ref request)) { return(null); } controller = request.Controller; method = controller.GetType().GetMethod(request.Action); ValidateActionMethod(); controllerName = controller.GetType().Name; actionName = method.Name; WaitActionLockPendingCompletations(ref request, ref controller, ref actionName); if (method.GetCustomAttribute <SingleThreaded>() != null) { ActionLocker.AddLock(controller, actionName); } ResolveActionParameters(ref request); if (!ResolveInterceptors(ref request)) { return(null); } ParameterInfo[] methodParameters = method.GetParameters(); object[] parameterValues = new object[methodParameters.Length]; int methodParameterCount = methodParameters .Where(pr => request.Parameters.Any(rp => rp.Name.Equals(pr.Name))) .Count(); int parameterIndex = 0; int valueIndex = 0; foreach (RequestParameter rp in request.Parameters) { ParameterInfo parameterInfo = methodParameters.FirstOrDefault(mp => mp.Name.Equals(rp.Name)); if (parameterInfo == null) { parameterIndex += 1; continue; } parameterValues[valueIndex] = request.Parameters[parameterIndex].Value; parameterIndex += 1; valueIndex += 1; } ActionResult result = null; Stopwatch w = new Stopwatch(); w.Start(); if (method.ReturnType == null) { //void action method.Invoke(controller, parameterValues); result = ActionResult.Json(new OperationResult(null, 600, "")); } else if (method.ReturnType == typeof(ActionResult)) //ActionResult action { result = (ActionResult)method.Invoke(controller, parameterValues); } else { //user-defined object Action object returnObj = method.Invoke(controller, parameterValues); result = ActionResult.Json(new OperationResult(returnObj, 600, "")); } w.Stop(); if (telemetry != null) { telemetry.Collect(new ActionExecutionTime(controllerName, actionName, w.ElapsedMilliseconds)); } logger.WriteLog($"Request completed: {controllerName}/{actionName}; ~{w.ElapsedMilliseconds}ms"); if (w.ElapsedMilliseconds > 10000) { ServerAlertManager.CreateAlert(new ServerAlert(request.Controller.GetType().Name, request.Action, $"The action it is taking considerable time to execute ({w.ElapsedMilliseconds} ms). Review your code to improve performance.'")); } ActionLocker.ReleaseLock(controller, method.Name); request.ProcessResponse(result, clientSocket, requestBody.InTo); return(result); } catch (LockedActionException lockedEx) { ProcessErrorResponse(lockedEx, ref request); return(null); } catch (Exception ex) { if (method != null && controller != null) { ActionLocker.ReleaseLock(controller, actionName); } ProcessErrorResponse(ex, ref request); return(null); } }