/// <summary> /// The disassemble. /// </summary> /// <param name="operationContext"> /// The operation context. /// </param> /// <param name="execution"> /// The execution. /// </param> /// <param name="messageId"> /// The message id. /// </param> /// <param name="messageBody"> /// The message body. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> public async Task Disassemble( ISystemProcessOperationContext operationContext, ScheduledExecution execution, string messageId, string messageBody) { try { if (execution?.Rules == null || !execution.Rules.Any()) { this.logger.LogError( $"deserialised message {messageId} but could not find any rules on the scheduled execution"); operationContext.EndEventWithError( $"deserialised message {messageId} but could not find any rules on the scheduled execution"); return; } var scheduleRule = this.ValidateScheduleRule(execution); if (!scheduleRule) { operationContext.EndEventWithError( "did not validate the scheduled execution passed through. Check error logs."); return; } var parameters = await this.ruleParameterApiRepository.GetAsync(); var ruleCtx = this.BuildRuleContext(operationContext, execution); await this.ScheduleRule(execution, parameters, ruleCtx); ruleCtx.EndEvent().EndEvent(); this.logger.LogInformation( $"read message {messageId} with body {messageBody} for operation {operationContext.Id} has completed"); } catch (Exception e) { this.logger.LogError( $"execute non distributed message encountered a top level exception. {e.Message} {e.InnerException?.Message}", e); } }
/// <summary> /// The set failed back test due to future execution. /// </summary> /// <param name="operationContext"> /// The operation context. /// </param> /// <param name="execution"> /// The execution. /// </param> /// <param name="cancellableRule"> /// The cancellable rule. /// </param> /// <param name="ids"> /// The ids. /// </param> private void SetFailedBackTestDueToFutureExecution( ISystemProcessOperationContext operationContext, ScheduledExecution execution, CancellableRule cancellableRule, IReadOnlyCollection <string> ids) { operationContext.EndEventWithError("Set back test to end some time in the future"); this.logger.LogInformation($"End of universe execution for {execution.CorrelationId} - back test had illegal future dates"); this.ruleCancellation.Unsubscribe(cancellableRule); this.logger.LogInformation("calling rule run update message send"); this.RuleRunUpdateMessageSend(execution, ids); this.logger.LogInformation("completed rule run update message send"); }
/// <summary> /// The set rule cancelled state. /// </summary> /// <param name="operationContext"> /// The operation context. /// </param> /// <param name="execution"> /// The execution. /// </param> /// <param name="cancellableRule"> /// The cancellable rule. /// </param> /// <param name="ids"> /// The ids. /// </param> private void SetRuleCancelledState( ISystemProcessOperationContext operationContext, ScheduledExecution execution, CancellableRule cancellableRule, IReadOnlyCollection <string> ids) { operationContext.EndEventWithError("USER CANCELLED RUN"); this.logger.LogInformation($"END OF UNIVERSE EXECUTION FOR {execution.CorrelationId} - USER CANCELLED RUN"); this.ruleCancellation.Unsubscribe(cancellableRule); this.logger.LogInformation("calling rule run update message send"); this.RuleRunUpdateMessageSend(execution, ids); this.logger.LogInformation("completed rule run update message send"); }
/// <summary> /// The execute analysis engine /// This is the top level function for trade analysis /// within the surveillance engine /// </summary> /// <param name="execution"> /// The execution. /// </param> /// <param name="operationContext"> /// The operation context. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> public async Task Execute(ScheduledExecution execution, ISystemProcessOperationContext operationContext) { if (execution?.Rules == null || !execution.Rules.Any()) { this.logger.LogError("was executing a schedule that did not specify any rules to run"); operationContext.EndEventWithError("was executing a schedule that did not specify any rules to run"); return; } this.logger.LogInformation($"START OF UNIVERSE EXECUTION FOR {execution.CorrelationId}"); this.LogExecutionParameters(execution, operationContext); var cts = new CancellationTokenSource(); var cancellableRule = new CancellableRule(execution, cts); this.ruleCancellation.Subscribe(cancellableRule); var ruleParameters = await this.ruleParameterService.RuleParameters(execution); execution.LeadingTimespan = this.timespanService.LeadingTimespan(ruleParameters); execution.TrailingTimespan = this.timespanService.TrailingTimeSpan(ruleParameters); var player = this.universePlayerFactory.Build(cts.Token); this.universeCompletionLogger.InitiateTimeLogger(execution); player.Subscribe(this.universeCompletionLogger); var dataRequestSubscriber = this.dataRequestSubscriberFactory.Build(operationContext); var universeAlertSubscriber = this.alertStreamSubscriberFactory.Build(operationContext.Id, execution.IsBackTest); var judgementService = this.judgementServiceFactory.Build(); var alertStream = this.alertStreamFactory.Build(); alertStream.Subscribe(universeAlertSubscriber); // internally subscribes rules to the player var subscribedRules = await this.ruleSubscriber.SubscribeRules( execution, player, alertStream, dataRequestSubscriber, judgementService, operationContext, ruleParameters); player.Subscribe(dataRequestSubscriber); // ensure this is registered after the rules so it will evaluate eschaton afterwards this.RuleRunUpdateMessageSend(execution, subscribedRules.RuleIds); if (this.GuardForBackTestIntoFutureExecution(execution)) { this.SetFailedBackTestDueToFutureExecution(operationContext, execution, cancellableRule, subscribedRules.RuleIds); return; } if (execution.AdjustedTimeSeriesTermination.Date >= DateTime.UtcNow.Date) { await this.reschedulerService.RescheduleFutureExecution(execution); } var universeAnalyticsSubscriber = this.analyticsSubscriber.Build(operationContext.Id); player.Subscribe(universeAnalyticsSubscriber); this.logger.LogInformation("START PLAYING UNIVERSE TO SUBSCRIBERS"); var dataConstraints = subscribedRules?.Rules?.Select(_ => _.DataConstraints())?.ToList(); var dataManifestInterpreter = await this.dataManifestBuilder.Build(execution, dataConstraints, operationContext); var lazyUniverse = this.universeFactory.Build(execution, operationContext, dataManifestInterpreter); player.Play(lazyUniverse); this.logger.LogInformation("STOPPED PLAYING UNIVERSE TO SUBSCRIBERS"); if (cts.IsCancellationRequested) { this.SetRuleCancelledState(operationContext, execution, cancellableRule, subscribedRules.RuleIds); return; } // post rule execution analysis universeAlertSubscriber.Flush(); await this.ruleAnalyticsRepository.Create(universeAnalyticsSubscriber.Analytics); await this.alertsRepository.Create(universeAlertSubscriber.Analytics); dataRequestSubscriber.DispatchIfSubmitRequest(); judgementService.PassJudgement(); this.SetOperationContextEndState(dataRequestSubscriber, operationContext); this.logger.LogInformation("calling rule run update message send"); this.RuleRunUpdateMessageSend(execution, subscribedRules.RuleIds); this.logger.LogInformation("completed rule run update message send"); this.ruleCancellation.Unsubscribe(cancellableRule); this.logger.LogInformation($"END OF UNIVERSE EXECUTION FOR {execution.CorrelationId}"); }