20
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Diagnostics;
|
|
4 using System.Linq;
|
|
5 using System.Threading.Tasks;
|
|
6 using NLog;
|
|
7 using Stocks.Common;
|
|
8 using Stocks.Common.Core;
|
|
9 using Stocks.Common.Events;
|
|
10 using Stocks.Common.Models;
|
|
11
|
|
12 namespace Stocks.Service
|
|
13 {
|
|
14 public class StocksService : IStocksService
|
|
15 {
|
|
16 private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
|
17
|
|
18 private IList<Company> _companies;
|
|
19 private readonly IConfigurationService _configurationService;
|
|
20 private List<Price> _currentPrices;
|
|
21 private string _serviceUrl;
|
|
22 private readonly IWebClientShim _webClient;
|
|
23
|
|
24 public bool IsRunning { get; private set; }
|
|
25 public SummaryStats Stats { get; private set; }
|
|
26
|
|
27 public StocksService(
|
|
28 IConfigurationService configurationService,
|
|
29 IWebClientShim webClientShim)
|
|
30 {
|
|
31 new AssemblyInit();
|
|
32
|
|
33 _webClient = webClientShim;
|
|
34 _configurationService = configurationService;
|
|
35 Stats = new SummaryStats();
|
|
36
|
|
37 GetCompanyList();
|
|
38 }
|
|
39
|
|
40 private void GetCompanyList()
|
|
41 {
|
|
42 _companies = _configurationService.GetCompanies();
|
|
43
|
|
44 var symbolsCsv = _companies.Select(
|
|
45 c => c.Symbol).Aggregate((c, d) => c + "," + d);
|
|
46
|
|
47 _serviceUrl = _configurationService.GetServiceUrl(symbolsCsv);
|
|
48 }
|
|
49
|
|
50 public IList<Price> GetFullCurrentPrices()
|
|
51 {
|
|
52 return _companies.Select(company => new Price(company.Symbol, 0, 0)).ToList();
|
|
53 }
|
|
54
|
|
55 public event PriceChangedEventHandler PriceChanged;
|
|
56 public delegate void PriceChangedEventHandler(object sender, PriceChangedEventArgs e);
|
|
57 protected virtual void OnPriceChanged(Price price)
|
|
58 {
|
|
59 Stats.PriceChangeEvents++;
|
|
60
|
|
61 if (PriceChanged != null)
|
|
62 PriceChanged(this, new PriceChangedEventArgs() { Price = price });
|
|
63 }
|
|
64
|
|
65 public void Start()
|
|
66 {
|
|
67 PrepareForServiceStarting();
|
|
68 Task.Factory.StartNew(DownloadPrices);
|
|
69 }
|
|
70
|
|
71 public void Stop()
|
|
72 {
|
|
73 IsRunning = false;
|
|
74 Log.Debug("StockService stopped");
|
|
75 }
|
|
76
|
|
77 private void PrepareForServiceStarting()
|
|
78 {
|
|
79 Log.Debug("StockService starting");
|
|
80 IsRunning = true;
|
|
81 Stats.Reset();
|
|
82 _currentPrices = new List<Price>(_companies.Count);
|
|
83 }
|
|
84
|
|
85 private void DownloadPrices()
|
|
86 {
|
|
87 try
|
|
88 {
|
|
89 while (IsRunning)
|
|
90 {
|
|
91 Stopwatch timeToDownload;
|
|
92 var webResponse = TimedDelegates.Execute(
|
|
93 _webClient.DownloadString,
|
|
94 _serviceUrl,
|
|
95 out timeToDownload);
|
|
96
|
|
97 PopulatePricesFromWebResponse(webResponse);
|
|
98 UpdateStats(timeToDownload, webResponse);
|
|
99 }
|
|
100 }
|
|
101 catch (Exception e)
|
|
102 {
|
|
103 Log.Error("Exception during DownloadPrices()");
|
|
104 Log.Error("Stack Trace {0}: /r/nException Message: {1}", e.StackTrace, e.Message);
|
|
105 this.Stop();
|
|
106 }
|
|
107 }
|
|
108
|
|
109 private void PopulatePricesFromWebResponse(string webResponse)
|
|
110 {
|
|
111 var webPrices = webResponse.Split(
|
|
112 new[] { "\n", "\r\n" },
|
|
113 StringSplitOptions.RemoveEmptyEntries);
|
|
114
|
|
115 foreach (var webPriceData in webPrices)
|
|
116 {
|
|
117 var webPrice = Factory.CreatePrice(webPriceData);
|
|
118 var localPrice = _currentPrices.Find(x => x.Symbol == webPrice.Symbol);
|
|
119
|
|
120 if (localPrice == null)
|
|
121 {
|
|
122 _currentPrices.Add(new Price(webPrice.Symbol, webPrice.CurrentPrice, webPrice.PreviousPrice));
|
|
123 continue;
|
|
124 }
|
|
125
|
|
126 if (!localPrice.Equals(webPrice))
|
|
127 UpdateLocalPrice(webPrice, localPrice);
|
|
128 }
|
|
129 }
|
|
130
|
|
131 private void UpdateLocalPrice(Price webPrice, Price localPrice)
|
|
132 {
|
|
133 localPrice.PreviousPrice = localPrice.CurrentPrice;
|
|
134 localPrice.CurrentPrice = webPrice.CurrentPrice;
|
|
135 OnPriceChanged(localPrice);
|
|
136 }
|
|
137
|
|
138 private void UpdateStats(Stopwatch timeToDownload, string webResponse)
|
|
139 {
|
|
140 Stats.LastWebRequest.Duration = (int)timeToDownload.ElapsedMilliseconds;
|
|
141 Stats.LastWebRequest.PricesDownloaded = _currentPrices.Count;
|
|
142 Stats.LastWebRequest.Response = webResponse;
|
|
143 Stats.LastWebRequest.Request = _serviceUrl;
|
|
144 Stats.LastWebRequest.SymbolCount = _companies.Count;
|
|
145 Stats.NumberOfRequests++;
|
|
146 Log.Trace(Stats);
|
|
147 }
|
|
148 }
|
|
149 } |