Пример #1
0
        /// <summary>
        /// InitializeDatabaseAsync
        /// </summary>
        /// <param name="database"></param>
        /// <param name="lockManager"></param>
        /// <returns></returns>
        /// <exception cref="DatabaseException"></exception>
        public static async Task InitializeDatabaseAsync(HB.FullStack.Database.IDatabase database, IDistributedLockManager lockManager, IEnumerable <Migration>?migrations)
        {
            GlobalSettings.Logger.LogDebug($"开始初始化数据库:{database.DatabaseNames.ToJoinedString(",")}");

            IDistributedLock distributedLock = await lockManager.LockAsync(
                resources : database.DatabaseNames,
                expiryTime : TimeSpan.FromMinutes(5),
                waitTime : TimeSpan.FromMinutes(10)).ConfigureAwait(false);

            try
            {
                if (!distributedLock.IsAcquired)
                {
                    ThrowIfDatabaseInitLockNotGet(database.DatabaseNames);
                }

                GlobalSettings.Logger.LogDebug($"获取了初始化数据库的锁:{database.DatabaseNames.ToJoinedString(",")}");

                await database.InitializeAsync(migrations).ConfigureAwait(false);
            }
            finally
            {
                await distributedLock.DisposeAsync().ConfigureAwait(false);
            }
        }
Пример #2
0
        /// <summary>
        /// CosumeTaskProcedure
        /// </summary>


        private async Task CosumeAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    long now = TimeUtil.UtcNowUnixTimeSeconds;

                    //1, Get Entity
                    IDatabase database = await RedisInstanceManager.GetDatabaseAsync(_instanceSetting, _logger).ConfigureAwait(false);

                    RedisValue redisValue = await database.ListRightPopLeftPushAsync(RedisEventBusEngine.QueueName(_eventType), RedisEventBusEngine.HistoryQueueName(_eventType)).ConfigureAwait(false);

                    if (redisValue.IsNullOrEmpty)
                    {
                        _logger.LogTrace("ConsumeTask Sleep, {InstanceName}, {eventType}", _instanceSetting.InstanceName, _eventType);

                        await Task.Delay(_cONSUME_INTERVAL_SECONDS * 1000, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    EventMessageEntity?entity = SerializeUtil.FromJson <EventMessageEntity>(redisValue);

                    if (entity == null)
                    {
                        _logger.LogCritical("有空EventMessageEntity, {eventType}, {value}", _eventType, redisValue);
                        continue;
                    }

                    using IDistributedLock distributedLock = await _lockManager.NoWaitLockAsync(
                              "eBusC_" + entity.Guid,
                              TimeSpan.FromSeconds(_options.EventBusConsumerAckTimeoutSeconds),
                              false,
                              cancellationToken).ConfigureAwait(false);

                    if (!distributedLock.IsAcquired)
                    {
                        //竟然有人在检查entity.Guid,好了,这下肯定有人在处理了,任务结束。哪怕那个人没处理成功,也没事,等着history吧。
                        continue;
                    }

                    //2, 过期检查

                    if (now - entity.Timestamp > _eventBusEventMessageExpiredSeconds)
                    {
                        _logger.LogCritical("有EventMessage过期,{eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));

                        await distributedLock.DisposeAsync().ConfigureAwait(false);

                        continue;
                    }

                    //3, 防重检查

                    string AcksSetName = RedisEventBusEngine.AcksSetName(_eventType);

                    bool?isExist = await IsAcksExistedAsync(database, AcksSetName, entity.Guid).ConfigureAwait(false);

                    if (isExist == null || isExist.Value)
                    {
                        _logger.LogInformation("有EventMessage重复,{eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));

                        await distributedLock.DisposeAsync().ConfigureAwait(false);

                        continue;
                    }

                    //4, Handle Entity
                    try
                    {
                        await _eventHandler.HandleAsync(entity.JsonData, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogCritical(ex, "处理消息出错, {_eventType}, {entity}", _eventType, SerializeUtil.ToJson(entity));
                    }

                    //5, Acks
                    await AddAcksAsync(now, database, AcksSetName, entity.Guid, entity.Timestamp).ConfigureAwait(false);

                    _logger.LogTrace("Consume Task For {eventType} Stopped.", _eventType);
                }
                catch (RedisConnectionException ex)
                {
                    _logger.LogError(ex, "Consume 中出现Redis链接问题. {eventType}", _eventType);
                    await Task.Delay(5000, cancellationToken).ConfigureAwait(false);
                }
                catch (RedisTimeoutException ex)
                {
                    _logger.LogError(ex, "Consume 中出现Redis超时问题. {eventType}", _eventType);
                }
                catch (Exception ex)
                {
                    _logger.LogCritical(ex, "Consume 出现未知问题. {eventType}", _eventType);
                }
            }
        }