Example #1
0
        private SQueue GetQueue(SMessage message)
        {
            if (!message.Extensions.TryGetValue(_queueName, out object objQueue))
            {
                return(null);
            }

            return((SQueue)objQueue);
        }
Example #2
0
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task Add(SMessage message)
        {
            //根据key获取队列
            var queue = await _sQueueChooseService.Choose(message.Key);

            //执行存储
            await _smessageStore.Add(queue, message);

            //执行扩展
            var context = _smessageOperationContextFactory.Create(message, new Dictionary <string, object>());
            await MessageQueueExtensionDescription.OnSMessageAddExecuted(context);
        }
Example #3
0
        /// <summary>
        /// 获取与指定消息的key相同,且期望执行时间早于指定消息的消息
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task <SMessage> GetBeforeExpectTimeMessage(SMessage message)
        {
            //如果消息是死消息,则只需要在对应的队列中查找
            //否则还需要到对应的死队列中查找

            //首先在自身队列中查找
            //尝试获取message扩展属性中存储的队列
            var queue = GetQueue(message);

            if (queue == null)
            {
                //如果扩展属性中的队列为空,则需要通过Key来获取队列
                //如果消息为死消息,则需要获取所属的死队列
                if (message.IsDead)
                {
                    queue = await _sQueueChooseService.ChooseDead(message.Key);
                }
                else
                {
                    queue = await _sQueueChooseService.Choose(message.Key);
                }
            }

            var beforeMessage = await _smessageStore.QueryByKeyAndBeforeExpectTime(queue, message.Key, message.ExpectationExecuteTime);

            if (beforeMessage != null)
            {
                return(beforeMessage);
            }


            //在对应的死队列中查找
            if (!message.IsDead)
            {
                //获取对应死队列
                queue = await _sQueueChooseService.ChooseDead(message.Key);

                beforeMessage = await _smessageStore.QueryByKeyAndBeforeExpectTime(queue, message.Key, message.ExpectationExecuteTime);

                if (beforeMessage != null)
                {
                    return(beforeMessage);
                }
            }

            return(null);
        }
Example #4
0
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task Delete(SMessage message)
        {
            //尝试获取message扩展属性中存储的队列
            var queue = GetQueue(message);

            if (queue == null)
            {
                //如果扩展属性中的队列为空,则需要通过Key来获取队列
                //如果消息为死消息,则需要获取所属的死队列
                if (message.IsDead)
                {
                    queue = await _sQueueChooseService.ChooseDead(message.Key);
                }
                else
                {
                    queue = await _sQueueChooseService.Choose(message.Key);
                }
            }

            //执行删除
            await _smessageStore.Delete(queue, message.ID);
        }
Example #5
0
        public async Task AddDelay(SMessage message, int delaySeconds, string extensionMessage)
        {
            //尝试获取message扩展属性中存储的队列
            var queue = GetQueue(message);

            if (queue == null)
            {
                //如果扩展属性中的队列为空,则需要通过Key来获取队列
                //如果消息为死消息,则需要获取所属的死队列
                if (message.IsDead)
                {
                    queue = await _sQueueChooseService.ChooseDead(message.Key);
                }
                else
                {
                    queue = await _sQueueChooseService.Choose(message.Key);
                }
            }

            var existMessage = await _smessageStore.QueryByDelayID(queue, message.ID);

            if (existMessage == null)
            {
                var newMessage = new SMessage()
                {
                    Key  = message.Key,
                    Type = message.Type,
                    OriginalMessageID      = message.OriginalMessageID,
                    TypeListenerID         = message.TypeListenerID,
                    ExtensionMessage       = extensionMessage,
                    ExpectationExecuteTime = DateTime.UtcNow.AddSeconds(delaySeconds),
                    DelayMessageID         = message.ID,
                    Data = message.Data
                };
                await message.Add();
            }
        }
