/// <summary> /// Initializes a new instance of the /// <see cref="DataLoader{TKey, TValue}"/> class. /// </summary> /// <param name="options"> /// An options object to configure the behavior of this particular /// <see cref="DataLoader{TKey, TValue}"/>. /// </param> /// <param name="fetch"> /// A delegate to fetch data batches which will be invoked every time /// when trying to setup a new batch request. /// </param> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="options"/> is <c>null</c>. /// </exception> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="fetch"/> is <c>null</c>. /// </exception> public DataLoader( DataLoaderOptions <TKey> options, FetchDataDelegate <TKey, TValue> fetch) : base(options) { _fetch = fetch ?? throw new ArgumentNullException(nameof(fetch)); }
private static DataLoaderOptions CreateLocalOptions(DataLoaderOptions options) { DataLoaderOptions local = options.Copy(); local.MaxBatchSize = 1; return(local); }
public void RemoveEntry() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { Batching = false }; var loader = new DataLoader <string, string>(options, fetch); var key = "Foo"; loader.Set(key, Task.FromResult("Bar")); // act IDataLoader <string, string> result = loader.Remove(key); // assert Task <string> loadResult = loader.LoadAsync(key); if (loadResult is IAsyncResult asyncResult) { asyncResult.AsyncWaitHandle.WaitOne(); } Assert.Equal(loader, result); Assert.NotNull(loadResult.Exception); }
/// <summary> /// Initializes a new instance of the /// <see cref="DataLoaderBase{TKey, TValue}"/> class. /// </summary> /// <param name="options"> /// A configuration for <c>DataLoaders</c>. /// </param> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="options"/> is <c>null</c>. /// </exception> protected DataLoaderBase(DataLoaderOptions <TKey> options) : this(options, new TaskCache <TValue>( options?.CacheSize ?? Defaults.CacheSize, options?.SlidingExpiration ?? Defaults.SlidingExpiration)) { }
public async Task LoadCollectionResult() { // arrange var expectedResult = Result <string> .Resolve("Bar"); FetchDataDelegate <string, string> fetch = async k => await Task.FromResult(new[] { expectedResult }) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { Batching = false }; var loader = new DataLoader <string, string>(options, fetch); var keys = new List <string> { "Foo" }; // act IReadOnlyList <string> loadResult = await loader .LoadAsync(keys) .ConfigureAwait(false); // assert Assert.Collection(loadResult, v => Assert.Equal(expectedResult.Value, v)); }
public async Task DispatchAsyncKeysValuesNotMatching() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { BatchRequestDelay = TimeSpan.FromMinutes(10) }; var loader = new DataLoader <string, string>(options, fetch); await Task.Delay(10); Task <IReadOnlyList <string> > loadResult = loader.LoadAsync("Foo", "Bar"); await loader.DispatchAsync().ConfigureAwait(false); // act Func <Task> verify = () => loadResult; // assert await Assert.ThrowsAsync <InvalidOperationException>(verify) .ConfigureAwait(false); }
public void ConstructorAllProps() { // act var options = new DataLoaderOptions <string> { AutoDispatching = false, Batching = false, BatchRequestDelay = TimeSpan.FromSeconds(1), CacheKeyResolver = k => k, CacheSize = 1, Caching = false, MaxBatchSize = 1, SlidingExpiration = TimeSpan.FromSeconds(10) }; // assert Assert.False(options.AutoDispatching); Assert.False(options.Batching); Assert.Equal(TimeSpan.FromSeconds(1), options.BatchRequestDelay); Assert.NotNull(options.CacheKeyResolver); Assert.Equal(1, options.CacheSize); Assert.False(options.Caching); Assert.Equal(1, options.MaxBatchSize); Assert.Equal(TimeSpan.FromSeconds(10), options.SlidingExpiration); }
public async Task DispatchAsyncAuto() { // arrange IResult <string> expectedResult = Result <string> .Resolve("Bar"); FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new[] { expectedResult }) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { BatchRequestDelay = TimeSpan.FromMinutes(10) }; var loader = new DataLoader <string, string>(options, fetch); await Task.Delay(10); Task <string> loadResult = loader.LoadAsync("Foo"); // act await loader.DispatchAsync().ConfigureAwait(false); // assert Assert.Equal(expectedResult.Value, await loadResult.ConfigureAwait(false)); }
public async Task DispatchAsyncNoBatching() { // arrange IResult <string> expectedResult = Result <string> .Resolve("Bar"); FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new[] { expectedResult }) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { Batching = false }; var loader = new DataLoader <string, string>(options, fetch); // this would block if batching would be enabled var loadResult = await loader.LoadAsync("Foo") .ConfigureAwait(false); // act await loader.DispatchAsync().ConfigureAwait(false); // assert Assert.Equal(expectedResult.Value, loadResult); }
public async Task ClearAllEntries() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); var options = new DataLoaderOptions <string> { Batching = false }; var loader = new DataLoader <string, string>(options, fetch); loader.Set("Foo", Task.FromResult("Bar")); loader.Set("Bar", Task.FromResult("Baz")); // act IDataLoader <string, string> result = loader.Clear(); // assert Func <Task> verify = () => loader.LoadAsync("Foo", "Bar"); Assert.Equal(loader, result); await Assert.ThrowsAsync <InvalidOperationException>(verify) .ConfigureAwait(false); }
public void ConstructorEmpty() { // act var options = new DataLoaderOptions <string>(); // assert options.MatchSnapshot(); }
/// <summary> /// Initializes a new instance of the <see cref="DataLoader{TKey, TValue}"/> class. /// </summary> /// <param name="batchScheduler"> /// A scheduler to tell the <c>DataLoader</c> when to dispatch buffered batches. /// </param> /// <param name="options"> /// An options object to configure the behavior of this particular /// <see cref="DataLoader{TKey, TValue}"/>. /// </param> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="options"/> is <c>null</c>. /// </exception> protected DataLoaderBase(IBatchScheduler batchScheduler, DataLoaderOptions <TKey>?options) { _options = options ?? new DataLoaderOptions <TKey>(); _cache = _options.Cache ?? new TaskCache(_options.CacheSize); _cacheKeyResolver = _options.CacheKeyResolver ?? ((TKey key) => key); _batchScheduler = batchScheduler; _maxBatchSize = _options.GetBatchSize(); }
public DataLoader( IBatchScheduler batchScheduler, FetchDataDelegate <TKey, TValue> fetch, DataLoaderOptions <TKey>?options) : base(batchScheduler, options) { _fetch = fetch ?? throw new ArgumentNullException(nameof(fetch)); }
public void ConstructorEmpty() { // act var options = new DataLoaderOptions(); // assert Assert.Null(options.Cache); Assert.True(options.Caching); Assert.Equal(1024, options.MaxBatchSize); Assert.Null(options.DiagnosticEvents); }
/// <summary> /// Initializes a new instance of the /// <see cref="DataLoaderBase{TKey, TValue}"/> class. /// </summary> /// <param name="options"> /// A configuration for <c>DataLoaders</c>. /// </param> /// <param name="cache"> /// A cache instance for <c>Tasks</c>. /// </param> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="options"/> is <c>null</c>. /// </exception> /// <exception cref="ArgumentNullException"> /// Throws if <paramref name="cache"/> is <c>null</c>. /// </exception> protected DataLoaderBase(DataLoaderOptions <TKey> options, ITaskCache <TValue> cache) { _options = options ?? throw new ArgumentNullException(nameof(options)); _buffer = new TaskCompletionBuffer <TKey, TValue>(); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _cacheKeyResolver = _options.CacheKeyResolver ?? ((TKey key) => key); StartAsyncBackgroundDispatching(); }
public void ConstructorBFetchNull() { // arrange FetchDataDelegate <string, string> fetch = null; var options = new DataLoaderOptions <string>(); // act Action verify = () => new DataLoader <string, string>(options, fetch); // assert Assert.Throws <ArgumentNullException>("fetch", verify); }
public void DispatchAsyncNoException() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>(); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); // act Action verify = () => loader.DispatchAsync(); // assert Assert.Null(Record.Exception(verify)); }
public void LoadCollectionNoException() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>("Bar"); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); // act Action verify = () => loader.LoadAsync(new List <string>()); // assert Assert.Null(Record.Exception(verify)); }
public void SetNoException() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>(); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); var key = "Foo"; string value = null; // act Action verify = () => loader.Set(key, value); // assert Assert.Null(Record.Exception(verify)); }
public void SetKeyNull() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>(); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); string key = null; var value = "Bar"; // act Action verify = () => loader.Set(key, value); // assert Assert.Throws <ArgumentNullException>("key", verify); }
public void ConstructorBOptionsNull() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); DataLoaderOptions <string> options = null; // act Action verify = () => new DataLoader <string, string>(options, fetch); // assert Assert.Throws <ArgumentNullException>("options", verify); }
public void ClearNoException() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); // act Action verify = () => loader.Clear(); // assert Assert.Null(Record.Exception(verify)); }
public void ConstructorEmpty() { // act var options = new DataLoaderOptions <string>(); // assert Assert.False(options.AutoDispatching); Assert.True(options.Batching); Assert.Equal(TimeSpan.FromMilliseconds(50), options.BatchRequestDelay); Assert.Null(options.CacheKeyResolver); Assert.Equal(1000, options.CacheSize); Assert.True(options.Caching); Assert.Equal(0, options.MaxBatchSize); Assert.Equal(TimeSpan.Zero, options.SlidingExpiration); }
public async Task ExecuteBatchRequest() { var listener = new DispatchingListener(); var observer = new DispatchingObserver(listener); using (DiagnosticListener.AllListeners.Subscribe(observer)) { // arrange FetchDataDelegate <string, string> fetch = async keys => { var error = new Exception("Quux"); return(await Task.FromResult(new[] { Result <string> .Reject(error) }).ConfigureAwait(false)); }; var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); // act try { await loader.LoadAsync("Foo").ConfigureAwait(false); } catch { } // assert Assert.Collection(listener.Keys, (key) => Assert.Equal("Foo", key)); Assert.Collection(listener.Values, (item) => { Assert.Equal("Foo", item.Key); Assert.True(item.Value.IsError); Assert.Equal("Quux", item.Value.Error.Message); }); Assert.Collection(listener.Errors, (item) => { Assert.Equal("Foo", item.Key); Assert.Equal("Quux", item.Value.Message); }); } }
public void IDataLoaderLoadSingleNoException() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>("Bar"); var options = new DataLoaderOptions <string>(); IDataLoader loader = new DataLoader <string, string>( options, fetch); var key = "Foo"; // act Action verify = () => loader.LoadAsync(key); // assert Assert.Null(Record.Exception(verify)); }
public async Task DispatchAsyncNoException() { // arrange FetchDataDelegate <string, string> fetch = async keys => await Task.FromResult(new IResult <string> [0]) .ConfigureAwait(false); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); // act Func <Task> verify = () => loader.DispatchAsync(); // assert Assert.Null(await Record.ExceptionAsync(verify) .ConfigureAwait(false)); }
public void ConstructorAllProps1() { // act var options = new DataLoaderOptions { Cache = new TaskCache(1), Caching = true, MaxBatchSize = 1, DiagnosticEvents = new DataLoaderDiagnosticEventListener() }; // assert Assert.NotNull(options.Cache); Assert.True(options.Caching); Assert.Equal(1, options.MaxBatchSize); Assert.NotNull(options.DiagnosticEvents); }
public void ConstructorAllProps2() { // act var options = new DataLoaderOptions { Cache = null, Caching = false, MaxBatchSize = 10, DiagnosticEvents = null }; // assert Assert.Null(options.Cache); Assert.False(options.Caching); Assert.Equal(10, options.MaxBatchSize); Assert.Null(options.DiagnosticEvents); }
public async Task SetNewCacheEntry() { // arrange FetchDataDelegate <string, string> fetch = TestHelpers .CreateFetch <string, string>(); var options = new DataLoaderOptions <string>(); var loader = new DataLoader <string, string>(options, fetch); var key = "Foo"; var value = "Bar"; // act loader.Set(key, value); // assert var loadResult = await loader.LoadAsync(key).ConfigureAwait(false); Assert.Equal(value, loadResult); }
public void ConstructorAllProps() { // act var options = new DataLoaderOptions <string> { Batch = false, Cache = new TaskCache(1), CacheKeyResolver = k => k, CacheSize = 1, Caching = false, MaxBatchSize = 1 }; // assert options.MatchSnapshot(matchOptions => matchOptions .Assert(fieldOption => Assert.NotNull(fieldOption.Field <object>("CacheKeyResolver")))); }