You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Framework/Connected.Caching/CachingService.cs

151 lines
3.4 KiB

2 years ago
using System.Collections.Immutable;
using Connected.Caching.Net;
using Connected.Net.Server;
namespace Connected.Caching;
internal sealed class CachingService : MemoryCache, ICachingService, IDisposable, IAsyncDisposable
{
public CachingService(IEndpointServer server, CacheServer state, CacheServerConnection backplaneClient)
{
if (server is null)
throw new ArgumentException(null, nameof(server));
if (state is null)
throw new ArgumentException(null, nameof(state));
BackplaneClient = backplaneClient;
Server = server;
BackplaneServer = state;
server.Changed += OnServerChanged;
server.Initialized += OnServerInitialized;
BackplaneServer.Received += OnReceived;
BackplaneClient.Received += OnReceived;
}
private CacheServerConnection BackplaneClient { get; set; }
private CacheServer BackplaneServer { get; }
private IEndpointServer Server { get; }
private async void OnServerInitialized(object? sender, EventArgs e)
{
await Initialize();
}
public async Task Initialize()
{
await BackplaneClient.Disconnect();
try
{
if (!await Server.IsServer())
{
await BackplaneClient.Initialize(Server.ServerUrl);
await BackplaneClient.Connect();
}
}
catch
{
// Server probably not initalized yet
}
}
private async void OnReceived(object? sender, CacheNotificationArgs e)
{
if (string.Equals(e.Method, nameof(Clear), StringComparison.Ordinal))
ClearCore(e.Key);
else if (string.Equals(e.Method, nameof(Remove), StringComparison.Ordinal))
{
if (e.Ids is not null && e.Ids.Any())
{
foreach (var id in e.Ids)
RemoveCore(e.Key, id);
}
}
else if (string.Equals(e.Method, nameof(Invalidate), StringComparison.Ordinal))
{
if (e.Ids is not null && e.Ids.Any())
{
foreach (var id in e.Ids)
await InvalidateCore(e.Key, id, true);
}
}
}
private async void OnServerChanged(object? sender, ServerChangedArgs e)
{
await Initialize();
}
public override async Task Clear(string key)
{
await base.Clear(key);
var args = new CacheNotificationArgs(nameof(Clear)) { Key = key };
if (await Server.IsServer())
await BackplaneServer.Send(args);
else
await BackplaneClient.Notify(nameof(Clear), args);
}
protected internal override async Task OnInvalidating(CacheEventArgs e)
{
var args = new CacheNotificationArgs(nameof(Invalidate))
{
Ids = new List<string> { e.Id },
Key = e.Key
};
if (await Server.IsServer())
await BackplaneServer.Send(args);
else
await BackplaneClient.Notify(nameof(Invalidate), args);
}
protected override async Task OnRemove(string key, ImmutableList<string> ids)
{
await base.OnRemove(key, ids);
var args = new CacheNotificationArgs(nameof(Remove))
{
Ids = ids.ToList(),
Key = key
};
if (await Server.IsServer())
await BackplaneServer.Send(args);
else
await BackplaneClient.Notify(nameof(Remove), args);
}
protected override async Task OnRemove(string key, object? id)
{
await base.OnRemove(key, id);
var ids = new List<string>();
if (id is not null)
ids.Add(id.ToString());
await OnRemove(key, ids.ToImmutableList());
}
public async ValueTask DisposeAsync()
{
Server.Changed -= OnServerChanged;
Server.Initialized -= OnServerInitialized;
}
protected override void OnDisposing(bool disposing)
{
Server.Changed -= OnServerChanged;
Server.Initialized -= OnServerInitialized;
base.OnDisposing(disposing);
}
}