view Stocks/Stocks.Service/StocksService.cs @ 0:e5d46bb6cdb0

Initial commit
author adminSH stevenhollidge@hotmail.com
date Mon, 20 Feb 2012 13:52:35 +0700
parents
children 29ed98d659e9
line wrap: on
line source

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using NLog;
using Stocks.Common;
using Stocks.Common.Models;
using Stocks.Common.Events;

namespace Stocks.Service
{ 
  public class StocksService : IStocksService
  {
    private static readonly Logger Log = LogManager.GetCurrentClassLogger();

    private IList<Company> _companies;
    private IConfigurationService _configurationService;
    private List<Price> _currentPrices;
    private string _serviceUrl;
    private WebClient _webClient;

    public bool IsActive { get; private set; }
    public SummaryStats Stats { get; private set; }

    public StocksService(IConfigurationService configurationService)
    {
      new AssemblyInit();

      _webClient = new WebClient();
      _configurationService = configurationService;
      _companies = configurationService.GetCompanies();

      string symbolsCsv = _companies.Select(
        c => c.Symbol).Aggregate((c, d) => c + "," + d);
      _serviceUrl = _configurationService.GetServiceUrl(symbolsCsv);
      
      Stats = new SummaryStats();
    }

    public delegate void PriceChangedEventHandler(object sender, PriceChangedEventArgs e);
    public event PriceChangedEventHandler PriceChanged;
    protected virtual void RaisePriceChanged(Price price)
    {
      Stats.PriceChangeEvents++;

      if (PriceChanged != null)
        PriceChanged(this, new PriceChangedEventArgs() { Price = price });
    }

    public void Start()
    {
      PrepareForServiceStarting();
      Task.Factory.StartNew(() => DownloadPrices());
    }

    public void Stop()
    {
      IsActive = false;
      Log.Debug("StockService stopped");
    }

    private void PrepareForServiceStarting()
    {
      Log.Debug("StockService starting");
      IsActive = true;
      Stats.Reset();
      _currentPrices = new List<Price>(_companies.Count);
    }

    private void DownloadPrices()
    {
      try
      {
        Stopwatch timeToDownload = new Stopwatch();

        while (IsActive)
        {
          timeToDownload.Restart();
          string webResponse = _webClient.DownloadString(_serviceUrl);
          timeToDownload.Stop();

          PopulatePricesFromWebResponse(webResponse);
          UpdateStats(timeToDownload, webResponse);
        }
      }
      catch (Exception e)
      {
        Log.Error("Exception during DownloadPrices()");
        Log.Error("Stack Trace {0}: /r/nException Message: {1}", e.StackTrace, e.Message);
        this.Stop();
      }
    }

    private void PopulatePricesFromWebResponse(string webResponse)
    {
      string[] webPrices = webResponse.Split(
        new string[] { "\n", "\r\n" },
        StringSplitOptions.RemoveEmptyEntries);

      foreach (string webPriceData in webPrices)
      {
        var webPrice = Factory.CreatePrice(webPriceData);
        var localPrice = _currentPrices.Find(x => x.Symbol == webPrice.Symbol);

        if (localPrice == null) {
          _currentPrices.Add(new Price(webPrice.Symbol, webPrice.CurrentPrice, webPrice.PreviousPrice));
          continue;
        }

        if (localPrice.Equals(webPrice)) {
          continue;
        }
        else {
          localPrice.PreviousPrice = localPrice.CurrentPrice;
          localPrice.CurrentPrice = webPrice.CurrentPrice;
          RaisePriceChanged(localPrice); 
        }
      }
    }

    private void UpdateStats(Stopwatch timeToDownload, string webResponse)
    {
      Stats.LastWebRequest.Duration = (int)timeToDownload.ElapsedMilliseconds;
      Stats.LastWebRequest.PricesDownloaded = _currentPrices.Count;
      Stats.LastWebRequest.Response = webResponse;
      Stats.LastWebRequest.Request = _serviceUrl;
      Stats.LastWebRequest.SymbolCount = _companies.Count;
      Stats.NumberOfRequests++;
      Log.Trace(Stats);
    }
  }
}