示例#1
0
        /// <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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }