public void TestWorkflowErrorHandling() { using (ILogger logger = new TraceLogger(true)) { IWorkContext context = new WorkContext(logger, null, "UnitTest"); const int routerPort = 9991; using (var router = new GridSeqStep()) { router.Initialise(context); router.EnableGrid(GridLevel.Router, Guid.NewGuid(), routerPort, null); using (var worker = new GridSeqStep()) { worker.Initialise(context); worker.EnableGrid(GridLevel.Worker, Guid.NewGuid(), routerPort, null); // succeeds { WorkflowOutput <GridData2> output = worker.Execute(new GridData1 { S = "1.0" }); Assert.IsNotNull(output.Errors); Assert.AreEqual(0, output.Errors.Length); Assert.AreEqual(1.0, output.Result.D); } // fails in 1st substep { WorkflowOutput <GridData2> output = worker.Execute(new GridData1 { S = "not_a_number" }); Assert.IsNotNull(output.Errors); Assert.AreEqual(1, output.Errors.Length); Assert.AreEqual(typeof(FormatException).FullName, output.Errors[0].FullName); Assert.AreEqual(default, output.Result);
public void OnExecute3MTest() { #region Load the curve ICoreItem item = Engine.Cache.LoadItem <Market>(NameSpace + "." + Aud3M); var baseMarket = (Market)item.Data; NamedValueSet properties = item.AppProps; #endregion #region Do it // Execute WorkflowOutput <HandlerResponse> actual = RunStressGenerator(properties); // Check for thrown errors Assert.IsNotNull(actual); Assert.AreEqual(0, actual.Errors.Length); //Assert.AreEqual(0, CurveEngine._Logger.Logs[LogSeverity.Error].Count); #endregion #region Load the stressed curves back out // Check the stressed curves are as expected IEnumerable <ICoreItem> stressedItems = GetStressedItems("3M"); // ZeroStress var zeroStressItem = stressedItems.Where(a => a.AppProps.GetString("StressName", true) == "ZeroStress").Single(); var zeroStressMarket = (Market)zeroStressItem.Data; // PercentUp1 var pup1StressItem = stressedItems.Where(a => a.AppProps.GetString("StressName", true) == "PercentUp1").Single(); var pup1StressMarket = (Market)pup1StressItem.Data; #endregion #region Check the inputs IEnumerable <decimal> baseInputs = ((YieldCurveValuation)baseMarket.Items1[0]).inputs.assetQuote.Select(a => a.quote[0].value); // Check the zeroStress curve IEnumerable <decimal> zeroStressedInputs = ((YieldCurveValuation)zeroStressMarket.Items1[0]).inputs.assetQuote.Select(a => a.quote[0].value); CollectionAssert.AreEqual(baseInputs.ToList(), zeroStressedInputs.ToList()); // Check the PercentUp1 curve IEnumerable <decimal> pup1StressedInputs = ((YieldCurveValuation)pup1StressMarket.Items1[0]).inputs.assetQuote.Select(a => a.quote[0].value); CollectionAssert.AreNotEqual(baseInputs.ToList(), pup1StressedInputs.ToList()); #endregion #region Check the zero rates IEnumerable <decimal> baseZeroRates = ((YieldCurveValuation)baseMarket.Items1[0]).zeroCurve.rateCurve.point.Select(a => a.mid); // Check the zeroStress curve IEnumerable <decimal> zeroStressedZeroRates = ((YieldCurveValuation)zeroStressMarket.Items1[0]).zeroCurve.rateCurve.point.Select(a => a.mid); CollectionAssert.AreEqual(baseZeroRates.ToList(), zeroStressedZeroRates.ToList()); // Check the PercentUp1 curve IEnumerable <decimal> pup1StressedZeroRates = ((YieldCurveValuation)pup1StressMarket.Items1[0]).zeroCurve.rateCurve.point.Select(a => a.mid); CollectionAssert.AreNotEqual(baseZeroRates.ToList(), pup1StressedZeroRates.ToList()); #endregion }
private void BaseCurveCallback(ICoreItem baseCurveItem) { try { // check for server shutdown if (GetState() != BasicServerState.Running) { return; } // refresh all curves // - update market data // - regenerate curves DateTime dtNow = DateTime.Now; // Curve identifiers var nameSpace = baseCurveItem.AppProps.GetValue <string>(EnvironmentProp.NameSpace, true); var marketName = baseCurveItem.AppProps.GetValue <string>(CurveProp.Market, true); var curveType = baseCurveItem.AppProps.GetValue <string>(CurveProp.PricingStructureType, true); var curveName = baseCurveItem.AppProps.GetValue <string>(CurveProp.CurveName, true); // }); //} var curveGenRequest = new OrdinaryCurveGenRequest { RequestId = Guid.NewGuid().ToString(), RequesterId = new UserIdentity { Name = IntClient.Target.ClientInfo.Name, DisplayName = "Curve Generation Server" }, BaseDate = dtNow.Date, NameSpace = nameSpace, SaveMarketData = false, UseSavedMarketData = true, ForceGenerateEODCurves = false, CurveSelector = new[] { new CurveSelection { NameSpace = nameSpace, MarketName = marketName, CurveType = curveType, CurveName = curveName } } }; IWorkContext context = new WorkContext(Logger, IntClient.Target, "DEV"); using (var workflow = new WFGenerateOrdinaryCurve()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(curveGenRequest); WorkflowHelper.ThrowErrors(output.Errors); } } catch (Exception excp) { Logger.LogDebug("Base curve generation failed with exception: {0}", excp.GetType().Name); Logger.Log(excp); } }
private static HandlerResponse ExecuteCurveStressing(IEnumerable <string> marketNames, IEnumerable <string> curveTypes, IEnumerable <string> curveNames) { // create list of base curve ids to stress var curveSelectors = new List <CurveSelection>(); // hack make sure QR_LIVE AUD reference curve is stressed first { curveSelectors.Add(new CurveSelection { MarketName = CurveConst.QR_LIVE, CurveType = "RateCurve", CurveName = "AUD-BBR-BBSW-3M" }); } curveSelectors.AddRange(from marketName in marketNames from curveType in curveTypes from curveName in curveNames let baseCurveUniqueId = String.Format(UTE.NameSpace + ".Market.{0}.{1}.{2}", marketName, curveType, curveName) let curveItem = Engine.Cache.LoadItem <Market>(baseCurveUniqueId) where curveItem != null select new CurveSelection { MarketName = marketName, CurveType = curveType, CurveName = curveName }); // create and execute workflow var request = new StressedCurveGenRequest { RequestId = Guid.NewGuid().ToString(), RequesterId = new UserIdentity { Name = Engine.Cache.ClientInfo.Name, DisplayName = "Unit Test Agent" }, BaseDate = TestBaseDate, CurveSelector = curveSelectors.ToArray() }; // build list of curve unique ids required var baseCurveUniqueIds = curveSelectors.Select(curveSelector => String.Format(UTE.NameSpace + ".Market.{0}.{1}.{2}", curveSelector.MarketName, curveSelector.CurveType, curveSelector.CurveName)).ToList(); AssertNotModified <Market>(baseCurveUniqueIds); HandlerResponse result; IWorkContext context = new WorkContext(UTE.Logger, Engine.Cache, "UnitTest"); using (var workflow = new WFGenerateStressedCurve()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(request); WorkflowHelper.ThrowErrors(output.Errors); result = output.Result; } AssertNotModified <Market>(baseCurveUniqueIds); return(result); }
private void BaseCurveCallback(ICoreItem baseCurveItem) { try { // check for server shutdown if (GetState() != BasicServerState.Running) { return; } // base curve changed DateTime dtNow = DateTime.Now; //Market baseCurve = (Market)baseCurveItem.Data; var curveType = baseCurveItem.AppProps.GetValue <string>(CurveProp.PricingStructureType, true); var curveName = baseCurveItem.AppProps.GetValue <string>(CurveProp.CurveName, true); var marketName = baseCurveItem.AppProps.GetValue <string>(CurveProp.Market, true); //var marketDate = baseCurveItem.AppProps.GetValue<DateTime?>(CurveProp.MarketDate, null); var nameSpace = baseCurveItem.AppProps.GetValue <string>(EnvironmentProp.NameSpace, true); DateTime curveBaseDate = baseCurveItem.AppProps.GetValue(CurveProp.BaseDate, dtNow.Date); var curveGenRequest = new StressedCurveGenRequest { RequestId = Guid.NewGuid().ToString(), RequesterId = new UserIdentity { Name = IntClient.Target.ClientInfo.Name, DisplayName = "Stress Curve Generation Server" }, BaseDate = curveBaseDate, CurveSelector = new[] { new CurveSelection { NameSpace = nameSpace, MarketName = marketName, MarketDate = null,//marketDate, CurveType = curveType, CurveName = curveName } } }; IWorkContext context = new WorkContext(Logger, IntClient.Target, "DEV"); using (var workflow = new WFGenerateStressedCurve()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(curveGenRequest); WorkflowHelper.ThrowErrors(output.Errors); } } catch (Exception e) { Logger.Log(e); } }
/// <summary> /// /// </summary> /// <param name="request"></param> private static HandlerResponse ExecuteTradeValuation(PortfolioValuationRequest request) { // create and execute workflow HandlerResponse result; IWorkContext context = new WorkContext(UTE.Logger, Engine.Cache, "UnitTest"); using (var workflow = new WFCalculatePortfolioStressValuation()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(request); result = output.Result; WorkflowHelper.ThrowErrors(output.Errors); } return(result); }
public void TestSelfHostedGrid() { using (ILogger logger = new TraceLogger(true)) { IWorkContext context = new WorkContext(logger, null, "UnitTest"); // defines and executes a basic sequential workflow on a private 2-worker grid const int routerPort = 9992; // create nodes using (var router = new GridSeqStep()) using (var worker1 = new GridSeqStep()) using (var worker2 = new GridSeqStep()) using (var client = new GridSeqStep()) { // start nodes router.Initialise(context); router.EnableGrid(GridLevel.Router, Guid.NewGuid(), routerPort, null); worker1.Initialise(context); worker1.EnableGrid(GridLevel.Worker, Guid.NewGuid(), routerPort, null); worker2.Initialise(context); worker2.EnableGrid(GridLevel.Worker, Guid.NewGuid(), routerPort, null); client.Initialise(context); client.EnableGrid(GridLevel.Client, Guid.NewGuid(), routerPort, null); // execute { WorkflowOutput <GridData2> output = client.Execute(new GridData1 { S = "4.0" }); // should return sqrt(1/4.0) = 0.5 Assert.AreEqual(0.5, output.Result.D); Assert.IsNotNull(output.Errors); Assert.AreEqual(0, output.Errors.Length); } // and again { WorkflowOutput <GridData2> output = client.Execute(new GridData1 { S = "16.0" }); // should return sqrt(1/16.0) = 0.25 Assert.AreEqual(0.25, output.Result.D); Assert.IsNotNull(output.Errors); Assert.AreEqual(0, output.Errors.Length); } } } }
public void ProcessItems() { int count = Interlocked.Decrement(ref _queuedCalls); // exit if there are more callbacks following us //if (count % 10000 == 0) _loggerRef.Target.LogDebug("ProcessItems: Queued calls remaining: {0}", count); if (count != 0) { return; } ICoreItem item = null; _queuedItems.Locked(queue => { if (queue.Count > 0) { item = queue.Dequeue(); } }); while (item != null) { var qas = item.Data as QuotedAssetSet; if (qas != null) { // 1. Get the property values that uniquely identify the curves to refresh. // This is the process for the workflow request. Alternatively, a direct build of the curve can occur. // var nameSpace = item.AppProps.GetValue <string>(EnvironmentProp.NameSpace); var market = item.AppProps.GetValue <string>(CurveProp.Market);//For real time use Market and not MarketAndDate var curveType = item.AppProps.GetValue <string>(CurveProp.PricingStructureType); var curveName = item.AppProps.GetValue <string>(CurveProp.CurveName); var configIdentifier = FunctionProp.Configuration + ".PricingStructures." + market + "." + curveType + "." + curveName; var identifier = FunctionProp.Market + "." + market + "." + curveType + "." + curveName; List <ICoreItem> items = null; // 2.Check if the dependent curves should be refreshed // if (chkBoxDependentCurves.Checked) { //Find all the QAS's where the ReferenceCurveName is equal to the curveType.curveName! var requestProperties = new NamedValueSet(); requestProperties.Set(EnvironmentProp.NameSpace, NameSpace); requestProperties.Set(CurveProp.Market, market); requestProperties.Set(EnvironmentProp.Function, FunctionProp.Configuration); requestProperties.Set(CurveProp.ReferenceCurveName, curveType + '.' + curveName); IExpression queryExpr = Expr.BoolAND(requestProperties); _loggerRef.Target.LogDebug("Dependent curve property request set at {0}", DateTime.Now.ToLongTimeString()); items = _cache.LoadItems <Market>(queryExpr); } // 3. If the build is a local build then use the curve engine. // if (!chkBoxWorkflow.Checked) { _loggerRef.Target.LogDebug("Request to build base curve {0} locally at : {1}", identifier, DateTime.Now.ToLongTimeString()); var curve = CurveEngine.RefreshPricingStructureFromConfiguration(_loggerRef.Target, _cache, nameSpace, configIdentifier, identifier, qas, DateTime.Now, DateTime.Now); _loggerRef.Target.LogDebug("Built the base curve {0} locally at : {1}", curve, DateTime.Now.ToLongTimeString()); if (items != null) { foreach (var dataItem in items) { var spreadCurve = dataItem.Data as Market; if (spreadCurve == null) { continue; } //var bootstrap = dataItem.AppProps.GetValue<bool>(CurveProp.BootStrap, false); //if (!bootstrap) { dataItem.AppProps.Set(CurveProp.BootStrap, true); } try { var curveId = spreadCurve.id; if (String.IsNullOrEmpty(curveId)) { curveId = spreadCurve.Items[0].id; //use yieldCurve.id, CurveGen 1.X compatible } dataItem.AppProps.Set(CurveProp.BaseDate, DateTime.Now); dataItem.AppProps.Set(CurveProp.BuildDateTime, DateTime.Now); var marketData = new Pair <PricingStructure, PricingStructureValuation>(spreadCurve.Items[0], spreadCurve.Items1[0]); var ps = PricingStructureFactory.Create(_loggerRef.Target, _cache, nameSpace, null, null, marketData, dataItem.AppProps); if (ps != null) { CurveEngine.SaveCurve(_cache, nameSpace, ps); } _loggerRef.Target.LogDebug("Built the spread curve {0} locally at : {1}", curveId, DateTime.Now.ToLongTimeString()); } catch (Exception e) { _loggerRef.Target.LogDebug(e.ToString()); } } } } else { // 4. Set the parameters for the work request. // var curveGenRequest = new OrdinaryCurveGenRequest { NameSpace = nameSpace, BaseDate = DateTime.Now, RequestId = Guid.NewGuid().ToString(), RequesterId = new UserIdentity { Name = _cache.ClientInfo.Name, DisplayName = _cache.ClientInfo.UserFullName //Name = _clientRef.Target.ClientInfo.Name, //DisplayName = _clientRef.Target.ClientInfo.UserFullName }, UseSavedMarketData = true, ForceGenerateEODCurves = true }; // 5. Set the base curve in the curve selection for the work request. // var curveSelector = new List <CurveSelection> { new CurveSelection { NameSpace = nameSpace, MarketName = market, CurveType = curveType, CurveName = curveName } }; // 6.Include all other dependent curvenames i.e. spread curves. // if (items != null) { curveSelector.AddRange(from childCurve in items let spreadCurveType = childCurve.AppProps.GetValue <string>( CurveProp.PricingStructureType) let spreadCurveName = childCurve.AppProps.GetValue <string>(CurveProp.CurveName) select new CurveSelection { NameSpace = nameSpace, MarketName = market, CurveType = spreadCurveType, CurveName = spreadCurveName }); } curveGenRequest.CurveSelector = curveSelector.ToArray(); // 7. Set the actual work request. // IWorkContext context = new WorkContext(_loggerRef.Target, _cache, "DEV"); //IWorkContext context = new WorkContext(_loggerRef.Target, _clientRef.Target, "DEV"); _loggerRef.Target.LogDebug("WorkContext set at {0}", DateTime.Now.ToLongTimeString()); using (var workflow = new WFGenerateOrdinaryCurve()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(curveGenRequest); WorkflowHelper.ThrowErrors(output.Errors); foreach (var error in output.Errors) { _loggerRef.Target.LogInfo("WorkFlow error: {0} at {1}", error.Message, DateTime.Now.ToLongTimeString()); } } _loggerRef.Target.LogDebug("WorkFlow executed at {0}", DateTime.Now.ToLongTimeString()); //item = null; //_queuedItems.Locked(queue => // { // if (queue.Count > 0) // item = queue.Dequeue(); // }); } } } }
private void DequeueWorkerRequests(object notUsed) { // throttle callbacks to once per timer period DateTime dtNow = DateTime.Now; if ((dtNow - _lastManagedAt) < _requestManagerPeriod) { return; } _lastManagedAt = dtNow; try { // processing algorithm // - find oldest unprocessed (status==received) request and process it bool workToDo = true; while (workToDo && (GetState() == BasicServerState.Running)) { workToDo = false; InternalTradeRevalRequest activeRequest = null; DateTimeOffset oldestRequestCreated = DateTimeOffset.MaxValue; _outstandingRequests.Locked(requests => { foreach (InternalTradeRevalRequest request in requests.Values) { if ((request.LatestResult.Status == RequestStatusEnum.Received) && (request.Created < oldestRequestCreated) && (request.Request != null)) { activeRequest = request; oldestRequestCreated = request.Created; } } if (activeRequest != null) { // we have found a request to process workToDo = true; } }); if (activeRequest != null) { // process request TradeValuationRequest request = activeRequest.Request; try { // run the valuation workflow using (var workflow = new WFCalculateTradeValuation()) { workflow.Initialise(_workContext); activeRequest.Workflow = workflow; _activeWorkflow = workflow; try { WorkflowOutput <HandlerResponse> output = workflow.Execute(request); WorkflowHelper.LogErrors(Logger, output.Errors); } finally { activeRequest.Workflow = null; _activeWorkflow = null; } } } catch (Exception innerExcp) { Logger.Log(innerExcp); // publish 'faulted' result var response = new HandlerResponse { RequestId = request.RequestId, RequesterId = request.RequesterId, //RequesterData = request.TradeId, Status = RequestStatusEnum.Faulted, FaultDetail = new ExceptionDetail(innerExcp) }; _workContext.Cache.SaveObject(response); } } } // while there is work to do } catch (Exception outerExcp) { // deserialisation error? Logger.Log(outerExcp); } }
private void DequeueWorkerRequests(object notUsed) { // exit if more requests following if (Interlocked.Decrement(ref _WorkerRequests) > 0) { return; } // throttle callbacks to once per timer period DateTime dtNow = DateTime.Now; if ((dtNow - _LastManagedAt) < RequestManagerPeriod) { return; } _LastManagedAt = dtNow; try { // processing algorithm // - find oldest unprocessed (status==received) request and process it bool workToDo = true; while (workToDo) { workToDo = false; InternalRequest oldestUnstartedRequest = null; DateTimeOffset oldestRequestCreated = DateTimeOffset.MaxValue; _OutstandingRequests.Locked((requests) => { foreach (InternalRequest request in requests.Values) { if ((request.LatestResult.Status == RequestStatusEnum.Received) && (request.Created < oldestRequestCreated)) { oldestUnstartedRequest = request; oldestRequestCreated = request.Created; } } if (oldestUnstartedRequest != null) { // we have found a request to process workToDo = true; } }); if (oldestUnstartedRequest != null) { // process request PortfolioValuationRequest request = oldestUnstartedRequest.Request; try { // run the valuation worflow WorkflowOutput <ServerRequestStatus> output = _Workflow.Execute(request); bool failed = WorkflowHelper.LogErrors(Logger, output.Errors); } catch (Exception innerExcp) { Logger.Log(innerExcp); // publish 'faulted' result (new ServerRequestStatus() { RequestId = request.RequestId, RequesterId = request.RequesterId, RequesterData = request.PortfolioId, Status = RequestStatusEnum.Faulted, FaultDetail = new ExceptionDetail(innerExcp), }).Publish(_WorkContext.Logger, _WorkContext.Cache, TimeSpan.FromDays(1)); } } } // while there is work to do } catch (Exception outerExcp) { // deserialisation error? Logger.Log(outerExcp); } }
public void ProcessItems() { int count = Interlocked.Decrement(ref _queuedCalls); // exit if there are more callbacks following us if (count % 10000 == 0) { _loggerRef.Target.LogDebug("ProcessItems: Queued calls remaining: {0}", count); } if (count != 0) { return; } ICoreItem item = null; _queuedItems.Locked(queue => { if (queue.Count > 0) { item = queue.Dequeue(); } }); while (item != null) { if (item.Data is QuotedAssetSet) { var nameSpace = item.AppProps.GetValue <string>(EnvironmentProp.NameSpace); var marketName = item.AppProps.GetValue <string>(CurveProp.MarketAndDate); var curveType = item.AppProps.GetValue <string>(CurveProp.PricingStructureType); var curveName = item.AppProps.GetValue <string>(CurveProp.CurveName); var curveGenRequest = new OrdinaryCurveGenRequest { NameSpace = nameSpace, BaseDate = DateTime.Now, RequestId = Guid.NewGuid().ToString(), RequesterId = new UserIdentity { Name = _clientRef.Target.ClientInfo.Name, DisplayName = _clientRef.Target.ClientInfo.UserFullName }, UseSavedMarketData = true, ForceGenerateEODCurves = true, CurveSelector = new[] { new CurveSelection { NameSpace = nameSpace, MarketName = marketName, CurveType = curveType, CurveName = curveName } } }; IWorkContext context = new WorkContext(_loggerRef.Target, _clientRef.Target, "DEV"); using (var workflow = new WFGenerateOrdinaryCurve()) { workflow.Initialise(context); WorkflowOutput <HandlerResponse> output = workflow.Execute(curveGenRequest); WorkflowHelper.ThrowErrors(output.Errors); } item = null; _queuedItems.Locked(queue => { if (queue.Count > 0) { item = queue.Dequeue(); } }); } } }
public async Task <WorkflowOutput> GetWorkflowOutput(string instanceId, WorkflowCore.Models.Workflow workFlow, object dataObject, string publishedEvent = null) { var pointer = new WorkflowCore.Models.ExecutionPointer(); var workflowStatus = WorkflowCore.Models.WorkflowStatus.Running; string eventName = string.Empty; var expectedInputs = new List <ExpectedInput>(); var inputs = new List <string>(); var WorkflowInstance = await _workflowStore.GetWorkflowInstance(instanceId); if (WorkflowInstance != null) { workflowStatus = WorkflowInstance.Status; pointer = WorkflowInstance.ExecutionPointers.Last(); while ((pointer.Status == WorkflowCore.Models.PointerStatus.Pending || pointer.Status == WorkflowCore.Models.PointerStatus.Running) || (pointer.Status == WorkflowCore.Models.PointerStatus.Complete && workflowStatus == WorkflowCore.Models.WorkflowStatus.Running) || (pointer.Status == WorkflowCore.Models.PointerStatus.WaitingForEvent && pointer.EventName == publishedEvent)) { WorkflowInstance = await _workflowStore.GetWorkflowInstance(instanceId); workflowStatus = WorkflowInstance.Status; pointer = WorkflowInstance.ExecutionPointers.Last(); } } if ((pointer.Status == WorkflowCore.Models.PointerStatus.WaitingForEvent) && (!pointer.EventPublished)) { eventName = pointer.EventName; var step = workFlow.Definition.Steps.Where(s => s.Name == pointer.StepName).FirstOrDefault(); if (step.Outputs != null) { var outputs = step.Outputs; foreach (var item in outputs) { inputs.Add(item.Key); } } } foreach (var input in inputs) { var type = dataObject.GetType().GetProperty(input); if (type != null) { var expectedInput = new ExpectedInput { Name = input, DataType = type.PropertyType.Name }; expectedInputs.Add(expectedInput); } } WorkflowOutput output = new WorkflowOutput { InstanceId = instanceId, WorkflowStatus = workflowStatus.ToString(), LastStepName = pointer.StepName, StepStatus = pointer.Status.ToString(), EventName = eventName, ExpectedInputs = expectedInputs }; return(output); }