private async Task <Dictionary <string, double> > GetUserCountByProjectIdsAsync(ICollection <Stack> stacks, string systemFilter, DateTime utcStart, DateTime utcEnd) { var scopedCacheClient = new ScopedCacheClient(_cacheClient, $"project:user-count:{utcStart.Floor(TimeSpan.FromMinutes(15)).Ticks}-{utcEnd.Floor(TimeSpan.FromMinutes(15)).Ticks}"); var projectIds = stacks.Select(s => s.ProjectId).Distinct().ToList(); var cachedTotals = await scopedCacheClient.GetAllAsync <double>(projectIds); var totals = cachedTotals.Where(kvp => kvp.Value.HasValue).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Value); if (totals.Count == projectIds.Count) { return(totals); } var projects = cachedTotals.Where(kvp => !kvp.Value.HasValue).Select(kvp => new Project { Id = kvp.Key, OrganizationId = stacks.FirstOrDefault(s => s.ProjectId == kvp.Key)?.OrganizationId }).ToList(); var projectTerms = await _eventStats.GetNumbersTermsStatsAsync("project_id", _distinctUsersFields, utcStart, utcEnd, systemFilter, projects.BuildRetentionFilter()); // Cache all projects that have more than 10 users for 5 minutes. await scopedCacheClient.SetAllAsync(projectTerms.Terms.Where(t => t.Numbers[0] >= 10).ToDictionary(t => t.Term, t => t.Numbers[0]), TimeSpan.FromMinutes(5)); totals.AddRange(projectTerms.Terms.ToDictionary(kvp => kvp.Term, kvp => kvp.Numbers[0])); return(totals); }
private async Task <Dictionary <string, double> > GetUserCountByProjectIdsAsync(ICollection <Stack> stacks, AppFilter sf, DateTime utcStart, DateTime utcEnd) { var scopedCacheClient = new ScopedCacheClient(_cache, $"Project:user-count:{utcStart.Floor(TimeSpan.FromMinutes(15)).Ticks}-{utcEnd.Floor(TimeSpan.FromMinutes(15)).Ticks}"); var projectIds = stacks.Select(s => s.ProjectId).Distinct().ToList(); var cachedTotals = await scopedCacheClient.GetAllAsync <double>(projectIds); var totals = cachedTotals.Where(kvp => kvp.Value.HasValue).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Value); if (totals.Count == projectIds.Count) { return(totals); } var systemFilter = new RepositoryQuery <PersistentEvent>().AppFilter(sf).DateRange(utcStart, utcEnd, (PersistentEvent e) => e.Date).Index(utcStart, utcEnd); var projects = cachedTotals.Where(kvp => !kvp.Value.HasValue).Select(kvp => new Project { Id = kvp.Key, OrganizationId = stacks.FirstOrDefault(s => s.ProjectId == kvp.Key)?.OrganizationId }).ToList(); var countResult = await _eventRepository.CountAsync(q => q.SystemFilter(systemFilter).FilterExpression(projects.BuildFilter()).AggregationsExpression("terms:(project_id cardinality:user)")); // Cache all projects that have more than 10 users for 5 minutes. var projectTerms = countResult.Aggregations.Terms <string>("terms_project_id").Buckets; var aggregations = projectTerms.ToDictionary(t => t.Key, t => t.Aggregations.Cardinality("cardinality_user").Value.GetValueOrDefault()); await scopedCacheClient.SetAllAsync(aggregations.Where(t => t.Value >= 10).ToDictionary(k => k.Key, v => v.Value), TimeSpan.FromMinutes(5)); totals.AddRange(aggregations); return(totals); }