// Two primary constructors
 public ReplicaClientComputed(ComputedOptions options, InterceptedInput input, IReplicaComputed <T> source)
     : this(source.Replica, options, input, source.Version)
 {
     ((IComputedImpl)this).AddUsed((IComputedImpl)source);
     TrySetOutput(source.Output);
     if (!source.IsConsistent())
     {
         Invalidate();
     }
 }
示例#2
0
        public override IComputed <T>?TryGetCached(InterceptedInput input)
        {
            if (!(ComputedRegistry.TryGet(input) is IReplicaClientComputed <T> computed))
            {
                return(null);
            }
            var replica = computed.Replica;

            if (replica == null || replica.UpdateError != null || replica.DisposalState != DisposalState.Active)
            {
                ComputedRegistry.Remove(computed);
                return(null);
            }
            return(computed);
        }
        public override IComputed <T>?TryGetCached(InterceptedInput input, IComputed?usedBy)
        {
            if (!(ComputedRegistry.TryGet(input) is IReplicaServiceComputed <T> computed))
            {
                return(null);
            }
            var replica = computed.Replica;

            if (replica == null || replica.UpdateError != null || replica.DisposalState != DisposalState.Active)
            {
                ComputedRegistry.Remove(computed);
                return(null);
            }
            ((IComputedImpl?)usedBy)?.AddUsed((IComputedImpl)computed);
            return(computed);
        }
 protected SwappingComputed(ComputedOptions options, InterceptedInput input, ResultBox <T> maybeOutput, LTag version, bool isConsistent)
     : base(options, input, default, version, isConsistent)
     => _maybeOutput = maybeOutput;
 public SwappingComputed(ComputedOptions options, InterceptedInput input, LTag version)
     : base(options, input, version)
 {
 }
