/// <inheritdoc/> protected override async Task ExecutingRequestInActionFilterAsync(ActionExecutingContext context, ActionExecutionDelegate next, string key) { var @lock = _executingLockPool.GetLock(key); if (@lock is null) { CachingDiagnostics.CannotExecutionThroughLock(key, context, Context); await Context.OnCannotExecutionThroughLock(key, context, () => next()); return; } bool gotLock = false; try { var waitTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); gotLock = await @lock.WaitAsync(Context.LockMillisecondsTimeout, context.HttpContext.RequestAborted); if (!gotLock) //没有获取到锁 { _executingLockPool.Return(@lock); await Context.OnExecutionLockTimeout(key, context, () => next()); return; } if (@lock.TryGetLocalCache(key, waitTime, out var responseCacheEntry)) { _ = WriteCacheToResponseWithInterceptorAsync(context, responseCacheEntry); @lock.Release(); _executingLockPool.Return(@lock); return; } else { context.HttpContext.Items.Add(ResponseCachingConstants.ResponseCachingExecutingLockKey, @lock); } } catch { if (gotLock) { @lock.Release(); } _executingLockPool.Return(@lock); throw; } //执行请求的后续处理逻辑 await ExecutingAndReplaceResponseStreamAsync(context, next, key); }
/// <summary> /// 执行请求 /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <param name="key"></param> /// <returns></returns> protected override async Task ExecutingRequestAsync(ResourceExecutingContext context, ResourceExecutionDelegate next, string key) { var @lock = _executingLockPool.GetLock(key); if (@lock is null) { CachingDiagnostics.CannotExecutionThroughLock(key, context, Context); await Context.OnCannotExecutionThroughLock(key, context, () => next()); return; } bool gotLock = false; try { var waitTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); gotLock = await @lock.WaitAsync(Context.LockMillisecondsTimeout, context.HttpContext.RequestAborted); if (!gotLock) //没有获取到锁 { await Context.OnExecutionLockTimeout(key, context, () => next()); return; } if (@lock.TryGetLocalCache(key, waitTime, out var responseCacheEntry)) { _ = WriteCacheToResponseWithInterceptorAsync(context, responseCacheEntry); } else { responseCacheEntry = await DumpAndCacheResponseAsync(context, next, key); if (responseCacheEntry is not null) { @lock.SetLocalCache(key, responseCacheEntry, DateTimeOffset.Now.ToUnixTimeMilliseconds() + Context.DurationMilliseconds); } } } finally { if (gotLock) { @lock.Release(); } _executingLockPool.Return(@lock); } }