/// <summary> /// Runs aggregator /// </summary> /// <param name="cancellationToken">Cancellation token</param> public void Execute(CancellationToken cancellationToken) { Logger.DebugFormat("Aggregating records in 'Counter' table..."); long removedCount = 0; do { using (var storageConnection = (MongoConnection)_storage.GetConnection()) { HangfireDbContext database = storageConnection.Database; CounterDto[] recordsToAggregate = AsyncHelper.RunSync(() => database.Counter.Find(new BsonDocument()).Limit(NumberOfRecordsInSinglePass).ToListAsync()).ToArray(); var recordsToMerge = recordsToAggregate .GroupBy(_ => _.Key).Select(_ => new { Key = _.Key, Value = _.Sum(x => x.Value), ExpireAt = _.Max(x => x.ExpireAt) }) .ToArray(); foreach (var item in recordsToMerge) { AggregatedCounterDto aggregatedItem = AsyncHelper.RunSync(() => database.AggregatedCounter.Find(Builders <AggregatedCounterDto> .Filter.Eq(_ => _.Key, item.Key)).FirstOrDefaultAsync()); if (aggregatedItem != null) { AsyncHelper.RunSync(() => database.AggregatedCounter.UpdateOneAsync(Builders <AggregatedCounterDto> .Filter.Eq(_ => _.Key, item.Key), Builders <AggregatedCounterDto> .Update.Combine( Builders <AggregatedCounterDto> .Update.Inc(_ => _.Value, item.Value), Builders <AggregatedCounterDto> .Update.Set(_ => _.ExpireAt, item.ExpireAt > aggregatedItem.ExpireAt ? item.ExpireAt : aggregatedItem.ExpireAt)))); } else { AsyncHelper.RunSync(() => database.AggregatedCounter.InsertOneAsync(new AggregatedCounterDto { Id = ObjectId.GenerateNewId(), Key = item.Key, Value = item.Value, ExpireAt = item.ExpireAt })); } } removedCount = AsyncHelper.RunSync(() => database.Counter.DeleteManyAsync(Builders <CounterDto> .Filter.In( _ => _.Id, recordsToAggregate.Select(_ => _.Id)))).DeletedCount; } if (removedCount >= NumberOfRecordsInSinglePass) { cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses); cancellationToken.ThrowIfCancellationRequested(); } } while (removedCount >= NumberOfRecordsInSinglePass); cancellationToken.WaitHandle.WaitOne(_interval); }
public void Execute(CancellationToken cancellationToken) { var removedCount = 0; do { var counters = Data.GetEnumeration <CounterDto>().Take(NumberOfRecordsInSinglePass).ToList(); var groupedCounters = counters.GroupBy(c => c.Key).Select(g => new { g.Key, Value = g.Sum(c => c.Value), ExpireAt = g.Max(c => c.ExpireAt) }); foreach (var counter in groupedCounters) { var aggregate = Data.GetEnumeration <AggregatedCounterDto>() .FirstOrDefault(a => a.Key == counter.Key); if (aggregate == null) { aggregate = new AggregatedCounterDto { Id = AutoIncrementIdGenerator.GenerateId(typeof(AggregatedCounterDto)), Key = counter.Key, Value = 0, ExpireAt = DateTime.MinValue }; Data.Create(aggregate); } aggregate.Value += counter.Value; if (counter.ExpireAt > aggregate.ExpireAt) { aggregate.ExpireAt = counter.ExpireAt; } } removedCount = counters.Count; Data.Delete(counters); if (removedCount > 0) { cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses); cancellationToken.ThrowIfCancellationRequested(); } } while (removedCount != 0); cancellationToken.WaitHandle.WaitOne(_aggregateInterval); }
private static ObjectId CreateExpirationEntry(HangfireDbContext connection, DateTime?expireAt) { var counter = new AggregatedCounterDto { Id = ObjectId.GenerateNewId(), Key = "key", Value = 1, ExpireAt = expireAt }; connection.AggregatedCounter.InsertOne(counter); var id = counter.Id; return(id); }