Example #6
0
        /// <summary>
        /// 通过模式2提交到监听者
        /// 通过HTTP协议Post消息到ListenerWebUrl的web接口,提交的对象类型为SMessagePostData
        /// 其中Signature为Id+Type+Data+CurrentTime的字符串格式(yyyy-MM-dd hh:mm:ss)通过ListenerWebSignature签名后的字符串
        /// 接收方需要对此进行校验
        /// </summary>
        /// <param name="listener"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task <ValidateResult> PostToListenerByMode2(SMessageTypeListener listener, SMessage message)
        {
            ValidateResult result = new ValidateResult()
            {
                Result = true
            };
            var expireTime        = DateTime.UtcNow.AddSeconds(300);
            var strContent        = $"{message.ID.ToString()}{message.Type}{message.Data}{expireTime.ToString("yyyy-MM-dd hh:mm:ss")}";
            var strSignature      = _securityService.SignByKey(strContent, listener.ListenerWebSignature);
            SMessagePostData data = new SMessagePostData()
            {
                ID         = message.ID,
                ExpireTime = expireTime,
                Type       = message.Type,
                Data       = message.Data,
                Signature  = strSignature
            };

            try
            {
                await HttpClinetHelper.PostAsync(data, listener.ListenerWebUrl);
            }
            catch (Exception ex)
            {
                result.Result      = false;
                result.Description = ex.Message;
            }

            return(result);
        }
Example #7
0
        /// <summary>
        /// 通过模式1提交到监听者
        /// 检查是否在缓存中已经存在相应的工厂类,
        //  如果不存在,根据ListenerFactoryTypeUseDI决定是通过DIContainerContainer获取工厂类,
        //  还是使用反射创建工厂类
        //  将创建出来的工厂类缓存在缓存中
        /// </summary>
        /// <param name="listener"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task <ValidateResult> PostToListenerByMode1(SMessageTypeListener listener, SMessage message)
        {
            if (!_listenerFactorys.TryGetValue(listener.ListenerFactoryType, out IFactory <ISMessageListener> listenerFactory))
            {
                lock (_listenerFactorys)
                {
                    Type listenerFactoryType = Type.GetType(listener.ListenerFactoryType);

                    if (!_listenerFactorys.TryGetValue(listener.ListenerFactoryType, out listenerFactory))
                    {
                        object objListenerFactory;
                        if (listener.ListenerFactoryTypeUseDI == true)
                        {
                            //通过DI容器创建
                            //objListenerFactory = DIContainerContainer.Get(listenerFactoryType);
                            objListenerFactory = DIContainerGetHelper.Get().Get(listenerFactoryType);
                        }
                        else
                        {
                            //通过反射创建
                            objListenerFactory = listenerFactoryType.Assembly.CreateInstance(listenerFactoryType.FullName);
                        }

                        if (!(objListenerFactory is IFactory <ISMessageListener>))
                        {
                            var fragment = new TextFragment()
                            {
                                Code = TextCodes.SMessageTypeListenerTypeError,
                                DefaultFormatting = "消息类型{0}中,名称为{1}的监听者工厂的类型{2}未实现接口IFactory<ISMessageListener>",
                                ReplaceParameters = new List <object>()
                                {
                                    listener.MessageType.Name, listener.Name, listener.ListenerFactoryType
                                }
                            };

                            throw new UtilityException((int)Errors.SMessageTypeListenerTypeError, fragment);
                        }

                        listenerFactory = (IFactory <ISMessageListener>)objListenerFactory;
                        _listenerFactorys.Add(listener.ListenerFactoryType, listenerFactory);
                    }
                }
            }

            var listenerObj = listenerFactory.Create();

            return(await listenerObj.Execute(message));
        }
Example #8
0
 public async Task <ValidateResult> PostToListener(SMessageTypeListener listener, SMessage message)
 {
     //检查监听者模式
     //不同的模式执行不同的处理
     if (listener.Mode == 0)
     {
         return(await PostToListenerByMode1(listener, message));
     }
     else
     {
         return(await PostToListenerByMode2(listener, message));
     }
 }
Example #9
0
 /// <summary>
 /// 在模式为0的情况下调用ISMessageListener实现类的方法
 /// 在模式为1的情况下Post消息到监听地址
 /// </summary>
 /// <returns></returns>
 public async Task <ValidateResult> PostToListener(SMessage message)
 {
     return(await _imp.PostToListener(this, message));
 }
