private bool RevertQuotesAndReturnFalse(IReadOnlyCollection <T> originalQuotes, IQuoteStorageService <T> quoteStorageService) { if (originalQuotes == null || originalQuotes.Count == 0) { return(false); } foreach (var originalQuote in originalQuotes) { quoteStorageService.AddOrUpdate(originalQuote); } return(false); }
public void AddOrUpdate(T quote) { // Index first, and if successful send to primary storage - taking this approach vs. the inverted as the indexes are simply pointers to the // primary storage and do not require thread syncronization, so reverting those is relatively painless and side-effect free compared to the possibility // of something existing in primary storage for a while, getting read possibly and used, then having to revert because something went wrong with // indexing. An alternate approach here could be to lock things for the duration of the add/update, but that would be either fairly broad (i.e. a // lock on an entire symbol), or fairly complex (locking portions of a symbol, i.e. a symbol and quote combination), which...why? _quoteIndexService.AddOrUpdate(quote); try { _quoteStorageService.AddOrUpdate(quote); } catch when(RemoveFromIndexAndReturnFalse(quote)) { // Unreachable throw - the above when filter will remove from the index and return false, which allows us to ensure index removal witout // unwinding the call stack just to throw an exception - as is, it'll just bubble out of here like an unhandled exception throw; } }