private static void Rollback(EventLog log, EventLogEntry logEntry, Exception reason) { var queueId = log.Id; if (logEntry.Operation == EventOperation.Raise) { var content = DTObject.CreateReusable(logEntry.ContentCode); var entryId = content.GetValue <int>("entryId"); var queue = EventQueue.Find(queueId); if (queue.IsEmpty()) { return; } var entry = queue.GetEntry(entryId); if (!entry.IsEmpty()) { Reverse(queue, entry); } EventQueue.Update(queue); } else if (logEntry.Operation == EventOperation.Start) { EventQueue.Delete(queueId); } }
/// <summary> /// 执行远程事件超时 /// </summary> /// <param name="queueId"></param> /// <param name="key"></param> /// <param name="callback"></param> public static void Timeout(Guid queueId, EventKey key, EventCallback callback) { TimeoutManager.End(key); //首先释放资源,删除为了收取信息而建立的临时队列 CleanupRemoteEventResult(key.EventName, key.EventId); //记录异常状态 DataContext.NewScope(() => { var queue = EventQueue.Find(queueId); if (queue.IsEmpty()) { return; } var entry = queue.GetEntry(key.EventId); if (entry.IsEmpty() || entry.IsLocal) { return; } entry.Status = EventStatus.TimedOut; EventQueue.Update(queue); }, true); //抛出执行失败的异常 throw new RemoteEventFailedException(Strings.ExecuteRemoteEventTimeout); }
/// <summary> /// 完成远程事件 /// </summary> /// <param name="event"></param> private static void CompleteRemoteEvent(Guid queueId, DTObject @event, EventKey key) { if (!TimeoutManager.End(key)) { return; //如果结束失败,证明已超时了 } //首先释放资源,删除为了收取信息而建立的临时队列 CleanupRemoteEventResult(key.EventName, key.EventId); //再处理结果 var success = @event.GetValue <bool>("success"); var message = @event.GetValue <string>("message"); if (!success) { //如果没有执行成功,那么抛出异常 throw new RemoteEventFailedException(message); } var args = @event.GetObject("args"); DataContext.NewScope(() => { var queue = EventQueue.Find(queueId); if (queue.IsEmpty()) { //短期内事件队列不存在只有一个原因,那就是由于回逆而被删除了 //长期内事件不存在,那是因为为防止数据过多导致性能下降,已完成的过期队列会被删除,这种情况下不可能被继续调用,不会执行到这里来 throw new DomainEventException(string.Format(Strings.QueueNotExistWithCallbackTip, queue.Id)); } var entry = queue.GetEntry(key.EventId); if (entry.IsEmpty()) { throw new DomainEventException(string.Format(Strings.EventEntryNotExistWithCallbackTip, queue.Id, entry.EventId)); } if (entry.IsLocal) //本地事件是不能继续触发的,这明显是个致命错误 { throw new DomainEventException(string.Format(Strings.ContinueNotWithLocal, entry.EventName)); } if (entry.Status == EventStatus.TimedOut) //已经超时了,抛出异常 { throw new RemoteEventFailedException(Strings.ExecuteRemoteEventTimeout); } //远程事件执行完毕后,用它所在的源事件接受结果 var source = entry.GetSourceEvent(); source.ApplyResult(entry.EventName, args); entry.Status = EventStatus.Raised; EventQueue.Update(queue); }, true); }
/// <summary> /// 触发队列事件 /// </summary> /// <param name="queue"></param> private static void Raise(Guid queueId, EventCallback callback) { bool isSucceeded = false; bool isRunning = false; while (!isRunning && !isSucceeded) { DataContext.NewScope(() => { //触发队列事件 var queue = EventQueue.Find(queueId); var entry = queue.GetPreRaise(); if (!entry.IsEmpty()) { var args = entry.GetArgs(); //获取条目的事件参数 EventLog.FlushRaise(queue, entry); if (entry.IsLocal) { var source = entry.GetSourceEvent(); var local = EventFactory.GetLocalEvent(entry, args, true); RaiseLocalEvent(entry, local, source); } else { var identity = queue.GetIdentity(); RaiseRemoteEvent(entry, identity, args); } } EventQueue.Update(queue); isRunning = queue.IsRunning; isSucceeded = queue.IsSucceeded; }, true); } bool completed = false; DomainEvent @event = null; if (isSucceeded) { DataContext.NewScope(() => { var queue = EventQueue.Find(queueId); if (queue.IsSubqueue) { var entry = queue.Source; var argsCode = entry.ArgsCode; var identity = queue.GetIdentity(); var eventName = entry.EventName; var eventId = entry.EventId; callback.Mount(() => //挂载回调事件,这样所有操作执行完毕后,会发布事件被完成的消息 { //发布事件被完成的消息 PublishRaiseSucceeded(identity, eventName, eventId, argsCode); }); } else { //不是被外界调用的,所以整个事件场景已完成 completed = true; @event = queue.Source.GetSourceEvent(); } }, true); EventLog.FlushEnd(queueId); //指示恢复管理器事件队列的操作已经全部完成 } if (completed) { callback.Mount(() => //挂载回调事件 { DomainEvent.OnSucceeded(queueId, @event); }); } }