Beispiel #1
0
        private void SetBatchResults(
            IDictionary <TKey, TaskCompletionSource <TValue> > bufferedPromises,
            IReadOnlyList <TKey> resolvedKeys,
            IReadOnlyList <IResult <TValue> > results)
        {
            if (resolvedKeys.Count == results.Count)
            {
                for (var i = 0; i < resolvedKeys.Count; i++)
                {
                    SetSingleResult(bufferedPromises[resolvedKeys[i]],
                                    resolvedKeys[i], results[i]);
                }
            }
            else
            {
                Exception error = Errors.CreateKeysAndValuesMustMatch(
                    resolvedKeys.Count, results.Count);

                for (var i = 0; i < resolvedKeys.Count; i++)
                {
                    DispatchingDiagnostics.RecordError(resolvedKeys[i], error);
                    bufferedPromises[resolvedKeys[i]].SetException(error);
                }
            }
        }
Beispiel #2
0
        private async Task DispatchAsync(
            TKey resolvedKey,
            TaskCompletionSource <TValue> promise)
        {
            var      resolvedKeys = new TKey[] { resolvedKey };
            Activity activity     = DispatchingDiagnostics
                                    .StartBatching(resolvedKeys);
            IReadOnlyList <IResult <TValue> > results =
                await Fetch(resolvedKeys).ConfigureAwait(false);

            if (results.Count == 1)
            {
                SetSingleResult(promise, resolvedKey, results.First());
            }
            else
            {
                Exception error = Errors.CreateKeysAndValuesMustMatch(1,
                                                                      results.Count);

                DispatchingDiagnostics.RecordError(resolvedKey, error);
                promise.SetException(error);
            }

            DispatchingDiagnostics.StopBatching(activity, resolvedKeys,
                                                results);
        }
Beispiel #3
0
        private async Task FetchInternalAsync(
            IDictionary <TKey, TaskCompletionSource <TValue> > bufferedPromises,
            IReadOnlyList <TKey> resolvedKeys)
        {
            Activity activity = DispatchingDiagnostics
                                .StartBatching(resolvedKeys);
            IReadOnlyList <IResult <TValue> > results =
                await Fetch(resolvedKeys).ConfigureAwait(false);

            SetBatchResults(bufferedPromises, resolvedKeys, results);
            DispatchingDiagnostics.StopBatching(activity, resolvedKeys,
                                                results);
        }
Beispiel #4
0
        /// <inheritdoc />
        public Task <TValue> LoadAsync(TKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            lock (_sync)
            {
                TKey resolvedKey = _cacheKeyResolver(key);

                if (_options.Caching && _cache.TryGetValue(resolvedKey,
                                                           out Task <TValue> cachedValue))
                {
                    DispatchingDiagnostics.RecordCachedValue(resolvedKey,
                                                             cachedValue);

                    return(cachedValue);
                }

                var promise = new TaskCompletionSource <TValue>(
                    TaskCreationOptions.RunContinuationsAsynchronously);

                if (_options.Batching)
                {
                    if (!_buffer.TryAdd(resolvedKey, promise) &&
                        _buffer.TryGetValue(resolvedKey,
                                            out TaskCompletionSource <TValue> value))
                    {
                        promise.TrySetCanceled();
                        promise = value;
                    }
                }
                else
                {
                    // note: must run in the background; do not await here.
                    Task.Factory.StartNew(
                        () => DispatchAsync(resolvedKey, promise),
                        TaskCreationOptions.RunContinuationsAsynchronously);
                }

                if (_options.Caching)
                {
                    _cache.TryAdd(resolvedKey, promise.Task);
                }

                return(promise.Task);
            }
        }
Beispiel #5
0
 private void SetSingleResult(
     TaskCompletionSource <TValue> promise,
     TKey resolvedKey,
     IResult <TValue> result)
 {
     if (result.IsError)
     {
         DispatchingDiagnostics.RecordError(resolvedKey, result.Error);
         promise.SetException(result.Error);
     }
     else
     {
         promise.SetResult(result.Value);
     }
 }