#167 Add cancellation tokens and defualt timeouts for Load/CommitAsync.
This commit is contained in:
parent
6f4f34a0bf
commit
1a1e4c309f
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
@ -24,6 +25,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
private readonly IDistributedCache _cache;
|
private readonly IDistributedCache _cache;
|
||||||
private readonly string _sessionKey;
|
private readonly string _sessionKey;
|
||||||
private readonly TimeSpan _idleTimeout;
|
private readonly TimeSpan _idleTimeout;
|
||||||
|
private readonly TimeSpan _ioTimeout;
|
||||||
private readonly Func<bool> _tryEstablishSession;
|
private readonly Func<bool> _tryEstablishSession;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private IDictionary<EncodedKey, byte[]> _store;
|
private IDictionary<EncodedKey, byte[]> _store;
|
||||||
|
|
@ -38,6 +40,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
IDistributedCache cache,
|
IDistributedCache cache,
|
||||||
string sessionKey,
|
string sessionKey,
|
||||||
TimeSpan idleTimeout,
|
TimeSpan idleTimeout,
|
||||||
|
TimeSpan ioTimeout,
|
||||||
Func<bool> tryEstablishSession,
|
Func<bool> tryEstablishSession,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
bool isNewSessionKey)
|
bool isNewSessionKey)
|
||||||
|
|
@ -65,6 +68,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
_sessionKey = sessionKey;
|
_sessionKey = sessionKey;
|
||||||
_idleTimeout = idleTimeout;
|
_idleTimeout = idleTimeout;
|
||||||
|
_ioTimeout = ioTimeout;
|
||||||
_tryEstablishSession = tryEstablishSession;
|
_tryEstablishSession = tryEstablishSession;
|
||||||
_store = new Dictionary<EncodedKey, byte[]>();
|
_store = new Dictionary<EncodedKey, byte[]>();
|
||||||
_logger = loggerFactory.CreateLogger<DistributedSession>();
|
_logger = loggerFactory.CreateLogger<DistributedSession>();
|
||||||
|
|
@ -194,58 +198,68 @@ namespace Microsoft.AspNetCore.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will throw if called directly and a failure occurs. The user is expected to handle the failures.
|
// This will throw if called directly and a failure occurs. The user is expected to handle the failures.
|
||||||
public async Task LoadAsync()
|
public async Task LoadAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
if (!_loaded)
|
if (!_loaded)
|
||||||
{
|
{
|
||||||
var data = await _cache.GetAsync(_sessionKey);
|
using (var timeout = new CancellationTokenSource(_ioTimeout))
|
||||||
if (data != null)
|
|
||||||
{
|
{
|
||||||
Deserialize(new MemoryStream(data));
|
var cts = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancellationToken);
|
||||||
}
|
var data = await _cache.GetAsync(_sessionKey, cts.Token);
|
||||||
else if (!_isNewSessionKey)
|
if (data != null)
|
||||||
{
|
{
|
||||||
_logger.AccessingExpiredSession(_sessionKey);
|
Deserialize(new MemoryStream(data));
|
||||||
|
}
|
||||||
|
else if (!_isNewSessionKey)
|
||||||
|
{
|
||||||
|
_logger.AccessingExpiredSession(_sessionKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_isAvailable = true;
|
_isAvailable = true;
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CommitAsync()
|
public async Task CommitAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
if (_isModified)
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
using (var timeout = new CancellationTokenSource(_ioTimeout))
|
||||||
{
|
{
|
||||||
if (_logger.IsEnabled(LogLevel.Information))
|
var cts = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancellationToken);
|
||||||
|
if (_isModified)
|
||||||
{
|
{
|
||||||
try
|
if (_logger.IsEnabled(LogLevel.Information))
|
||||||
{
|
{
|
||||||
var data = await _cache.GetAsync(_sessionKey);
|
try
|
||||||
if (data == null)
|
|
||||||
{
|
{
|
||||||
_logger.SessionStarted(_sessionKey, Id);
|
var data = await _cache.GetAsync(_sessionKey, cts.Token);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
_logger.SessionStarted(_sessionKey, Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.SessionCacheReadException(_sessionKey, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
|
||||||
{
|
var stream = new MemoryStream();
|
||||||
_logger.SessionCacheReadException(_sessionKey, exception);
|
Serialize(stream);
|
||||||
}
|
|
||||||
|
await _cache.SetAsync(
|
||||||
|
_sessionKey,
|
||||||
|
stream.ToArray(),
|
||||||
|
new DistributedCacheEntryOptions().SetSlidingExpiration(_idleTimeout),
|
||||||
|
cts.Token);
|
||||||
|
_isModified = false;
|
||||||
|
_logger.SessionStored(_sessionKey, Id, _store.Count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _cache.RefreshAsync(_sessionKey, cts.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stream = new MemoryStream();
|
|
||||||
Serialize(stream);
|
|
||||||
|
|
||||||
await _cache.SetAsync(
|
|
||||||
_sessionKey,
|
|
||||||
stream.ToArray(),
|
|
||||||
new DistributedCacheEntryOptions().SetSlidingExpiration(_idleTimeout));
|
|
||||||
|
|
||||||
_isModified = false;
|
|
||||||
_logger.SessionStored(_sessionKey, Id, _store.Count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _cache.RefreshAsync(_sessionKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISession Create(string sessionKey, TimeSpan idleTimeout, Func<bool> tryEstablishSession, bool isNewSessionKey)
|
public ISession Create(string sessionKey, TimeSpan idleTimeout, TimeSpan ioTimeout, Func<bool> tryEstablishSession, bool isNewSessionKey)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(sessionKey))
|
if (string.IsNullOrEmpty(sessionKey))
|
||||||
{
|
{
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
throw new ArgumentNullException(nameof(tryEstablishSession));
|
throw new ArgumentNullException(nameof(tryEstablishSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DistributedSession(_cache, sessionKey, idleTimeout, tryEstablishSession, _loggerFactory, isNewSessionKey);
|
return new DistributedSession(_cache, sessionKey, idleTimeout, ioTimeout, tryEstablishSession, _loggerFactory, isNewSessionKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,6 @@ namespace Microsoft.AspNetCore.Session
|
||||||
{
|
{
|
||||||
public interface ISessionStore
|
public interface ISessionStore
|
||||||
{
|
{
|
||||||
ISession Create(string sessionKey, TimeSpan idleTimeout, Func<bool> tryEstablishSession, bool isNewSessionKey);
|
ISession Create(string sessionKey, TimeSpan idleTimeout, TimeSpan ioTimeout, Func<bool> tryEstablishSession, bool isNewSessionKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
|
@ -98,7 +99,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
var feature = new SessionFeature();
|
var feature = new SessionFeature();
|
||||||
feature.Session = _sessionStore.Create(sessionKey, _options.IdleTimeout, tryEstablishSession, isNewSessionKey);
|
feature.Session = _sessionStore.Create(sessionKey, _options.IdleTimeout, _options.IOTimeout, tryEstablishSession, isNewSessionKey);
|
||||||
context.Features.Set<ISessionFeature>(feature);
|
context.Features.Set<ISessionFeature>(feature);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -113,7 +114,7 @@ namespace Microsoft.AspNetCore.Session
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await feature.Session.CommitAsync();
|
await feature.Session.CommitAsync(context.RequestAborted);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Session;
|
using Microsoft.AspNetCore.Session;
|
||||||
|
|
||||||
|
|
@ -35,6 +36,12 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromMinutes(20);
|
public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromMinutes(20);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximim amount of time allowed to load a session from the store or to commit it back to the store.
|
||||||
|
/// Note this may only apply to asynchronous operations. This timeout can be disabled using <see cref="Timeout.InfiniteTimeSpan"/>.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan IOTimeout { get; set; } = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
#region Obsolete API
|
#region Obsolete API
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>
|
/// <para>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"TypeId": "public interface Microsoft.AspNetCore.Session.ISessionStore",
|
||||||
|
"MemberId": "Microsoft.AspNetCore.Http.ISession Create(System.String sessionKey, System.TimeSpan idleTimeout, System.Func<System.Boolean> tryEstablishSession, System.Boolean isNewSessionKey)",
|
||||||
|
"Kind": "Removal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TypeId": "public class Microsoft.AspNetCore.Session.DistributedSession : Microsoft.AspNetCore.Http.ISession",
|
||||||
|
"MemberId": "public .ctor(Microsoft.Extensions.Caching.Distributed.IDistributedCache cache, System.String sessionKey, System.TimeSpan idleTimeout, System.Func<System.Boolean> tryEstablishSession, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.Boolean isNewSessionKey)",
|
||||||
|
"Kind": "Removal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TypeId": "public class Microsoft.AspNetCore.Session.DistributedSession : Microsoft.AspNetCore.Http.ISession",
|
||||||
|
"MemberId": "public System.Threading.Tasks.Task CommitAsync()",
|
||||||
|
"Kind": "Removal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TypeId": "public class Microsoft.AspNetCore.Session.DistributedSession : Microsoft.AspNetCore.Http.ISession",
|
||||||
|
"MemberId": "public System.Threading.Tasks.Task LoadAsync()",
|
||||||
|
"Kind": "Removal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TypeId": "public class Microsoft.AspNetCore.Session.DistributedSessionStore : Microsoft.AspNetCore.Session.ISessionStore",
|
||||||
|
"MemberId": "public Microsoft.AspNetCore.Http.ISession Create(System.String sessionKey, System.TimeSpan idleTimeout, System.Func<System.Boolean> tryEstablishSession, System.Boolean isNewSessionKey)",
|
||||||
|
"Kind": "Removal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TypeId": "public interface Microsoft.AspNetCore.Session.ISessionStore",
|
||||||
|
"MemberId": "Microsoft.AspNetCore.Http.ISession Create(System.String sessionKey, System.TimeSpan idleTimeout, System.TimeSpan ioTimeout, System.Func<System.Boolean> tryEstablishSession, System.Boolean isNewSessionKey)",
|
||||||
|
"Kind": "Addition"
|
||||||
|
}
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue