public async Task <DateTime?> FetchSince(DateTime cursor) { using (_logger.Scope("Processing manual status changes.")) { var manualChangesQuery = _table .CreateQuery <ManualStatusChangeEntity>(); // Table storage throws on queries with DateTime values that are too low. // If we are fetching manual changes for the first time, don't filter on the timestamp. if (cursor > DateTime.MinValue) { manualChangesQuery = manualChangesQuery.Where(c => c.Timestamp > new DateTimeOffset(cursor, TimeSpan.Zero)); } var manualChanges = manualChangesQuery.ToList(); _logger.LogInformation("Processing {ManualChangesCount} manual status changes.", manualChanges.Count()); foreach (var manualChange in manualChanges.OrderBy(m => m.Timestamp)) { await _handler.Handle(_table, manualChange); } return(manualChanges.Any() ? manualChanges.Max(c => c.Timestamp.UtcDateTime) : (DateTime?)null); } }
public static IQueryable <TEntity> GetActiveEntities <TEntity>(this ITableWrapper table) where TEntity : ComponentAffectingEntity, new() { return(table .CreateQuery <TEntity>() .Where(e => e.IsActive)); }
public static IQueryable <TChild> GetChildEntities <TChild, TParent>(this ITableWrapper table, TParent entity) where TChild : ITableEntity, IChildEntity <TParent>, new() where TParent : ITableEntity { return(table .CreateQuery <TChild>() .Where(e => e.ParentRowKey == entity.RowKey)); }
public IEnumerable <Event> Export(DateTime cursor) { return(_table .CreateQuery <EventEntity>() .Where(e => e.IsActive || (e.EndTime >= cursor - _eventVisibilityPeriod)) .ToList() .Select(_exporter.Export) .Where(e => e != null) .ToList()); }
public async Task <TAggregationEntity> GetAsync(ParsedIncident input) { TAggregationEntity aggregationEntity = null; var possiblePath = _aggregationPathProvider.Get(input); // Find an aggregation to link to var possibleAggregationsQuery = _table .CreateQuery <TAggregationEntity>() .Where(e => // The aggregation must affect the same path e.AffectedComponentPath == possiblePath && // The aggregation must begin before or at the same time e.StartTime <= input.StartTime); // The aggregation must cover the same time period if (input.IsActive) { // An active input can only be linked to an active aggregation possibleAggregationsQuery = possibleAggregationsQuery .Where(e => e.IsActive); } else { // An inactive input can be linked to an active aggregation or an inactive aggregation that ends after it possibleAggregationsQuery = possibleAggregationsQuery .Where(e => e.IsActive || e.EndTime >= input.EndTime); } var possibleAggregations = possibleAggregationsQuery .ToList(); _logger.LogInformation("Found {AggregationCount} possible aggregations to link entity to with path {AffectedComponentPath}.", possibleAggregations.Count(), possiblePath); foreach (var possibleAggregation in possibleAggregations) { if (await _strategy.CanBeAggregatedByAsync(input, possibleAggregation)) { _logger.LogInformation("Linking entity to aggregation."); aggregationEntity = possibleAggregation; break; } } if (aggregationEntity == null) { _logger.LogInformation("Could not find existing aggregation to link to, creating new aggregation to link entity to."); aggregationEntity = await _aggregationFactory.CreateAsync(input); _logger.LogInformation("Created new aggregation {AggregationRowKey} to link entity to.", aggregationEntity.RowKey); } return(aggregationEntity); }