|
using System; |
|
using System.Collections.Generic; |
|
using System.Diagnostics.CodeAnalysis; |
|
using System.Runtime.CompilerServices; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using Microsoft.AspNetCore.Http; |
|
using Microsoft.AspNetCore.Session; |
|
using Microsoft.Extensions.Logging; |
|
using Microsoft.Extensions.Options; |
|
|
|
namespace MyCompany.AspNetCore.Session |
|
{ |
|
public class OurDistributedSession |
|
: ISession |
|
{ |
|
private readonly ILogger<OurDistributedSession> _logger; |
|
private readonly OurDistributedSessionSettings _settings; |
|
private readonly DistributedSession _session; |
|
private bool _isLoaded = false; |
|
|
|
public OurDistributedSession( |
|
ILogger<OurDistributedSession> logger, |
|
IOptionsSnapshot<OurDistributedSessionSettings> settings, |
|
DistributedSession session) |
|
{ |
|
_logger = logger; |
|
_settings = settings.Value; |
|
_session = session; |
|
} |
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] // hoping this will get us the callerMemberName properly |
|
private void CheckIfLoaded( |
|
string key = "unknown", |
|
[CallerMemberName] string? callerMemberName = null) |
|
{ |
|
if (_isLoaded) |
|
{ |
|
return; |
|
} |
|
|
|
switch (_settings.Mode) |
|
{ |
|
case OurDistributedSessionMode.AllowSyncLoad: |
|
return; |
|
case OurDistributedSessionMode.AllowSyncLoadButLogWarning: |
|
_logger.LogWarning( |
|
"Session will be loaded synchronously. Caller: {callerMemberName} Key: {key}", |
|
callerMemberName ?? "unknown", |
|
key); |
|
return; |
|
case OurDistributedSessionMode.DontAllowSyncLoad: |
|
callerMemberName ??= "unknown"; |
|
throw new Exception( |
|
$"Session would've been loaded synchronously. Caller: {callerMemberName} Key: {key}"); |
|
} |
|
} |
|
|
|
public bool IsAvailable |
|
{ |
|
get |
|
{ |
|
CheckIfLoaded("is available get"); |
|
var isAvailable = _session.IsAvailable; |
|
_isLoaded = true; |
|
return isAvailable; |
|
} |
|
} |
|
|
|
public string Id |
|
{ |
|
get |
|
{ |
|
CheckIfLoaded("id get"); |
|
var id = _session.Id; |
|
_isLoaded = true; |
|
return id; |
|
} |
|
} |
|
|
|
public IEnumerable<string> Keys |
|
{ |
|
get |
|
{ |
|
CheckIfLoaded("keys enumeration"); |
|
var keys = _session.Keys; |
|
_isLoaded = true; |
|
return keys; |
|
} |
|
} |
|
|
|
public void Clear() |
|
{ |
|
CheckIfLoaded("clear operation"); |
|
_session.Clear(); |
|
_isLoaded = true; |
|
} |
|
|
|
public async Task CommitAsync(CancellationToken cancellationToken = default) |
|
{ |
|
CheckIfLoaded("commit operation"); |
|
await _session.CommitAsync(cancellationToken); |
|
_isLoaded = true; |
|
} |
|
|
|
public async Task LoadAsync(CancellationToken cancellationToken = default) |
|
{ |
|
await _session.LoadAsync(cancellationToken); |
|
_isLoaded = true; |
|
} |
|
|
|
public void Remove(string key) |
|
{ |
|
CheckIfLoaded(key); |
|
_session.Remove(key); |
|
_isLoaded = true; |
|
} |
|
|
|
public void Set(string key, byte[] value) |
|
{ |
|
if (value == null) |
|
{ |
|
throw new ArgumentNullException(nameof(value)); |
|
} |
|
|
|
CheckIfLoaded(key); |
|
_session.Set(key, value); |
|
_isLoaded = true; |
|
} |
|
|
|
public bool TryGetValue(string key, [NotNullWhen(true)] out byte[]? value) |
|
{ |
|
CheckIfLoaded(key); |
|
var result = _session.TryGetValue(key, out value); |
|
_isLoaded = true; |
|
return result; |
|
} |
|
} |
|
} |