Ejemplo n.º 1
0
    public virtual async Task <IComputed <TOut> > Invoke(TIn input,
                                                         IComputed?usedBy,
                                                         ComputeContext?context,
                                                         CancellationToken cancellationToken = default)
    {
        context ??= ComputeContext.Current;

        // Read-Lock-RetryRead-Compute-Store pattern

        var result = GetExisting(input);

        if (result.TryUseExisting(context, usedBy))
        {
            return(result !);
        }

        using var @lock = await Locks.Lock(input, cancellationToken).ConfigureAwait(false);

        result = GetExisting(input);
        if (result.TryUseExisting(context, usedBy))
        {
            return(result !);
        }

        result = await Compute(input, result, cancellationToken).ConfigureAwait(false);

        result.UseNew(context, usedBy);
        return(result);
    }
Ejemplo n.º 2
0
        public virtual async Task <TOut> InvokeAndStripAsync(TIn input,
                                                             IComputed?usedBy,
                                                             ComputeContext?context,
                                                             CancellationToken cancellationToken = default)
        {
            context ??= ComputeContext.Current;

            // Read-Lock-RetryRead-Compute-Store pattern

            var result = TryGetCached(input);

            if (result.TryUseCached(context, usedBy))
            {
                return(result.Strip());
            }

            using var @lock = await Locks.LockAsync(input, cancellationToken).ConfigureAwait(false);

            result = TryGetCached(input);
            if (result.TryUseCached(context, usedBy))
            {
                return(result.Strip());
            }

            result = await ComputeAsync(input, result, cancellationToken).ConfigureAwait(false);

            result.UseNew(context, usedBy);
            return(result.Strip());
        }
Ejemplo n.º 3
0
        public virtual async Task <TOut> InvokeAndStripAsync(TIn input,
                                                             IComputed?usedBy,
                                                             ComputeContext?context,
                                                             CancellationToken cancellationToken = default)
        {
            context ??= ComputeContext.Current;
            Result <TOut> output;

            // Read-Lock-RetryRead-Compute-Store pattern

            var result = TryGetExisting(input);

            if (result.TryUseExisting(context, usedBy))
            {
                return(result.Strip());
            }

            using var @lock = await Locks.LockAsync(input, cancellationToken).ConfigureAwait(false);

            result = TryGetExisting(input);
            if (result.TryUseExisting(context, usedBy))
            {
                return(result.Strip());
            }

            result = await ComputeAsync(input, result, cancellationToken).ConfigureAwait(false);

            output = result.Output; // It can't be gone here b/c KeepAlive isn't called yet
            result.UseNew(context, usedBy);
            return(output.Value);
        }
Ejemplo n.º 4
0
        public virtual async Task <IComputed <TOut> > InvokeAsync(TIn input,
                                                                  IComputed?usedBy,
                                                                  ComputeContext?context,
                                                                  CancellationToken cancellationToken = default)
        {
            context ??= ComputeContext.Current;

            // Read-Lock-RetryRead-Compute-Store pattern

            var result = TryGetCached(input);

            if (result.TryUseCached(context, usedBy))
            {
                return(result !);
            }

            using var @lock = await Locks.LockAsync(input, cancellationToken).ConfigureAwait(false);

            result = TryGetCached(input);
            if (result.TryUseCached(context, usedBy))
            {
                return(result !);
            }

            result = await ComputeAsync(input, result, cancellationToken).ConfigureAwait(false);

            if (InvalidatedHandler != null)
            {
                result.Invalidated += InvalidatedHandler;
            }
            Register((IComputed <TIn, TOut>)result);
            result.UseNew(context, usedBy);
            return(result);
        }
Ejemplo n.º 5
0
        internal ComputeContextScope(ComputeContext context)
        {
            var current = ComputeContext.CurrentLocal;

            _previousContext = current.Value;
            current.Value    = context;
            Context          = context;
        }
Ejemplo n.º 6
0
 public static ComputeContextUseScope Use(this ComputeContext?context)
 {
     if (context != null)
     {
         return(new ComputeContextUseScope(context, false));
     }
     context = ComputeContext.CurrentLocal.Value;
     if (context != null && context.TrySetIsUsed())
     {
         return(new ComputeContextUseScope(context, true));
     }
     return(new ComputeContextUseScope(ComputeContext.Default, false));
 }
