sync CommunityServer and AppServer cache via redis
This commit is contained in:
parent
04ff8d38dc
commit
a7dc8c7dfd
@ -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; }
|
||||
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"Redis": {
|
||||
"Ssl": false,
|
||||
"ConnectTimeout": 60000,
|
||||
"ConnectTimeout": 5000,
|
||||
"SyncTimeout": 60000,
|
||||
"ConnectRetry": 2,
|
||||
"Database": 0,
|
||||
"Hosts": [
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user