Ejemplo n.º 1
0
        public async Task MemoizeAsync_CallAfterRefreshTime_RefreshOnBackground()
        {
            TimeSpan refreshTime = TimeSpan.FromMinutes(1);
            var      refreshTask = new TaskCompletionSource <Thing>();
            var      args        = new object[] { "someString" };
            string   firstValue  = "first Value";
            string   secondValue = "second Value";
            var      dataSource  = CreateDataSource(firstValue, refreshTask);

            IMemoizer memoizer = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            // fake that refreshTime has passed
            TimeFake.UtcNow += refreshTime;

            // Refresh task hasn't finished, should get old value (5)
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue); // value is not refreshed yet. it is running on background

            // Complete refresh task and verify new value
            refreshTask.SetResult(new Thing {
                Id = secondValue, Name = "seven"
            });
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(secondValue); // new value is expected now
        }
Ejemplo n.º 2
0
        public async Task MemoizeAsync_TwoCalls_RespectsCachingPolicy()
        {
            var       dataSource = CreateDataSource(5, 7);
            IMemoizer memoizer   = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy(0.05))).Id.ShouldBe(5);
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(5);
            await Task.Delay(100);

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(7);

            dataSource.Received(2).ThingifyTaskThing("someString");
        }
Ejemplo n.º 3
0
        public async Task MemoizeAsync_MultipleIdenticalCallsBeforeFirstCompletes_TeamsWithFirstCall()
        {
            var dataSource = CreateDataSource();

            dataSource.ThingifyTaskInt("someString").Returns(async i => { await Task.Delay(100); return(1); }, async i => 2);
            IMemoizer memoizer = CreateMemoizer(CreateCache());

            var task1 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());
            var task2 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());
            var task3 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());

            await Task.WhenAll(task1, task2, task3);

            dataSource.Received(1).ThingifyTaskInt("someString");
        }
Ejemplo n.º 4
0
        public async Task MemoizeAsync_TwoCalls_RespectsCachingPolicy()
        {
            string    firstValue  = "first Value";
            string    secondValue = "second Value";
            var       dataSource  = CreateDataSource(firstValue, secondValue);
            IMemoizer memoizer    = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy(1))).Id.ShouldBe(firstValue);
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy(1))).Id.ShouldBe(firstValue);
            await Task.Delay(TimeSpan.FromSeconds(2));

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy(1))).Id.ShouldBe(secondValue);

            dataSource.Received(2).ThingifyTaskThing("someString");
        }
        /// <summary>
        /// Instantiates the expression Bonsai serializer.
        /// </summary>
        /// <param name="version">Version of Bonsai to use.</param>
        /// <param name="liftMemoizer">The function memoizer to use for converting types to object serializers.</param>
        /// <param name="reduceMemoizer">The function memoizer to use for converting types to object deserializers.</param>
        public BonsaiExpressionSerializer(Version version, IMemoizer liftMemoizer, IMemoizer reduceMemoizer)
        {
            _version = version;

            _serializeConstant   = liftMemoizer?.Memoize <Func <Type, Func <object, Json.Expression> > >(GetConstantSerializer);
            _deserializeConstant = reduceMemoizer?.Memoize <Func <Type, Func <Json.Expression, object> > >(GetConstantDeserializer);
        }
Ejemplo n.º 6
0
        public void MemoizeAsync_MultipleIdenticalCallsBeforeFirstFails_TeamsWithFirstCall()
        {
            var dataSource = Substitute.For <IThingFrobber>();

            dataSource.ThingifyTaskInt("someString").Returns <Task <int> >(async i => { await Task.Delay(100); throw new InvalidOperationException(); }, async i => 2);
            IMemoizer memoizer = CreateMemoizer(CreateCache());

            var task1 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());
            var task2 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());
            var task3 = (Task <int>)memoizer.Memoize(dataSource, ThingifyTaskInt, new object[] { "someString" }, GetPolicy());

            task1.ShouldThrow <InvalidOperationException>();
            task2.ShouldThrow <InvalidOperationException>();
            task3.ShouldThrow <InvalidOperationException>();

            dataSource.Received(1).ThingifyTaskInt("someString");
        }
Ejemplo n.º 7
0
        public async Task MemoizeAsync_CallsWithDifferentParams_UsesSeparateCacheSlots()
        {
            var dataSource = CreateDataSource(5);

            dataSource.ThingifyTaskThing("otherString").Returns(Task.FromResult(new Thing {
                Id = 7
            }));
            IMemoizer memoizer = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(5);
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "otherString" }, GetPolicy())).Id.ShouldBe(7);

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "someString" }, GetPolicy())).Id.ShouldBe(5);
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, new object[] { "otherString" }, GetPolicy())).Id.ShouldBe(7);

            dataSource.Received(1).ThingifyTaskThing("someString");
            dataSource.Received(1).ThingifyTaskThing("otherString");
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Creates a new evaluator factory using the specified <paramref name="memoizer"/> to cache the
        /// compiled delegates created by <see cref="ShouldCache(MemberInfo)"/>. Note that the member objects
        /// and the evaluator delegates can be held alive by the cache created through the memoizer. See
        /// other constructor overloads for alternative options, if needed.
        /// </summary>
        /// <param name="memoizer">The memoizer to use for caching <see cref="GetEvaluator(MemberInfo)"/> calls.</param>
        public MemoizingEvaluatorFactory(IMemoizer memoizer)
        {
            if (memoizer == null)
            {
                throw new ArgumentNullException(nameof(memoizer));
            }

            _getEvaluator = memoizer.Memoize <MemberInfo, Delegate>(base.GetEvaluator);
        }