Ejemplo n.º 7
0
        public virtual async Task <IComputed <TOut> > InvokeAsync(TIn input,
                                                                  IComputed?usedBy,
                                                                  ComputeContext?context,
                                                                  CancellationToken cancellationToken = default)
        {
            using var contextUseScope = context.Use();
            context = contextUseScope.Context;

            // Read-Lock-RetryRead-Compute-Store pattern

            var result             = TryGetCached(input, usedBy);
            var resultIsConsistent = result?.IsConsistent ?? false;

            if (resultIsConsistent || (context.CallOptions & CallOptions.TryGetCached) != 0)
            {
                if ((context.CallOptions & CallOptions.Invalidate) == CallOptions.Invalidate)
                {
                    result?.Invalidate();
                }
                context.TryCaptureValue(result);
                return(result !);
            }

            using var @lock = await Locks.LockAsync(input, cancellationToken).ConfigureAwait(false);

            result             = TryGetCached(input, usedBy);
            resultIsConsistent = result?.IsConsistent ?? false;
            if (resultIsConsistent || (context.CallOptions & CallOptions.TryGetCached) != 0)
            {
                if ((context.CallOptions & CallOptions.Invalidate) == CallOptions.Invalidate)
                {
                    result?.Invalidate();
                }
                context.TryCaptureValue(result);
                return(result !);
            }

            result = await ComputeAsync(input, result, cancellationToken).ConfigureAwait(false);

            if (InvalidatedHandler != null)
            {
                result.Invalidated += InvalidatedHandler;
            }
            ((IComputedImpl?)usedBy)?.AddUsed((IComputedImpl)result);
            Register((IComputed <TIn, TOut>)result);
            context.TryCaptureValue(result);
            return(result);
        }
Ejemplo n.º 8
0
        public override async Task <T> InvokeAndStrip(
            ComputeMethodInput input, IComputed?usedBy, ComputeContext?context,
            CancellationToken cancellationToken = default)
        {
            context ??= ComputeContext.Current;
            ResultBox <T>?output;

            // Read-Lock-RetryRead-Compute-Store pattern

            var computed = TryGetExisting(input);

            if (computed != null)
            {
                output = await computed.TryUseExisting(context, usedBy, cancellationToken)
                         .ConfigureAwait(false);

                if (output != null)
                {
                    return(output.Value);
                }
            }

            using var @lock = await Locks.Lock(input, cancellationToken).ConfigureAwait(false);

            computed = TryGetExisting(input);
            if (computed != null)
            {
                output = await computed.TryUseExisting(context, usedBy, cancellationToken)
                         .ConfigureAwait(false);

                if (output != null)
                {
                    return(output.Value);
                }
            }

            computed = (IAsyncComputed <T>) await Compute(input, computed, cancellationToken)
                       .ConfigureAwait(false);

            var rOutput = computed.Output; // RenewTimeouts isn't called yet, so it's ok

            computed.UseNew(context, usedBy);
            return(rOutput !.Value);
        }
Ejemplo n.º 9
0
 Task IFunction.InvokeAndStripAsync(ComputedInput input,
                                    IComputed?usedBy,
                                    ComputeContext?context,
                                    CancellationToken cancellationToken)
 => InvokeAndStripAsync((TIn)input, usedBy, context, cancellationToken);
Ejemplo n.º 10
0
 async Task <IComputed> IFunction.InvokeAsync(ComputedInput input,
                                              IComputed?usedBy,
                                              ComputeContext?context,
                                              CancellationToken cancellationToken)
 => await InvokeAsync((TIn)input, usedBy, context, cancellationToken).ConfigureAwait(false);
Ejemplo n.º 11
0
 protected abstract Task InvokeAndStripAsync(
     ComputedInput input, IComputed?usedBy, ComputeContext?context,
     CancellationToken cancellationToken);
Ejemplo n.º 12
0
        // IFunction

        Task <IComputed> IFunction.InvokeAsync(
            ComputedInput input, IComputed?usedBy, ComputeContext?context,
            CancellationToken cancellationToken) =>
        InvokeAsync(input, usedBy, context, cancellationToken);
Ejemplo n.º 13
0
 public Task <IComputed> GetComputedAsync(IComputed?usedBy       = null,
                                          ComputeContext?context = null,
                                          CancellationToken cancellationToken = default)
 => Function.InvokeAsync(this, usedBy, context, cancellationToken);