sync CommunityServer and AppServer cache via redis

This commit is contained in:
Alexey Bannov 2021-12-30 18:09:20 +03:00
parent 04ff8d38dc
commit a7dc8c7dfd
3 changed files with 23 additions and 55 deletions

View File

@ -16,8 +16,6 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using Google.Protobuf;
@ -29,9 +27,7 @@ namespace ASC.Common.Caching;
[Singletone]
public class RedisCache<T> : ICacheNotify<T> where T : IMessage<T>, new()
{
private readonly string CacheId = Guid.NewGuid().ToString();
private readonly IRedisDatabase _redis;
private readonly ConcurrentDictionary<Type, ConcurrentBag<Action<object, CacheNotifyAction>>> actions = new ConcurrentDictionary<Type, ConcurrentBag<Action<object, CacheNotifyAction>>>();
public RedisCache(IRedisCacheClient redisCacheClient)
{
@ -40,65 +36,38 @@ public class RedisCache<T> : ICacheNotify<T> where T : IMessage<T>, new()
public void Publish(T obj, CacheNotifyAction action)
{
Task.Run(() => _redis.PublishAsync("asc:channel:" + typeof(T).FullName, new RedisCachePubSubItem<T>() { CacheId = CacheId, Object = obj, Action = action }))
Task.Run(() => _redis.PublishAsync(GetChannelName(action), new RedisCachePubSubItem<T>() { Object = obj, Action = action }))
.GetAwaiter()
.GetResult();
ConcurrentBag<Action<object, CacheNotifyAction>> onchange;
actions.TryGetValue(typeof(T), out onchange);
if (onchange != null)
{
onchange.ToList().ForEach(r => r(obj, action));
}
}
public void Subscribe(Action<T> onchange, CacheNotifyAction action)
{
Task.Run(() => _redis.SubscribeAsync<RedisCachePubSubItem<T>>("asc:channel:" + typeof(T).FullName, (i) =>
Task.Run(() => _redis.SubscribeAsync<RedisCachePubSubItem<T>>(GetChannelName(action), (i) =>
{
if (i.CacheId != CacheId)
{
onchange(i.Object);
}
onchange(i.Object);
return Task.FromResult(true);
})).GetAwaiter()
.GetResult();
if (onchange != null)
{
Action<object, CacheNotifyAction> _action = (o, a) => onchange((T)o);
actions.AddOrUpdate(typeof(T),
new ConcurrentBag<Action<object, CacheNotifyAction>> { _action },
(type, bag) =>
{
bag.Add(_action);
return bag;
});
}
else
{
ConcurrentBag<Action<object, CacheNotifyAction>> removed;
actions.TryRemove(typeof(T), out removed);
}
}
public void Unsubscribe(CacheNotifyAction action)
{
Task.Run(() => _redis.UnsubscribeAsync<RedisCachePubSubItem<T>>("asc:channel:" + typeof(T).FullName, (i) =>
Task.Run(() => _redis.UnsubscribeAsync<RedisCachePubSubItem<T>>(GetChannelName(action), (i) =>
{
return Task.FromResult(true);
})).GetAwaiter()
.GetResult();
}
private string GetChannelName(CacheNotifyAction cacheNotifyAction)
{
return $"asc:channel:{cacheNotifyAction}:{typeof(T).FullName}".ToLower();
}
class RedisCachePubSubItem<T0>
{
public string CacheId { get; set; }
public T0 Object { get; set; }
public CacheNotifyAction Action { get; set; }

View File

@ -1,7 +1,8 @@
{
"Redis": {
"Ssl": false,
"ConnectTimeout": 60000,
"ConnectTimeout": 5000,
"SyncTimeout": 60000,
"ConnectRetry": 2,
"Database": 0,
"Hosts": [

View File

@ -153,19 +153,19 @@ namespace ASC.Web.Core.Users
return isLoaded ? TenantDiskCache.Add(tenantId) : TenantDiskCache.Remove(tenantId);
}
public void ClearCache(Guid userID)
public void ClearCache(Guid userID, int tenantId)
{
if (CacheNotify != null)
{
CacheNotify.Publish(new UserPhotoManagerCacheItem { UserID = userID.ToString() }, CacheNotifyAction.Remove);
CacheNotify.Publish(new UserPhotoManagerCacheItem { UserID = userID.ToString(), TenantId = tenantId }, CacheNotifyAction.Remove);
}
}
public void AddToCache(Guid userID, Size size, string fileName)
public void AddToCache(Guid userID, Size size, string fileName, int tenantId)
{
if (CacheNotify != null)
{
CacheNotify.Publish(new UserPhotoManagerCacheItem { UserID = userID.ToString(), Size = UserPhotoManager.ToCache(size), FileName = fileName }, CacheNotifyAction.InsertOrUpdate);
CacheNotify.Publish(new UserPhotoManagerCacheItem { UserID = userID.ToString(), Size = UserPhotoManager.ToCache(size), FileName = fileName, TenantId = tenantId }, CacheNotifyAction.InsertOrUpdate);
}
}
@ -326,8 +326,6 @@ namespace ASC.Web.Core.Users
return defaultRetinaPhotoURL ??= GetDefaultPhotoAbsoluteWebPath(RetinaFotoSize);
}
public static Size OriginalFotoSize { get; } = new Size(1280, 1280);
public static Size RetinaFotoSize { get; } = new Size(360, 360);
@ -375,7 +373,7 @@ namespace ASC.Web.Core.Users
photoUrl = SaveOrUpdatePhoto(userID, data, -1, new Size(-1, -1), false, out fileName);
}
UserPhotoManagerCache.AddToCache(userID, Size.Empty, fileName);
UserPhotoManagerCache.AddToCache(userID, Size.Empty, fileName, tenant.TenantId);
return photoUrl;
}
@ -422,7 +420,7 @@ namespace ASC.Web.Core.Users
//empty photo. cache default
var photoUrl = GetDefaultPhotoAbsoluteWebPath(size);
UserPhotoManagerCache.AddToCache(userID, size, "default");
UserPhotoManagerCache.AddToCache(userID, size, "default", tenant.TenantId);
isdef = true;
return photoUrl;
}
@ -501,7 +499,7 @@ namespace ASC.Web.Core.Users
//Parse size
size = new Size(int.Parse(match.Groups["width"].Value), int.Parse(match.Groups["height"].Value));
}
UserPhotoManagerCache.AddToCache(parsedUserId, size, fileName);
UserPhotoManagerCache.AddToCache(parsedUserId, size, fileName, tenant.TenantId);
}
}
}
@ -539,7 +537,7 @@ namespace ASC.Web.Core.Users
}
UserManager.SaveUserPhoto(idUser, null);
UserPhotoManagerCache.ClearCache(idUser);
UserPhotoManagerCache.ClearCache(idUser, tenant.TenantId);
}
public void SyncPhoto(Guid userID, byte[] data)
@ -547,7 +545,7 @@ namespace ASC.Web.Core.Users
data = TryParseImage(data, -1, OriginalFotoSize, out _, out int width, out int height);
UserManager.SaveUserPhoto(userID, data);
SetUserPhotoThumbnailSettings(userID, width, height);
UserPhotoManagerCache.ClearCache(userID);
UserPhotoManagerCache.ClearCache(userID, tenant.TenantId);
}
@ -562,7 +560,7 @@ namespace ASC.Web.Core.Users
{
UserManager.SaveUserPhoto(userID, data);
SetUserPhotoThumbnailSettings(userID, width, height);
UserPhotoManagerCache.ClearCache(userID);
UserPhotoManagerCache.ClearCache(userID, tenant.TenantId);
}
@ -731,7 +729,7 @@ namespace ASC.Web.Core.Users
using var stream2 = new MemoryStream(data);
item.DataStore.Save(fileName, stream2).ToString();
UserPhotoManagerCache.AddToCache(item.UserId, item.Size, fileName);
UserPhotoManagerCache.AddToCache(item.UserId, item.Size, fileName, tenant.TenantId);
}
catch (ArgumentException error)
{
@ -844,7 +842,7 @@ namespace ASC.Web.Core.Users
photoUrl = store.Save(fileName, s).ToString();
}
UserPhotoManagerCache.AddToCache(userID, size, fileName);
UserPhotoManagerCache.AddToCache(userID, size, fileName, tenant.TenantId);
return photoUrl;
}