private Task SetWaitingEntryToStateInternalAsync(CountryKind country, string stockId, HistoricalDataWaitingState state)
        {
            IHistoricalDataWaitingEntry entry = HistoricalDataWaitingEntryTable.Find(a => a.Country == country &&
                                                                                     string.Equals(a.StockId, stockId, StringComparison.OrdinalIgnoreCase));

            if (entry is HistoricalDataWaitingEntry tempEntry)
            {
                tempEntry.State = state;
            }

            return(Task.CompletedTask);
        }
        public Task AddWaitingEntryAsync(CountryKind country, string stockId, DateTime startDate, DateTime endDate)
        {
            IHistoricalDataWaitingEntry entry = HistoricalDataWaitingEntryTable.Find(a => a.Country == country &&
                                                                                     string.Equals(a.StockId, stockId, StringComparison.OrdinalIgnoreCase));

            if (entry != null)
            {
                return(Task.CompletedTask);
            }

            entry = new HistoricalDataWaitingEntry(country, stockId, HistoricalDataWaitingState.Waiting, startDate, endDate);
            HistoricalDataWaitingEntryTable.Add(entry);

            return(Task.CompletedTask);
        }
        private async Task CoreRunAsync(IHistoricalDataWaitingEntry entry, StockPriceHistoryInsertion insertion, CancellationToken token)
        {
            DateTime start = DateTime.Now;

            WriteToWorkerLog($"Start {entry.StockId}");

            if (token.IsCancellationRequested)
            {
                return;
            }

            IReadOnlyList <IStockQuoteFromDataSource> records = await YahooDataSource.GetHistoricalQuotesAsync(entry.Country.ConvertToTTStockQuoteSourceCountry(),
                                                                                                               entry.StockId,
                                                                                                               entry.DataStartDate,
                                                                                                               entry.DataEndDate,
                                                                                                               WriteToErrorLog)
                                                                .ConfigureAwait(false);

            if (records == null || records.Count == 0)
            {
                WriteToWorkerLog($"Data source returned NULL historical data of {entry.Country.GetShortName()}.{entry.StockId}");
                return;
            }

            foreach (IStockQuoteFromDataSource record in records)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }

                // insert records into database
                await insertion.InsertToDatabase(record).ConfigureAwait(false);
            }

            await DatabaseOperations.SetWaitingEntryToDoneAsync(entry.Country, entry.StockId).ConfigureAwait(false);

            TimeSpan timeSpan = DateTime.Now - start;

            WriteToWorkerLog($"Finish {entry.Country.GetShortName()}.{entry.StockId}. Total time = {timeSpan.TotalSeconds} seconds");
        }