private void CachePage(Page page, string subscriptionId) { if (IsCachingEnabled) { IReadOnlyList <Transaction> transactions = page.Transactions; // Add to cache in reverse order to prevent other projectors seeing the first transactions on the cache before the entire page is there. for (int index = transactions.Count - 1; index > 0; index--) { cachedTransactionsByPrecedingCheckpoint.Set(transactions[index - 1].Checkpoint, transactions[index]); } cachedTransactionsByPrecedingCheckpoint.Set(page.PrecedingCheckpoint, transactions[0]); logDebug(() => $"Cached: (subscription: {subscriptionId}, precedingCheckpoint: {page.PrecedingCheckpoint}, transactions: {transactions.Count}, range: {transactions.First().Checkpoint}-{transactions.Last().Checkpoint}."); } }
private async Task <Page> TryLoadNextPage(long previousCheckpoint, string subscriptionId) { // Maybe it's just loaded to cache. try { Page cachedPage = TryGetNextPageFromCache(previousCheckpoint, subscriptionId); if (cachedPage.Transactions.Count > 0) { #if LIQUIDPROJECTIONS_DIAGNOSTICS logger(() => $"Loader for subscription {subscriptionId} has found a page in the cache."); #endif return(cachedPage); } } catch (Exception exception) { logger(() => $"Failed getting transactions after checkpoint {previousCheckpoint} from the cache: " + exception); } DateTime timeOfRequestUtc = getUtcNow(); List <Transaction> transactions; try { transactions = await Task .Run(() => eventStore .GetFrom((previousCheckpoint == 0) ? (long?)null : previousCheckpoint) .Take(maxPageSize) .ToList()) .ConfigureAwait(false); } catch (Exception exception) { logger(() => $"Failed loading transactions after checkpoint {previousCheckpoint} from NEventStore: " + exception); throw; } if (transactions.Count > 0) { #if LIQUIDPROJECTIONS_DIAGNOSTICS logger(() => $"Loader for subscription {subscriptionId ?? "without ID"} has loaded {transactions.Count} transactions " + $"from checkpoint {transactions.First().Checkpoint} to checkpoint {transactions.Last().Checkpoint}."); #endif if (transactionCacheByPreviousCheckpoint != null) { /* Add to cache in reverse order to prevent other projectors * from requesting already loaded transactions which are not added to cache yet. */ for (int index = transactions.Count - 1; index > 0; index--) { transactionCacheByPreviousCheckpoint.Set(transactions[index - 1].Checkpoint, transactions[index]); } transactionCacheByPreviousCheckpoint.Set(previousCheckpoint, transactions[0]); #if LIQUIDPROJECTIONS_DIAGNOSTICS logger(() => $"Loader for subscription {subscriptionId ?? "without ID"} has cached {transactions.Count} transactions " + $"from checkpoint {transactions.First().Checkpoint} to checkpoint {transactions.Last().Checkpoint}."); #endif } } else { #if LIQUIDPROJECTIONS_DIAGNOSTICS logger(() => $"Loader for subscription {subscriptionId} has discovered " + $"that there are no new transactions yet. Next request for the new transactions will be delayed."); #endif Volatile.Write( ref lastSuccessfulPollingRequestWithoutResults, new CheckpointRequestTimestamp(previousCheckpoint, timeOfRequestUtc)); } return(new Page(previousCheckpoint, transactions)); }