예제 #1
0
        private async Task <DataTree> GetUserEntriesForDayAsync(DateTime date, string dateKey, string userId)
        {
            DataTree      userTree  = new DataTree();
            DataTree      result    = new DataTree();
            SemaphoreSlim semaphore = null;

            try
            {
                // Lock whole cache when getting a single user entry
                lock (userEntries)
                {
                    userTree = userEntries[userId];
                    userTree.Create();
                }

                // Use semaphore instead of lock for async calls.
                lock (userDataSemaphores)
                {
                    if (userDataSemaphores.ContainsKey(userId))
                    {
                        semaphore = userDataSemaphores[userId];
                    }
                    else
                    {
                        semaphore = new SemaphoreSlim(1);
                        userDataSemaphores[userId] = semaphore;
                    }
                }

                // Lock the user entry when working on it.
                await semaphore.WaitAsync();

                // Make sure we really have a date.
                string dateStr = date.Date.ToString(DateStringFormat);

                // Determine if day's data is dirty and if we need to get new data.
                if ((bool)userEntries[userId][dateStr]["dirty"].GetValueOrDefault(true))
                {
                    // In case the data is dirty we need to refetch. We maintain lock to this user's data but not to anything else.
                    result = await RefreshUserDataForDayAsync(userTree, date, dateKey);
                }
                else
                {
                    return(userEntries[userId][dateStr]);
                }
            }
            catch (Exception ex)
            {
                logger.LogError("Failed to get user entries from cache.", ex);
            }
            finally
            {
                if (semaphore != null)
                {
                    semaphore.Release();
                }
            }

            return(result);
        }