示例#6
0
 public ReplicaClientComputed(ComputedOptions options, InterceptedInput input, Exception error, LTag version)
     : this(options, null, input, new Result <T>(default !, error), version, false)
        protected override async ValueTask <IComputed <T> > ComputeAsync(
            InterceptedInput input, IComputed <T>?existing,
            CancellationToken cancellationToken)
        {
            var                  method = input.Method;
            IReplica <T>         replica;
            IReplicaComputed <T> replicaComputed;

            // 1. Trying to update the Replica first
            if (existing is IReplicaClientComputed <T> rsc && rsc.Replica != null)
            {
                try {
                    replica         = rsc.Replica;
                    replicaComputed = (IReplicaComputed <T>) await replica.Computed
                                      .UpdateAsync(true, cancellationToken).ConfigureAwait(false);

                    return(new ReplicaClientComputed <T>(method.Options, input, replicaComputed));
                }
                catch (OperationCanceledException) {
                    if (IsLogDebugEnabled)
                    {
                        Log.LogDebug($"{nameof(ComputeAsync)}: Cancelled (1).");
                    }
                    throw;
                }
                catch (Exception e) {
                    if (IsLogDebugEnabled)
                    {
                        Log.LogError(e, $"{nameof(ComputeAsync)}: Error on Replica update.");
                    }
                }
            }

            // 2. Replica update failed, let's refresh it
            using var psiCapture = new PublicationStateInfoCapture();
            Result <T> output;

            try {
                var result = input.InvokeOriginalFunction(cancellationToken);
                if (method.ReturnsValueTask)
                {
                    var task = (ValueTask <T>)result;
                    output = Result.Value(await task.ConfigureAwait(false));
                }
                else
                {
                    var task = (Task <T>)result;
                    output = Result.Value(await task.ConfigureAwait(false));
                }
            }
            catch (OperationCanceledException) {
                if (IsLogDebugEnabled)
                {
                    Log.LogDebug($"{nameof(ComputeAsync)}: Cancelled (2).");
                }
                throw;
            }
            catch (Exception e) {
                if (IsLogDebugEnabled)
                {
                    Log.LogError(e, $"{nameof(ComputeAsync)}: Error on update.");
                }
                if (e is AggregateException ae)
                {
                    e = ae.GetFirstInnerException();
                }
                output = Result.Error <T>(e);
            }

            var psi = psiCapture.Captured;

            if (psi == null)
            {
                output = new Result <T>(default !, Errors.NoPublicationStateInfoCaptured());
示例#8
0
 public ReplicaServiceComputed(ComputedOptions options, InterceptedInput input, Exception error, LTag lTag)
     : this(options, null, input, new Result <T>(default !, error), lTag, false)
示例#9
0
 // Two primary constructors
 public ReplicaServiceComputed(ComputedOptions options, IReplicaComputed <T> source, InterceptedInput input)
     : this(options, source.Replica, input, source.LTag)
 {
     ((IComputedImpl)this).AddUsed((IComputedImpl)source);
     TrySetOutput(source.Output);
     if (!source.IsConsistent)
     {
         Invalidate();
     }
 }
示例#10
0
        protected override async ValueTask <IComputed <T> > ComputeAsync(
            InterceptedInput input, IComputed <T>?cached,
            CancellationToken cancellationToken)
        {
            var method = input.Method;

            // 1. Trying to update the Replica first
            if (cached is IReplicaServiceComputed <T> rsc && rsc.Replica != null)
            {
                try {
                    var replica  = rsc.Replica;
                    var computed = await replica.Computed
                                   .UpdateAsync(true, cancellationToken).ConfigureAwait(false);

                    var replicaComputed = (IReplicaComputed <T>)computed;
                    var output          = new ReplicaServiceComputed <T>(
                        method.Options, replicaComputed, input);
                    return(output);
                }
                catch (OperationCanceledException) {
                    if (_isLogDebugEnabled)
                    {
                        _log.LogDebug($"{nameof(ComputeAsync)}: Cancelled (1).");
                    }
                    throw;
                }
                catch (Exception e) {
                    if (_isLogDebugEnabled)
                    {
                        _log.LogError(e, $"{nameof(ComputeAsync)}: Error on Replica update.");
                    }
                }
            }

            // 2. Replica update failed, let's refresh it
            try {
                using var replicaCapture = new ReplicaCapture();
                var result = input.InvokeOriginalFunction(cancellationToken);
                if (method.ReturnsComputed)
                {
                    if (method.ReturnsValueTask)
                    {
                        var task = (ValueTask <IComputed <T> >)result;
                        await task.ConfigureAwait(false);
                    }
                    else
                    {
                        var task = (Task <IComputed <T> >)result;
                        await task.ConfigureAwait(false);
                    }
                }
                else
                {
                    if (method.ReturnsValueTask)
                    {
                        var task = (ValueTask <T>)result;
                        await task.ConfigureAwait(false);
                    }
                    else
                    {
                        var task = (Task <T>)result;
                        await task.ConfigureAwait(false);
                    }
                }
                var replica  = replicaCapture.GetCapturedReplica <T>();
                var computed = await replica.Computed
                               .UpdateAsync(true, cancellationToken).ConfigureAwait(false);

                var replicaComputed = (IReplicaComputed <T>)computed;
                var output          = new ReplicaServiceComputed <T>(
                    method.Options, replicaComputed, input);
                return(output);
            }
            catch (OperationCanceledException) {
                if (_isLogDebugEnabled)
                {
                    _log.LogDebug($"{nameof(ComputeAsync)}: Cancelled (2).");
                }
                throw;
            }
            catch (Exception e) {
                if (_isLogDebugEnabled)
                {
                    _log.LogError(e, $"{nameof(ComputeAsync)}: Error on update.");
                }
                // We need a unique LTag here, so we use a range that's supposed
                // to be unused by LTagGenerators.
                var lTag   = new LTag(LTagGenerator.Next().Value ^ (1L << 62));
                var output = new ReplicaServiceComputed <T>(
                    method.Options, null, input, new Result <T>(default !, e), lTag);
示例#11
0
 protected Computed(ComputedOptions options, InterceptedInput input, Result <T> output, LTag version, bool isConsistent = true)
     : base(options, input, output, version, isConsistent)
 {
 }