Ejemplo n.º 9
0
            public MemberInfoSlimHashingVisitor(ExpressionSlimHasher parent, TypeSlimHashingVisitor typeHasher, IMemoizer memoizer)
            {
                _parent     = parent;
                _typeHasher = typeHasher;

                // NB: We use reference equality for memoization in order to prevent the computation of another
                //     hash code through the overridden GetHashCode implementation on MemberInfoSlim. The use
                //     of reference equality is very effective within expressions and for reflection objects that
                //     come from a shared reflection context where reference-equal objects are returned.

                _visitCache = memoizer.Memoize(base.Visit, MemoizationOptions.None, ReferenceEqualityComparer <MemberInfoSlim> .Instance);
            }
Ejemplo n.º 10
0
        public async Task MemoizeAsync_BackgroundRefreshFails_LastGoodValueStillReturned()
        {
            TimeSpan refreshTime = TimeSpan.FromMinutes(1);
            var      refreshTask = new TaskCompletionSource <Thing>();
            var      args        = new object[] { "someString" };
            var      dataSource  = CreateDataSource(5, refreshTask);

            IMemoizer memoizer = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5);

            // fake that refreshTime has passed
            TimeFake.UtcNow += refreshTime;

            // Refresh task hasn't finished, should get old value (5)
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // value is not refreshed yet. it is running on background

            // Complete refresh task and verify new value
            refreshTask.SetException(new Exception("Boo!!"));
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(5); // new value is expected now
        }
        /// <summary>
        /// Memoizes the specified <paramref name="function"/> using the specified <paramref name="memoizer"/>.
        /// </summary>
        /// <typeparam name="T">Type of the function argument.</typeparam>
        /// <typeparam name="TResult">Type of the function result.</typeparam>
        /// <param name="memoizer">The memoizer used to memoize the function.</param>
        /// <param name="function">The function to memoize.</param>
        /// <param name="options">Flags to influence the memoization behavior.</param>
        /// <returns>A memoized delegate containing the memoized function and providing access to the memoization cache.</returns>
        public static IMemoizedDelegate <Func <T, TResult> > Memoize <T, TResult>(this IMemoizer memoizer, Func <T, TResult> function, MemoizationOptions options = MemoizationOptions.None)
        {
            if (memoizer == null)
            {
                throw new ArgumentNullException(nameof(memoizer));
            }
            if (function == null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            return(memoizer.Memoize <T, TResult>(function, options, comparer: null));
        }
        /// <summary>
        /// Memoizes the specified <paramref name="function"/> using the specified <paramref name="memoizer"/>.
        /// </summary>
        /// <typeparam name="TResult">Type of the function result.</typeparam>
        /// <param name="memoizer">The memoizer used to memoize the function.</param>
        /// <param name="function">The function to memoize.</param>
        /// <param name="options">Flags to influence the memoization behavior.</param>
        /// <returns>A memoized delegate containing the memoized function and providing access to the memoization cache.</returns>
        public static IMemoizedDelegate <Func <TResult> > Memoize <TResult>(this IMemoizer memoizer, Func <TResult> function, MemoizationOptions options = MemoizationOptions.None)
        {
            if (memoizer == null)
            {
                throw new ArgumentNullException(nameof(memoizer));
            }
            if (function == null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            var res = memoizer.Memoize <object, TResult>(_ => function(), options, comparer: null);
            var del = res.Delegate;

            return(new MemoizedDelegate <Func <TResult> >(() => del(null), res.Cache));
        }
Ejemplo n.º 13
0
        public async Task MemoizeAsync_BackgroundRefreshFails_NextRequestAfterDelayTriggersRefresh()
        {
            TimeSpan refreshTime        = TimeSpan.FromMinutes(1);
            TimeSpan failedRefreshDelay = TimeSpan.FromSeconds(1);
            var      refreshTask        = new TaskCompletionSource <Thing>();
            var      args        = new object[] { "someString" };
            string   firstValue  = "first Value";
            string   secondValue = "second Value";
            var      dataSource  = CreateDataSource(firstValue, refreshTask, secondValue);

            IMemoizer memoizer = CreateMemoizer(CreateCache());

            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            // fake that refreshTime has passed
            TimeFake.UtcNow += refreshTime;

            // Should trigger refresh task that won't be completed yet, should get old value (5)
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            // Fail the first refresh task and verify old value (5) still returned.
            // FailedRefreshDelay hasn't passed so shouldn't trigger refresh.
            refreshTask.SetException(new Exception("Boo!!"));
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            TimeFake.UtcNow += TimeSpan.FromMilliseconds(failedRefreshDelay.TotalMilliseconds * 0.7);

            // FailedRefreshDelay still hasn't passed so shouldn't trigger refresh.
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            TimeFake.UtcNow += TimeSpan.FromMilliseconds(failedRefreshDelay.TotalMilliseconds * 0.7);

            // FailedRefreshDelay passed so should trigger refresh.
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(firstValue);

            // Second refresh should succeed, should get new value (7);
            (await(Task <Thing>) memoizer.Memoize(dataSource, ThingifyTaskThing, args, GetPolicy())).Id.ShouldBe(secondValue);
        }
Ejemplo n.º 14
0
 private async Task <Revocable <Thing> > CallWithMemoize(IMemoizer memoizer, IThingFrobber dataSource)
 {
     return(await(Task <Revocable <Thing> >) memoizer.Memoize(dataSource, ThingifyTaskRevokabkle, new object[] { "someString" }, GetPolicy()));
 }
Ejemplo n.º 15
0
 public static U Memoize <U>(this IMemoizer memo, Func <U> f) where U : class
 {
     return(memo.Memoize(memo, x => f()));
 }