Example #10
0
        /// <summary>
        /// 执行消息
        /// </summary>
        /// <param name="message"></param>
        /// <returns>0:成功,1:未到执行时间,2:失败,3:移除到死队列</returns>
        public async Task <StatusResult> Execute(SMessage message)
        {
            StatusResult result = new StatusResult()
            {
                Status = 0
            };

            //获取消息执行类型
            var executeType = await _smessageExecuteTypeRepositoryCacheProxy.QueryByName(message.Type);

            if (executeType == null)
            {
                var fragment = new TextFragment()
                {
                    Code = TextCodes.NotFoundSMessageTypeByName,
                    DefaultFormatting = "找不到名称为{0}的消息类型",
                    ReplaceParameters = new List <object>()
                    {
                        message.Type
                    }
                };
                throw new UtilityException((int)Errors.NotFoundSMessageTypeByName, fragment);
            }


            var queue = GetQueue(message);

            if (queue == null)
            {
                //如果扩展属性中的队列为空,则需要通过Key来获取队列
                queue = await _sQueueChooseService.Choose(message.Key);
            }

            //检查预计执行时间是否>=当前时间
            //如果是,则直接返回结果
            var nowUTC = DateTime.UtcNow;

            if (message.ExpectationExecuteTime >= nowUTC)
            {
                result.Status = 1;
                return(await Task.FromResult(result));
            }


            //检查是否存在比期望执行时间早的相同key的消息
            //如果消息本身不是死消息,找到的消息是死消息,则直接将该消息转移到死消息队列中
            //返回结果3
            var beforeMessage = await GetBeforeExpectTimeMessage(message);

            if (beforeMessage != null)
            {
                result.Status = 1;
                if (!message.IsDead && beforeMessage.IsDead)
                {
                    var deadQueue = await _sQueueChooseService.ChooseDead(message.Key);

                    await using (var transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                    {
                        IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 30)
                    }))
                    {
                        await _smessageStore.Delete(queue, message.ID);

                        await _smessageStore.AddToDead(deadQueue, message);

                        result.Status = 3;
                        //执行扩展
                        var context = _smessageOperationContextFactory.Create(message, new Dictionary <string, object>());
                        await MessageQueueExtensionDescription.OnSMessageAddToDeadExecuted(context);

                        transactionScope.Complete();
                    }
                }


                return(await Task.FromResult(result));
            }


            //增加消息历史
            var messageHistory = await _smessageHistoryStore.QueryById(message.ID);

            if (messageHistory == null)
            {
                messageHistory = new SMessageHistory()
                {
                    ID                = message.ID,
                    CreateTime        = DateTime.UtcNow,
                    ModifyTime        = DateTime.UtcNow,
                    Type              = message.Type,
                    Key               = message.Key,
                    Data              = message.Data,
                    OriginalMessageID = message.OriginalMessageID,
                    DelayMessageID    = message.DelayMessageID
                };
                await messageHistory.Add();
            }

            Dictionary <Guid, ISMessageTypeListenerPostContext> postContextList = new Dictionary <Guid, ISMessageTypeListenerPostContext>();
            ISMessageTypeListenerPostContext postContext = null;



            //如果已经关联了监听,则直接执行监听的行为
            if (message.TypeListenerID.HasValue)
            {
                var listener = await executeType.GetListener(message.TypeListenerID.Value);

                if (listener == null)
                {
                    var fragment = new TextFragment()
                    {
                        Code = TextCodes.NotFoundSMessageTypeListenerFromTypeByID,
                        DefaultFormatting = "名称为{0}的消息类型下,找不到监听ID为{1}的监听",
                        ReplaceParameters = new List <object>()
                        {
                            message.Type, message.TypeListenerID.Value.ToString()
                        }
                    };

                    throw new UtilityException((int)Errors.NotFoundSMessageTypeListenerFromTypeByID, fragment);
                }

                Exception error = null;
                try
                {
                    //判断该监听是否已经完成
                    var listenerDetail = await _smessageHistoryListenerDetailStore.QueryByName(message.ID, listener.Name);

                    if (listenerDetail == null)
                    {
                        var execueResult = await listener.PostToListener(message);

                        if (!execueResult.Result)
                        {
                            throw new Exception(execueResult.Description);
                        }

                        postContext = _smessageTypeListenerPostContextFactory.Create(listener, message, null, new Dictionary <string, object>());

                        listenerDetail = new SMessageHistoryListenerDetail()
                        {
                            SMessageHistoryID   = messageHistory.ID,
                            ListenerMode        = listener.Mode,
                            ListenerFactoryType = listener.ListenerFactoryType,
                            ListenerName        = listener.Name,
                            ListenerRealWebUrl  = string.Empty,
                            ListenerWebUrl      = listener.ListenerWebUrl,
                        };

                        await messageHistory.AddListenerDetail(listenerDetail);
                    }
                }
                catch (Exception ex)
                {
                    error = ex;
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    postContext = _smessageTypeListenerPostContextFactory.Create(listener, message, ex, new Dictionary <string, object>());
                }

                if (postContext != null)
                {
                    await MessageQueueExtensionDescription.OnSMessageTypeListenerExecuted(postContext);
                }

                if (error != null)
                {
                    string strError = $"{error.Message},{error.StackTrace}";
                    result.Status      = 2;
                    result.Description = StringLanguageTranslate.Translate(TextCodes.SMessageExecuteError, string.Format("消息执行出错,消息key:{0},消息type:{1},消息内容:{2},错误内容:{3}", message.Key, message.Type, message.Data, strError));

                    //如果消息不是死消息,并且重试次数超过3次,则移除到死消息队列中
                    //否则增加重试次数
                    if (!message.IsDead && message.RetryNumber + 1 >= 3)
                    {
                        message.ExceptionMessage = result.Description;
                        var deadQueue = await _sQueueChooseService.ChooseDead(message.Key);

                        await using (var transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                        {
                            IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 30)
                        }))
                        {
                            await _smessageStore.Delete(queue, message.ID);

                            await _smessageStore.AddToDead(deadQueue, message);

                            result.Status = 3;
                            //执行扩展
                            var context = _smessageOperationContextFactory.Create(message, new Dictionary <string, object>());
                            await MessageQueueExtensionDescription.OnSMessageAddToDeadExecuted(context);

                            transactionScope.Complete();
                        }
                    }
                    else
                    {
                        await using (var transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                        {
                            IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 30)
                        }))
                        {
                            /*if (strError.Length > 3000)
                             * {
                             *  strError = strError.Remove(3000, strError.Length - 3000);
                             * }*/

                            await _smessageStore.AddRetry(queue, message.ID, strError);

                            await _smessageStore.UpdateLastExecuteTime(queue, message.ID);

                            transactionScope.Complete();
                        }
                    }



                    return(await Task.FromResult(result));
                }
                else
                {
                    await messageHistory.Complete();
                }
            }
            else
            {
                //为每个监听者并行执行监听处理
                List <Task>      tasks          = new List <Task>();
                List <Exception> taskExceptions = new List <Exception>();
                ParallelHelper   parallel       = new ParallelHelper(10);


                await executeType.GetAllListener(async (listener) =>
                {
                    parallel.Run(tasks, async(exception) =>
                    {
                        while (exception.InnerException != null)
                        {
                            exception = exception.InnerException;
                        }
                        taskExceptions.Add(exception);
                        postContext = _smessageTypeListenerPostContextFactory.Create(listener, message, exception, new Dictionary <string, object>());
                        postContextList[listener.ID] = postContext;
                        await Task.FromResult(0);
                    },
                                 async() =>
                    {
                        //判断该监听是否已经完成
                        var listenerDetail = await _smessageHistoryListenerDetailStore.QueryByName(message.ID, listener.Name);
                        if (listenerDetail == null)
                        {
                            //检查监听是否有所属队列,如果有,则为该监听创建新的消息,如果没有,则执行消息
                            if (!string.IsNullOrEmpty(listener.QueueGroupName))
                            {
                                //生成key
                                var newKey = await _listenerMessageKeyGenerateService.Generate(message.Key, listener);

                                //获取新消息所属队列
                                var newMessageQueue     = await _sQueueChooseService.Choose(newKey);
                                var newMessageDeadQueue = await _sQueueChooseService.ChooseDead(newKey);

                                //检查是否已经存在消息
                                var existNewMessage = _smessageStore.QueryByOriginalID(newMessageQueue, message.ID, listener.ID);
                                if (existNewMessage == null)
                                {
                                    existNewMessage = _smessageStore.QueryByOriginalID(newMessageDeadQueue, message.ID, listener.ID);
                                }

                                if (existNewMessage == null)
                                {
                                    SMessage newMessage = new SMessage()
                                    {
                                        Data   = message.Data,
                                        Key    = newKey,
                                        IsDead = message.IsDead,
                                        ExpectationExecuteTime = message.ExpectationExecuteTime,
                                        Type              = message.Type,
                                        TypeListenerID    = listener.ID,
                                        OriginalMessageID = message.ID,
                                        RetryNumber       = 0
                                    };

                                    await newMessage.Add();
                                }
                            }
                            else
                            {
                                var execueResult = await listener.PostToListener(message);
                                if (!execueResult.Result)
                                {
                                    throw new Exception(execueResult.Description);
                                }
                            }


                            postContext = _smessageTypeListenerPostContextFactory.Create(listener, message, null, new Dictionary <string, object>());
                            postContextList[listener.ID] = postContext;

                            listenerDetail = new SMessageHistoryListenerDetail()
                            {
                                SMessageHistoryID   = messageHistory.ID,
                                ListenerMode        = listener.Mode,
                                ListenerFactoryType = listener.ListenerFactoryType,
                                ListenerName        = listener.Name,
                                ListenerRealWebUrl  = string.Empty,
                                ListenerWebUrl      = listener.ListenerWebUrl,
                            };

                            await messageHistory.AddListenerDetail(listenerDetail);
                        }
                    }
                                 );
                    await Task.FromResult(0);
                });

                //等待所有监听者执行完成
                foreach (var taskItem in tasks)
                {
                    await taskItem;
                }


                //调用扩展介入类的OnSMessageTypeListenerExecuted方法
                foreach (var item in postContextList)
                {
                    await MessageQueueExtensionDescription.OnSMessageTypeListenerExecuted(item.Value);
                }

                if (taskExceptions.Count > 0)
                {
                    var strError = new StringBuilder();
                    foreach (var exceptionItem in taskExceptions)
                    {
                        strError.Append("Message:");
                        strError.Append(await exceptionItem.GetCurrentLcidMessage());
                        strError.Append("\n");
                        strError.Append("StackTrace");
                        strError.Append(exceptionItem.StackTrace);
                        strError.Append("\n\n");
                    }

                    message.ExceptionMessage = strError.ToString();
                    result.Status            = 2;
                    result.Description       = StringLanguageTranslate.Translate(TextCodes.SMessageExecuteError, string.Format("消息执行出错,消息key:{0},消息type:{1},消息内容:{2},错误内容:{3}", message.Key, message.Type, message.Data, strError));

                    //如果消息不是死消息,并且重试次数超过3次,则移除到死消息队列中
                    //否则增加重试次数
                    if (!message.IsDead && message.RetryNumber + 1 >= 3)
                    {
                        message.ExceptionMessage = result.Description;
                        var deadQueue = await _sQueueChooseService.ChooseDead(message.Key);

                        await using (var transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                        {
                            IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 30)
                        }))
                        {
                            await _smessageStore.Delete(queue, message.ID);

                            await _smessageStore.AddToDead(deadQueue, message);

                            result.Status = 3;
                            //执行扩展
                            var context = _smessageOperationContextFactory.Create(message, new Dictionary <string, object>());
                            await MessageQueueExtensionDescription.OnSMessageAddToDeadExecuted(context);

                            transactionScope.Complete();
                        }
                    }
                    else
                    {
                        await using (var transactionScope = new DBTransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                        {
                            IsolationLevel = IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 30, 30)
                        }))
                        {
                            /*if (strError.Length > 3000)
                             * {
                             *  strError = strError.Remove(3000, strError.Length - 3000);
                             * }*/

                            await _smessageStore.AddRetry(queue, message.ID, strError.ToString());

                            await _smessageStore.UpdateLastExecuteTime(queue, message.ID);

                            transactionScope.Complete();
                        }
                    }
                }
                else
                {
                    await messageHistory.Complete();
                }
            }



            return(await Task.FromResult(result));
        }