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; } } }
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()); }
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 }); }