Code cleanup.
This commit is contained in:
@@ -51,18 +51,12 @@ namespace MarketData.Cache
|
|||||||
private DateGenerator dateGenerator = new DateGenerator();
|
private DateGenerator dateGenerator = new DateGenerator();
|
||||||
private static GBPriceCache priceCacheInstance = null;
|
private static GBPriceCache priceCacheInstance = null;
|
||||||
private int cacheRefreshAfter = 120000; // 2 minutes
|
private int cacheRefreshAfter = 120000; // 2 minutes
|
||||||
|
|
||||||
private SemaphoreSlim fetchSemaphore = new SemaphoreSlim(8); // max 8 concurrent DB fetches
|
private SemaphoreSlim fetchSemaphore = new SemaphoreSlim(8); // max 8 concurrent DB fetches
|
||||||
|
|
||||||
public IPricingDataAccess PricingDataAccess { get; set; } = new RealPricingDA();
|
public IPricingDataAccess PricingDataAccess { get; set; } = new RealPricingDA();
|
||||||
|
|
||||||
protected GBPriceCache()
|
protected GBPriceCache()
|
||||||
{
|
{
|
||||||
snapshot = new CacheSnapshot(
|
snapshot = new CacheSnapshot(new Dictionary<String, PricesByDate>(), new Dictionary<String, Price>(), new Dictionary<String, bool>());
|
||||||
new Dictionary<String, PricesByDate>(),
|
|
||||||
new Dictionary<String, Price>(),
|
|
||||||
new Dictionary<String, bool>());
|
|
||||||
|
|
||||||
cacheMonitorThread = new Thread(new ThreadStart(ThreadProc));
|
cacheMonitorThread = new Thread(new ThreadStart(ThreadProc));
|
||||||
cacheMonitorThread.Start();
|
cacheMonitorThread.Start();
|
||||||
}
|
}
|
||||||
@@ -71,7 +65,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (typeof(GBPriceCache))
|
lock (typeof(GBPriceCache))
|
||||||
{
|
{
|
||||||
if (priceCacheInstance == null)
|
if (null == priceCacheInstance)
|
||||||
{
|
{
|
||||||
priceCacheInstance = new GBPriceCache();
|
priceCacheInstance = new GBPriceCache();
|
||||||
}
|
}
|
||||||
@@ -83,10 +77,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
snapshot = new CacheSnapshot(
|
snapshot = new CacheSnapshot(new Dictionary<String, PricesByDate>(), new Dictionary<String, Price>(), new Dictionary<String, bool>());
|
||||||
new Dictionary<String, PricesByDate>(),
|
|
||||||
new Dictionary<String, Price>(),
|
|
||||||
new Dictionary<String, bool>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +85,14 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (priceCacheInstance == null || !threadRun) return;
|
if (null == priceCacheInstance || !threadRun) return;
|
||||||
threadRun = false;
|
threadRun = false;
|
||||||
|
if (null != cacheMonitorThread)
|
||||||
if (cacheMonitorThread != null)
|
|
||||||
{
|
{
|
||||||
MDTrace.WriteLine(LogLevel.DEBUG, "[GBPriceCache:Dispose] Joining monitor thread...");
|
MDTrace.WriteLine(LogLevel.DEBUG, "[GBPriceCache:Dispose] Joining monitor thread...");
|
||||||
cacheMonitorThread.Join(5000);
|
cacheMonitorThread.Join(5000);
|
||||||
cacheMonitorThread = null;
|
cacheMonitorThread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
priceCacheInstance = null;
|
priceCacheInstance = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,26 +107,19 @@ namespace MarketData.Cache
|
|||||||
String symbol = entry.Key;
|
String symbol = entry.Key;
|
||||||
PricesByDate filteredPrices = new PricesByDate();
|
PricesByDate filteredPrices = new PricesByDate();
|
||||||
PricesByDate existingPrices = entry.Value;
|
PricesByDate existingPrices = entry.Value;
|
||||||
|
foreach (KeyValuePair<DateTime, Price> kvp in existingPrices)
|
||||||
foreach (KeyValuePair<DateTime, Price> kv in existingPrices)
|
|
||||||
{
|
{
|
||||||
if (kv.Key >= onOrBeforeDate)
|
if (kvp.Key >= onOrBeforeDate)
|
||||||
{
|
{
|
||||||
filteredPrices.Add(kv.Key, kv.Value);
|
filteredPrices.Add(kvp.Key, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredPrices.Count > 0)
|
if (filteredPrices.Count > 0)
|
||||||
{
|
{
|
||||||
newPriceCache.Add(symbol, filteredPrices);
|
newPriceCache.Add(symbol, filteredPrices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UpdateSnapshot(newPriceCache, snapshot.RealTimePriceCache, snapshot.NullCache);
|
||||||
UpdateSnapshot(
|
|
||||||
newPriceCache,
|
|
||||||
snapshot.RealTimePriceCache,
|
|
||||||
snapshot.NullCache);
|
|
||||||
|
|
||||||
if (collect) GC.Collect();
|
if (collect) GC.Collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,12 +127,10 @@ namespace MarketData.Cache
|
|||||||
public Price GetPriceOrLatestAvailable(String symbol, DateTime date)
|
public Price GetPriceOrLatestAvailable(String symbol, DateTime date)
|
||||||
{
|
{
|
||||||
Price price = GetPrice(symbol, date);
|
Price price = GetPrice(symbol, date);
|
||||||
if (price != null) return price;
|
if (null != price) return price;
|
||||||
|
|
||||||
DateTime latestPricingDate = PricingDataAccess.GetLatestDateOnOrBefore(symbol, date);
|
DateTime latestPricingDate = PricingDataAccess.GetLatestDateOnOrBefore(symbol, date);
|
||||||
price = GetPrice(symbol, latestPricingDate);
|
price = GetPrice(symbol, latestPricingDate);
|
||||||
if (price != null) return price;
|
if (null != price) return price;
|
||||||
|
|
||||||
fetchSemaphore.Wait();
|
fetchSemaphore.Wait();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -160,8 +140,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
fetchSemaphore.Release();
|
fetchSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
if (null !=price) AddPrice(price);
|
||||||
if (price != null) AddPrice(price);
|
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +152,7 @@ namespace MarketData.Cache
|
|||||||
}
|
}
|
||||||
|
|
||||||
Price price = MarketDataHelper.GetLatestPrice(symbol);
|
Price price = MarketDataHelper.GetLatestPrice(symbol);
|
||||||
if (price != null)
|
if (null != price)
|
||||||
{
|
{
|
||||||
Dictionary<String, Price> newRealtime = new Dictionary<String, Price>(snapshot.RealTimePriceCache);
|
Dictionary<String, Price> newRealtime = new Dictionary<String, Price>(snapshot.RealTimePriceCache);
|
||||||
newRealtime.Add(symbol, price);
|
newRealtime.Add(symbol, price);
|
||||||
@@ -192,7 +171,6 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchSemaphore.Wait();
|
fetchSemaphore.Wait();
|
||||||
Price price;
|
Price price;
|
||||||
try
|
try
|
||||||
@@ -203,8 +181,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
fetchSemaphore.Release();
|
fetchSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
if (null ==price)
|
||||||
if (price == null)
|
|
||||||
{
|
{
|
||||||
Dictionary<String, bool> newNullCache = new Dictionary<String, bool>(snapshot.NullCache);
|
Dictionary<String, bool> newNullCache = new Dictionary<String, bool>(snapshot.NullCache);
|
||||||
newNullCache.Add(key, true);
|
newNullCache.Add(key, true);
|
||||||
@@ -214,7 +191,6 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
AddPrice(price);
|
AddPrice(price);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!snapshot.PriceCache.ContainsKey(symbol)) return null;
|
if (!snapshot.PriceCache.ContainsKey(symbol)) return null;
|
||||||
PricesByDate pricesByDate = snapshot.PriceCache[symbol];
|
PricesByDate pricesByDate = snapshot.PriceCache[symbol];
|
||||||
if (!pricesByDate.ContainsKey(date)) return null;
|
if (!pricesByDate.ContainsKey(date)) return null;
|
||||||
@@ -224,24 +200,20 @@ namespace MarketData.Cache
|
|||||||
public Prices GetPrices(String symbol, DateTime earlierDate, DateTime laterDate)
|
public Prices GetPrices(String symbol, DateTime earlierDate, DateTime laterDate)
|
||||||
{
|
{
|
||||||
DateGenerator localDateGenerator = new DateGenerator();
|
DateGenerator localDateGenerator = new DateGenerator();
|
||||||
|
|
||||||
if (laterDate < earlierDate)
|
if (laterDate < earlierDate)
|
||||||
{
|
{
|
||||||
DateTime tempDate = earlierDate;
|
DateTime tempDate = earlierDate;
|
||||||
earlierDate = laterDate;
|
earlierDate = laterDate;
|
||||||
laterDate = tempDate;
|
laterDate = tempDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DateTime> datesList = localDateGenerator.GenerateHistoricalDates(earlierDate, laterDate);
|
List<DateTime> datesList = localDateGenerator.GenerateHistoricalDates(earlierDate, laterDate);
|
||||||
datesList = datesList.Where(x => x >= earlierDate).ToList();
|
datesList = datesList.Where(x => x >= earlierDate).ToList();
|
||||||
|
|
||||||
return GetPrices(symbol, laterDate, datesList.Count);
|
return GetPrices(symbol, laterDate, datesList.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Prices GetPrices(String symbol, DateTime startDate, int dayCount)
|
public Prices GetPrices(String symbol, DateTime startDate, int dayCount)
|
||||||
{
|
{
|
||||||
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(startDate, dayCount + 60);
|
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(startDate, dayCount + 60);
|
||||||
|
|
||||||
List<DateTime> missingDates = new List<DateTime>();
|
List<DateTime> missingDates = new List<DateTime>();
|
||||||
foreach (DateTime historicalDate in historicalDates)
|
foreach (DateTime historicalDate in historicalDates)
|
||||||
{
|
{
|
||||||
@@ -254,7 +226,6 @@ namespace MarketData.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missingDates.Count > 0)
|
if (missingDates.Count > 0)
|
||||||
{
|
{
|
||||||
DateTime minDate = missingDates.Min();
|
DateTime minDate = missingDates.Min();
|
||||||
@@ -292,7 +263,7 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
private void AddPrice(Price price)
|
private void AddPrice(Price price)
|
||||||
{
|
{
|
||||||
if (price == null) return;
|
if (null == price) return;
|
||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
@@ -331,8 +302,8 @@ namespace MarketData.Cache
|
|||||||
while (threadRun)
|
while (threadRun)
|
||||||
{
|
{
|
||||||
Thread.Sleep(quantumInterval);
|
Thread.Sleep(quantumInterval);
|
||||||
|
if(!threadRun)break;
|
||||||
quantums += quantumInterval;
|
quantums += quantumInterval;
|
||||||
|
|
||||||
if (quantums > cacheRefreshAfter)
|
if (quantums > cacheRefreshAfter)
|
||||||
{
|
{
|
||||||
quantums = 0;
|
quantums = 0;
|
||||||
@@ -344,10 +315,7 @@ namespace MarketData.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSnapshot(
|
private void UpdateSnapshot(Dictionary<String, PricesByDate> newPriceCache,Dictionary<String, Price> newRealtimePriceCache, Dictionary<String, bool> newNullCache)
|
||||||
Dictionary<String, PricesByDate> newPriceCache,
|
|
||||||
Dictionary<String, Price> newRealtimePriceCache,
|
|
||||||
Dictionary<String, bool> newNullCache)
|
|
||||||
{
|
{
|
||||||
snapshot = new CacheSnapshot(newPriceCache, newRealtimePriceCache, newNullCache);
|
snapshot = new CacheSnapshot(newPriceCache, newRealtimePriceCache, newNullCache);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
using MarketData.Utils;
|
using MarketData.Utils;
|
||||||
using MarketData.DataAccess;
|
using MarketData.DataAccess;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace MarketData.Cache
|
namespace MarketData.Cache
|
||||||
{
|
{
|
||||||
@@ -109,9 +114,11 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
Parallel.ForEach(symbols, new ParallelOptions { MaxDegreeOfParallelism = 8 }, symbol =>
|
Parallel.ForEach(symbols, new ParallelOptions { MaxDegreeOfParallelism = 8 }, symbol =>
|
||||||
{
|
{
|
||||||
if (!currentMaxDates.TryGetValue(symbol, out var cachedMax)) return;
|
DateTime cachedMax;
|
||||||
|
if (!currentMaxDates.TryGetValue(symbol, out cachedMax)) return;
|
||||||
|
|
||||||
if (maxDbDates.TryGetValue(symbol, out var dbMax) && dbMax.Date != cachedMax.Date)
|
DateTime dbMax;
|
||||||
|
if (maxDbDates.TryGetValue(symbol, out dbMax) && dbMax.Date != cachedMax.Date)
|
||||||
{
|
{
|
||||||
Prices prices = PricingDA.GetPrices(symbol, cachedMax);
|
Prices prices = PricingDA.GetPrices(symbol, cachedMax);
|
||||||
if (prices != null) fullReloads[symbol] = prices.GetPricesByDate();
|
if (prices != null) fullReloads[symbol] = prices.GetPricesByDate();
|
||||||
@@ -128,7 +135,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
latestDate = latestDateFromDb;
|
latestDate = latestDateFromDb;
|
||||||
|
|
||||||
foreach (var kvp in fullReloads)
|
foreach (KeyValuePair<string, PricesByDate> kvp in fullReloads)
|
||||||
{
|
{
|
||||||
if (priceCache.TryGetValue(kvp.Key, out PricesByDate existing) && existing.MaxDate == currentMaxDates[kvp.Key])
|
if (priceCache.TryGetValue(kvp.Key, out PricesByDate existing) && existing.MaxDate == currentMaxDates[kvp.Key])
|
||||||
{
|
{
|
||||||
@@ -136,11 +143,10 @@ namespace MarketData.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kvp in singleUpdates)
|
foreach (KeyValuePair<string, Price> kvp in singleUpdates)
|
||||||
{
|
{
|
||||||
if (priceCache.TryGetValue(kvp.Key, out PricesByDate pricesByDate) && pricesByDate.MaxDate == currentMaxDates[kvp.Key])
|
if (priceCache.TryGetValue(kvp.Key, out PricesByDate pricesByDate) && pricesByDate.MaxDate == currentMaxDates[kvp.Key])
|
||||||
{
|
{
|
||||||
// Remove the old price (if any) and add the new price properly
|
|
||||||
if (pricesByDate.ContainsKey(kvp.Value.Date))
|
if (pricesByDate.ContainsKey(kvp.Value.Date))
|
||||||
pricesByDate.Remove(kvp.Value.Date);
|
pricesByDate.Remove(kvp.Value.Date);
|
||||||
pricesByDate.Add(kvp.Value.Date, kvp.Value);
|
pricesByDate.Add(kvp.Value.Date, kvp.Value);
|
||||||
@@ -194,9 +200,9 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
foreach (var kvp in fetchedPrices)
|
foreach (KeyValuePair<string, Prices> kvp in fetchedPrices)
|
||||||
{
|
{
|
||||||
foreach (var price in kvp.Value)
|
foreach (Price price in kvp.Value)
|
||||||
{
|
{
|
||||||
Add(price);
|
Add(price);
|
||||||
}
|
}
|
||||||
@@ -238,7 +244,7 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
foreach (var kvp in fetchedPrices)
|
foreach (KeyValuePair<string, Price> kvp in fetchedPrices)
|
||||||
{
|
{
|
||||||
Add(kvp.Value);
|
Add(kvp.Value);
|
||||||
}
|
}
|
||||||
@@ -251,14 +257,15 @@ namespace MarketData.Cache
|
|||||||
|
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(price.Symbol, out var pricesByDate))
|
PricesByDate pricesByDate;
|
||||||
|
if (!priceCache.TryGetValue(price.Symbol, out pricesByDate))
|
||||||
{
|
{
|
||||||
pricesByDate = new PricesByDate();
|
pricesByDate = new PricesByDate();
|
||||||
priceCache[price.Symbol] = pricesByDate;
|
priceCache[price.Symbol] = pricesByDate;
|
||||||
}
|
}
|
||||||
if (!pricesByDate.ContainsKey(price.Date))
|
if (!pricesByDate.ContainsKey(price.Date))
|
||||||
{
|
{
|
||||||
pricesByDate.Add(price.Date, price); // must use Add() to update MinDate/MaxDate
|
pricesByDate.Add(price.Date, price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +274,8 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(symbol, out var symbolPrices) || symbolPrices.Count == 0)
|
PricesByDate symbolPrices;
|
||||||
|
if (!priceCache.TryGetValue(symbol, out symbolPrices) || symbolPrices.Count == 0)
|
||||||
{
|
{
|
||||||
return Utility.Epoch;
|
return Utility.Epoch;
|
||||||
}
|
}
|
||||||
@@ -279,7 +287,7 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
foreach (var kvp in priceCache)
|
foreach (KeyValuePair<string, PricesByDate> kvp in priceCache)
|
||||||
{
|
{
|
||||||
kvp.Value.Remove(date);
|
kvp.Value.Remove(date);
|
||||||
}
|
}
|
||||||
@@ -290,7 +298,8 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return new Prices();
|
PricesByDate pricesByDate;
|
||||||
|
if (!priceCache.TryGetValue(symbol, out pricesByDate)) return new Prices();
|
||||||
|
|
||||||
DateGenerator dateGenerator = new DateGenerator();
|
DateGenerator dateGenerator = new DateGenerator();
|
||||||
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(endDate, dayCount);
|
List<DateTime> historicalDates = dateGenerator.GenerateHistoricalDates(endDate, dayCount);
|
||||||
@@ -312,8 +321,11 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return null;
|
PricesByDate pricesByDate;
|
||||||
return pricesByDate.TryGetValue(date, out var price) ? price : null;
|
if (!priceCache.TryGetValue(symbol, out pricesByDate)) return null;
|
||||||
|
|
||||||
|
Price price;
|
||||||
|
return pricesByDate.TryGetValue(date, out price) ? price : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +333,8 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(symbol, out var pricesByDate)) return false;
|
PricesByDate pricesByDate;
|
||||||
|
if (!priceCache.TryGetValue(symbol, out pricesByDate)) return false;
|
||||||
return pricesByDate.ContainsKey(date);
|
return pricesByDate.ContainsKey(date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +347,8 @@ namespace MarketData.Cache
|
|||||||
{
|
{
|
||||||
foreach (string symbol in symbols)
|
foreach (string symbol in symbols)
|
||||||
{
|
{
|
||||||
if (!priceCache.TryGetValue(symbol, out var pricesByDate) || !pricesByDate.ContainsKey(date))
|
PricesByDate pricesByDate;
|
||||||
|
if (!priceCache.TryGetValue(symbol, out pricesByDate) || !pricesByDate.ContainsKey(date))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -356,7 +370,7 @@ namespace MarketData.Cache
|
|||||||
lock (thisLock)
|
lock (thisLock)
|
||||||
{
|
{
|
||||||
long count = 0;
|
long count = 0;
|
||||||
foreach (var pricesByDate in priceCache.Values)
|
foreach (PricesByDate pricesByDate in priceCache.Values)
|
||||||
{
|
{
|
||||||
count += pricesByDate.Count;
|
count += pricesByDate.Count;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user