public async void Stop()
        {
            try
            {
                // Stop the postion report pipelined computation by issuing a cancellation request.
                _environment.TokenSource.Cancel();
                await Task.WhenAll(_pipeline.Completion);
            }
            catch (OperationCanceledException)
            {
                HostLogger.Get <Service>().Debug("The Power Position Tool was cancelled.");
            }
            catch (Exception ex)
            {
                HostLogger.Get <Service>().Error("The Power Position Tool completed with an error.", ex);
            }
            finally
            {
                if (_subscription != null)
                {
                    _subscription.Dispose();
                    _subscription = null;
                }

                if (_environment != null)
                {
                    _environment.TokenSource.Dispose();
                    _environment = null;
                }
            }
        }
Exemple #2
0
 private static ExecutionDataflowBlockOptions ExecutionOptions(Environment env)
 {
     return(new ExecutionDataflowBlockOptions
     {
         CancellationToken = env.TokenSource.Token,
         BoundedCapacity = env.PipelineBufferSize
     });
 }
        public void Start()
        {
            // Build the computation environment.
            _environment = new Environment
            {
                TokenSource         = new CancellationTokenSource(),
                Interval            = TimeSpan.FromMinutes(XmlConvert.ToDouble(ConfigurationManager.AppSettings["schedule-interval-minutes"])),
                PowerService        = new PowerService(),
                GetTrades           = (p, d) => PositionReport.GetTrades(p, d),
                ValidateTrades      = t => PositionReport.ValidateTrades(t),
                BuildPosition       = t => PositionReport.BuildPosition(t),
                BuildReport         = (rs, p) => PositionReport.BuildReport(rs, p),
                WriteReport         = (rs, r) => PositionReport.WriteReport(rs, r),
                PipelineBufferSize  = XmlConvert.ToInt32(ConfigurationManager.AppSettings["pipeline-buffer-size"]),
                ReportSpecification = new ReportSpecification
                {
                    FilenameFormat     = ConfigurationManager.AppSettings["report-filename-format"],
                    FilenameDateFormat = ConfigurationManager.AppSettings["report-filename-date-format"],
                    OutputPath         = ConfigurationManager.AppSettings["report-output-path"],
                    Headers            = ConfigurationManager.AppSettings["report-headers"],
                    LocalTimeFormat    = ConfigurationManager.AppSettings["report-localtime-format"]
                }
            };

            // Create the position report pipelined computation.
            _pipeline = Pipeline.Create(LogManager.GetLogger("Pipeline"), _environment);

            // Run the position report pipelined computation at the specified interval until a cancellation request is received.
            _subscription =
                Observable.Generate(0,
                                    i => !_environment.TokenSource.IsCancellationRequested,
                                    i => i + 1,
                                    i => i,
                                    i => i == 0 ? TimeSpan.Zero : _environment.Interval)
                .Timestamp()
                .Select(x => x.Timestamp)
                .Subscribe(_pipeline.AsObserver());
        }
Exemple #4
0
        public static Pipeline Create(ILog log, Environment env)
        {
            var linkOptions = new DataflowLinkOptions {
                PropagateCompletion = true
            };

            var tradesBlock = new TransformBlock <DateTimeOffset, IEither <PowerTrades, Error> >(date =>
            {
                var message = string.Format("getting trades for {0}", date);
                try
                {
                    log.Debug(message);
                    return(Either.Left <PowerTrades, Error>(env.GetTrades(env.PowerService, date)));
                }
                catch (Exception e)
                {
                    log.Error(message, e);
                    return(Either.Right <PowerTrades, Error>(new Error {
                        Context = message, Exception = e
                    }));
                }
            }, ExecutionOptions(env));

            var validationBlock = new TransformBlock <IEither <PowerTrades, Error>, IEither <PowerTrades, Error> >(trades =>
            {
                var message = trades.Case(ts => string.Format("validating trades for {0}", ts.Day), e => string.Format("skip validating trades due to error {0}", e.Context));
                try
                {
                    log.Debug(message);
                    return(trades.Case(ts => Either.Left <PowerTrades, Error>(env.ValidateTrades(ts)), Either.Right <PowerTrades, Error>));
                }
                catch (Exception e)
                {
                    log.Error(message, e);
                    return(Either.Right <PowerTrades, Error>(new Error {
                        Context = message, Exception = e
                    }));
                }
            }, ExecutionOptions(env));

            var positionBlock = new TransformBlock <IEither <PowerTrades, Error>, IEither <Position, Error> >(trades =>
            {
                var message = trades.Case(ts => string.Format("building position for {0}", ts.Day), e => string.Format("skip building position due to error {0}", e.Context));
                try
                {
                    log.Debug(message);
                    return(trades.Case(ts => Either.Left <Position, Error>(env.BuildPosition(ts)), Either.Right <Position, Error>));
                }
                catch (Exception e)
                {
                    log.Error(message, e);
                    return(Either.Right <Position, Error>(new Error {
                        Context = message, Exception = e
                    }));
                }
            }, ExecutionOptions(env));

            var reportBlock = new TransformBlock <IEither <Position, Error>, IEither <Report, Error> >(position =>
            {
                var message = position.Case(p => string.Format("building report for {0}", p.Day), e => string.Format("skip building report due to error {0}", e.Context));
                try
                {
                    log.Debug(message);
                    return(position.Case(p => Either.Left <Report, Error>(env.BuildReport(env.ReportSpecification, p)), Either.Right <Report, Error>));
                }
                catch (Exception e)
                {
                    log.Error(message, e);
                    return(Either.Right <Report, Error>(new Error {
                        Context = message, Exception = e
                    }));
                }
            }, ExecutionOptions(env));

            var writeBlock = new ActionBlock <IEither <Report, Error> >(report =>
            {
                var message = report.Case(r => string.Format("writing report for {0}", r.Day), e => string.Format("skip writing report due to error {0}", e.Context));
                try
                {
                    log.Debug(message);
                    report.Case(p => env.WriteReport(env.ReportSpecification, p), e => {});
                }
                catch (Exception e)
                {
                    log.Error(message, e);
                }
            }, ExecutionOptions(env));

            tradesBlock.LinkTo(validationBlock, linkOptions);
            validationBlock.LinkTo(positionBlock, linkOptions);
            positionBlock.LinkTo(reportBlock, linkOptions);
            reportBlock.LinkTo(writeBlock, linkOptions);

            tradesBlock.Completion.ContinueWith(t => validationBlock.Completion);
            validationBlock.Completion.ContinueWith(t => positionBlock.Completion);
            positionBlock.Completion.ContinueWith(t => reportBlock.Completion);
            reportBlock.Completion.ContinueWith(t => writeBlock.Completion);

            return(new Pipeline
            {
                StartBlock = tradesBlock,
                EndBlock = writeBlock
            });
        }