private SQueue GetQueue(SMessage message) { if (!message.Extensions.TryGetValue(_queueName, out object objQueue)) { return(null); } return((SQueue)objQueue); }
/// <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); }
/// <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); }
/// <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); }
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(); } }
/// <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); }
/// <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)); }
public async Task <ValidateResult> PostToListener(SMessageTypeListener listener, SMessage message) { //检查监听者模式 //不同的模式执行不同的处理 if (listener.Mode == 0) { return(await PostToListenerByMode1(listener, message)); } else { return(await PostToListenerByMode2(listener, message)); } }
/// <summary> /// 在模式为0的情况下调用ISMessageListener实现类的方法 /// 在模式为1的情况下Post消息到监听地址 /// </summary> /// <returns></returns> public async Task <ValidateResult> PostToListener(SMessage message) { return(await _imp.PostToListener(this, message)); }
/// <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)); }