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); }
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()); }
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); }
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); }
internal ComputeContextScope(ComputeContext context) { var current = ComputeContext.CurrentLocal; _previousContext = current.Value; current.Value = context; Context = context; }
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)); }
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); }
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); }
Task IFunction.InvokeAndStripAsync(ComputedInput input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken) => InvokeAndStripAsync((TIn)input, usedBy, context, cancellationToken);
async Task <IComputed> IFunction.InvokeAsync(ComputedInput input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken) => await InvokeAsync((TIn)input, usedBy, context, cancellationToken).ConfigureAwait(false);
protected abstract Task InvokeAndStripAsync( ComputedInput input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken);
// IFunction Task <IComputed> IFunction.InvokeAsync( ComputedInput input, IComputed?usedBy, ComputeContext?context, CancellationToken cancellationToken) => InvokeAsync(input, usedBy, context, cancellationToken);
public Task <IComputed> GetComputedAsync(IComputed?usedBy = null, ComputeContext?context = null, CancellationToken cancellationToken = default) => Function.InvokeAsync(this, usedBy, context, cancellationToken);