|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|