2022-02-11 15:42:50 +00:00
|
|
|
|
namespace ASC.Feed.Aggregator.Service;
|
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
[Singletone]
|
2022-02-11 15:42:50 +00:00
|
|
|
|
public class FeedAggregatorService : FeedBaseService
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
protected override string LoggerName { get; set; } = "ASC.Feed.Aggregator";
|
2022-02-18 09:48:06 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
private readonly SignalrServiceClient _signalrServiceClient;
|
|
|
|
|
|
|
|
|
|
public FeedAggregatorService(
|
|
|
|
|
FeedSettings feedSettings,
|
2022-02-15 15:34:01 +00:00
|
|
|
|
IServiceScopeFactory serviceScopeFactory,
|
2022-02-11 15:42:50 +00:00
|
|
|
|
IOptionsMonitor<ILog> optionsMonitor,
|
|
|
|
|
SignalrServiceClient signalrServiceClient)
|
2022-02-15 15:34:01 +00:00
|
|
|
|
: base(feedSettings, serviceScopeFactory, optionsMonitor)
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
_signalrServiceClient = signalrServiceClient;
|
|
|
|
|
}
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
2022-02-11 15:42:50 +00:00
|
|
|
|
{
|
|
|
|
|
Logger.Info("Feed Aggregator service running.");
|
2022-02-11 11:39:42 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var cfg = FeedSettings;
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
|
|
|
{
|
|
|
|
|
AggregateFeeds(cfg.AggregateInterval);
|
|
|
|
|
|
|
|
|
|
await Task.Delay(cfg.AggregatePeriod, stoppingToken);
|
|
|
|
|
}
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
Logger.Info("Feed Aggregator Service stopping.");
|
2022-02-11 15:42:50 +00:00
|
|
|
|
}
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
private static T Attempt<T>(int count, Func<T> action)
|
2022-02-11 15:42:50 +00:00
|
|
|
|
{
|
2022-02-18 09:48:06 +00:00
|
|
|
|
var counter = 0;
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return action();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
if (count < ++counter)
|
|
|
|
|
{
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-11 15:42:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
private static bool TryAuthenticate(SecurityContext securityContext, AuthManager authManager, int tenantId, Guid userid)
|
2022-02-11 15:42:50 +00:00
|
|
|
|
{
|
2022-02-18 09:48:06 +00:00
|
|
|
|
try
|
2022-02-11 15:42:50 +00:00
|
|
|
|
{
|
2022-02-18 09:48:06 +00:00
|
|
|
|
securityContext.AuthenticateMeWithoutCookie(authManager.GetAccountByID(tenantId, userid));
|
|
|
|
|
return true;
|
2020-06-03 14:53:58 +00:00
|
|
|
|
}
|
2022-02-18 09:48:06 +00:00
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 09:48:06 +00:00
|
|
|
|
private void AggregateFeeds(object interval)
|
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
try
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var cfg = FeedSettings;
|
2022-02-15 15:34:01 +00:00
|
|
|
|
using var scope = ServiceScopeFactory.CreateScope();
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var cache = scope.ServiceProvider.GetService<ICache>();
|
2022-02-18 09:48:06 +00:00
|
|
|
|
var baseCommonLinkUtility = scope.ServiceProvider.GetService<BaseCommonLinkUtility>();
|
2022-02-11 15:42:50 +00:00
|
|
|
|
baseCommonLinkUtility.Initialize(cfg.ServerRoot);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var start = DateTime.UtcNow;
|
|
|
|
|
Logger.DebugFormat("Start of collecting feeds...");
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var unreadUsers = new Dictionary<int, Dictionary<Guid, int>>();
|
|
|
|
|
var modules = scope.ServiceProvider.GetService<IEnumerable<IFeedModule>>();
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-18 10:47:55 +00:00
|
|
|
|
var feedAggregateDataProvider = scope.ServiceProvider.GetService<FeedAggregateDataProvider>();
|
|
|
|
|
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
|
|
|
|
var userManager = scope.ServiceProvider.GetService<UserManager>();
|
|
|
|
|
var authManager = scope.ServiceProvider.GetService<AuthManager>();
|
|
|
|
|
var securityContext = scope.ServiceProvider.GetService<SecurityContext>();
|
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
foreach (var module in modules)
|
|
|
|
|
{
|
|
|
|
|
var result = new List<FeedRow>();
|
|
|
|
|
var fromTime = feedAggregateDataProvider.GetLastTimeAggregate(module.GetType().Name);
|
|
|
|
|
if (fromTime == default) fromTime = DateTime.UtcNow.Subtract((TimeSpan)interval);
|
|
|
|
|
var toTime = DateTime.UtcNow;
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var tenants = Attempt(10, () => module.GetTenantsWithFeeds(fromTime)).ToList();
|
|
|
|
|
Logger.DebugFormat("Find {1} tenants for module {0}.", module.GetType().Name, tenants.Count);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
foreach (var tenant in tenants)
|
|
|
|
|
{
|
|
|
|
|
// Warning! There is hack here!
|
|
|
|
|
// clearing the cache to get the correct acl
|
|
|
|
|
cache.Remove("acl" + tenant);
|
|
|
|
|
cache.Remove("/webitemsecurity/" + tenant);
|
|
|
|
|
//cache.Remove(string.Format("sub/{0}/{1}/{2}", tenant, "6045b68c-2c2e-42db-9e53-c272e814c4ad", NotifyConstants.Event_NewCommentForMessage.ID));
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
try
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
if (tenantManager.GetTenant(tenant) == null)
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
tenantManager.SetCurrentTenant(tenant);
|
|
|
|
|
var users = userManager.GetUsers();
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var feeds = Attempt(10, () => module.GetFeeds(new FeedFilter(fromTime, toTime) { Tenant = tenant }).Where(r => r.Item1 != null).ToList());
|
|
|
|
|
Logger.DebugFormat("{0} feeds in {1} tenant.", feeds.Count, tenant);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
var tenant1 = tenant;
|
|
|
|
|
var module1 = module;
|
|
|
|
|
var feedsRow = feeds
|
|
|
|
|
.Select(tuple => new Tuple<FeedRow, object>(new FeedRow(tuple.Item1)
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
Tenant = tenant1,
|
|
|
|
|
ProductId = module1.Product
|
|
|
|
|
}, tuple.Item2))
|
|
|
|
|
.ToList();
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
foreach (var u in users)
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
if (!TryAuthenticate(securityContext, authManager, tenant1, u.ID))
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
continue;
|
2020-06-03 14:53:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
module.VisibleFor(feedsRow, u.ID);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
}
|
2022-02-11 15:42:50 +00:00
|
|
|
|
|
|
|
|
|
result.AddRange(feedsRow.Select(r => r.Item1));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.ErrorFormat("Tenant: {0}, {1}", tenant, ex);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
feedAggregateDataProvider.SaveFeeds(result, module.GetType().Name, toTime);
|
2020-06-03 14:53:58 +00:00
|
|
|
|
|
2022-02-11 15:42:50 +00:00
|
|
|
|
foreach (var res in result)
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
foreach (var userGuid in res.Users.Where(userGuid => !userGuid.Equals(res.ModifiedById)))
|
2020-06-03 14:53:58 +00:00
|
|
|
|
{
|
2022-02-11 15:42:50 +00:00
|
|
|
|
if (!unreadUsers.TryGetValue(res.Tenant, out var dictionary))
|
|
|
|
|
{
|
|
|
|
|
dictionary = new Dictionary<Guid, int>();
|
|
|
|
|
}
|
|
|
|
|
if (dictionary.ContainsKey(userGuid))
|
|
|
|
|
{
|
|
|
|
|
++dictionary[userGuid];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dictionary.Add(userGuid, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unreadUsers[res.Tenant] = dictionary;
|
2020-06-03 14:53:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-11 15:42:50 +00:00
|
|
|
|
|
|
|
|
|
_signalrServiceClient.SendUnreadUsers(unreadUsers);
|
|
|
|
|
|
|
|
|
|
Logger.DebugFormat("Time of collecting news: {0}", DateTime.UtcNow - start);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.Error(ex);
|
|
|
|
|
}
|
2020-10-26 16:38:23 +00:00
|
|
|
|
}
|
2022-02-18 09:48:06 +00:00
|
|
|
|
}
|