/// <summary> /// 不依赖当前状态的的事件的并发处理 /// 如果事件的产生依赖当前状态,请使用<see cref="ConcurrentRaiseEvent(Func{Snapshot{PrimaryKey, SnapshotType}, Func{IEvent, EventUID, Task}, Task}, Func{bool, ValueTask}, Action{Exception})"/> /// </summary> /// <param name="event">不依赖当前状态的事件</param> /// <param name="uniqueId">幂等性判定值</param> /// <param name="hashKey">消息异步分发的唯一hash的key</param> /// <returns></returns> protected Task <bool> ConcurrentRaiseEvent(IEvent evt, EventUID uniqueId = null) { return(ConcurrentRaiseEvent(async(snapshot, eventFunc) => { await eventFunc(evt, uniqueId); })); }
private void Clr_LoaderAssemblyLoad(AssemblyLoadUnloadTraceData obj) { // Since we don't have start stop data, simply treat the assembly load event as a point in time so that it is visible in the textual load view EventUID eventTime = new EventUID(obj); AddStartStopData(obj.ProcessID, obj.ThreadID, eventTime, eventTime, $"AssemblyLoad({obj.FullyQualifiedAssemblyName},{obj.AssemblyID})"); }
private void Clr_MethodR2RGetEntryPoint(R2RGetEntryPointTraceData obj) { IdOfIncompleteAction id = new IdOfIncompleteAction(); id.Identifier = obj.MethodID; id.ThreadID = obj.ThreadID; // If we had a R2R start lookup event, capture that start time, otherwise, use the R2REntrypoint // data as both start and stop EventUID startUID = new EventUID(obj); if (_incompleteR2REvents.TryGetValue(id, out IncompleteActionDesc r2rStartData)) { startUID = r2rStartData.Start; _incompleteR2REvents.Remove(id); } if (obj.EntryPoint == 0) { // If Entrypoint is null then the search failed. AddStartStopData(obj.ProcessID, id.ThreadID, startUID, new EventUID(obj), "R2R_Failed" + "(" + JITStats.GetMethodName(obj) + ")"); } else { AddStartStopData(obj.ProcessID, id.ThreadID, startUID, new EventUID(obj), "R2R_Found" + "(" + JITStats.GetMethodName(obj) + ")"); } }
public static IEnumerable <StartStopThreadEventData> Stackify(IEnumerable <StartStopThreadEventData> inputStream) { Stack <StartStopThreadEventData> currentPerThreadProcessingState = new Stack <StartStopThreadEventData>(); foreach (var startStopIn in inputStream) { var startStop = startStopIn; if (currentPerThreadProcessingState.Count > 0) { while ((currentPerThreadProcessingState.Count > 0) && (currentPerThreadProcessingState.Peek().End.CompareTo(startStop.Start) < 0)) { // Current stack top event finished before this event happened. var poppedEvent = currentPerThreadProcessingState.Pop(); EventUID lastEventProcessedEnd = poppedEvent.End; if (currentPerThreadProcessingState.Count > 0) { var tempPoppedEvent = currentPerThreadProcessingState.Pop(); tempPoppedEvent.Start = lastEventProcessedEnd; yield return(tempPoppedEvent); currentPerThreadProcessingState.Push(tempPoppedEvent); } } } startStop.StackDepth = currentPerThreadProcessingState.Count; yield return(startStop); currentPerThreadProcessingState.Push(startStop); } }
public StartStopThreadEventData(EventUID start, EventUID end, string name) { Start = start; End = end; Name = name; StackDepth = 0; }
public Task <bool> AddAmount(decimal amount, EventUID uniqueId = null) { return(ConcurrentRaiseEvent((snapshot, func) => { var evt = new AmountAddEvent(amount, snapshot.State.Balance + amount); return func(evt, uniqueId); })); }
protected void TransactionRaiseEvent(IEvent @event, EventUID uniqueId = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "Start raise event by transaction, grain Id ={0} and state version = {1},event type = {2} ,event = {3},uniqueueId = {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), uniqueId); } if (!TransactionPending) { var ex = new UnopenTransactionException(GrainId.ToString(), GrainType, nameof(TransactionRaiseEvent)); if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.TransactionGrainTransactionFlow, ex, ex.Message); } throw ex; } try { Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var fullyEvent = new FullyEvent <PrimaryKey> { StateId = GrainId, Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 } }; if (uniqueId == default) { uniqueId = EventUID.Empty; } if (string.IsNullOrEmpty(uniqueId.UID)) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } else { fullyEvent.Base.Timestamp = uniqueId.Timestamp; } WaitingForTransactionEvents.Add(new TransactionTransport <PrimaryKey>(fullyEvent, uniqueId.UID, fullyEvent.StateId.ToString())); EventHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.TransactionGrainTransactionFlow, "Raise event successfully, grain Id= {0} and state version is {1}}", GrainId.ToString(), Snapshot.Base.Version); } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Critical)) { Logger.LogCritical(LogEventIds.TransactionGrainTransactionFlow, ex, "Grain Id = {0},event type = {1} and event = {2}", GrainId.ToString(), @event.GetType().FullName, Serializer.SerializeToString(@event)); } Snapshot.Base.DecrementDoingVersion();//还原doing Version throw; } }
public Task TransferArrived(decimal amount, EventUID uid) { var evt = new TransferArrivedEvent { Amount = amount, Balance = Snapshot.State.Balance + amount }; return(RaiseEvent(evt, uid)); }
public Task <bool> TransferRefunds(decimal amount, EventUID uid) { var evt = new TransferRefundsEvent { Amount = amount, Balance = Snapshot.State.Balance + amount }; return(RaiseEvent(evt, uid)); }
protected async Task TxRaiseEvent(long transactionId, IEvent @event, EventUID uniqueId = null) { if (transactionId <= 0) { throw new TxIdException(); } if (transactionId != CurrentTransactionId) { await BeginTransaction(transactionId); } TxRaiseEvent(@event, uniqueId); }
public Task <bool> TransferRefunds(decimal amount, EventUID uid) { return(ConcurrentRaiseEvent(async(snapshot, func) => { var evt = new TransferRefundsEvent { Amount = amount, Balance = Snapshot.State.Balance + amount }; await func(evt, null); })); }
protected override async Task <bool> RaiseEvent(IEvent @event, EventUID uniqueId = null) { if (TransactionPending) { var ex = new TransactionProcessingSubmitEventException(GrainId.ToString(), GrainType); Logger.LogError(ex, ex.Message); throw ex; } var checkTask = TransactionStateCheck(); if (!checkTask.IsCompletedSuccessfully) { await checkTask; } return(await base.RaiseEvent(@event, uniqueId)); }
private void AddStartStopData(int processID, int threadId, EventUID start, EventUID end, string name) { if (!_processSpecificDataInProgress.TryGetValue(processID, out RuntimeLoaderProcessData processData)) { processData = new RuntimeLoaderProcessData(end.Time, processID); _processSpecificDataInProgress[processID] = processData; } if (!processData.StartStopEvents.ContainsKey(threadId)) { processData.StartStopEvents[threadId] = new List <StartStopThreadEventData>(); } List <StartStopThreadEventData> startStopData = processData.StartStopEvents[threadId]; startStopData.Add(new StartStopThreadEventData(start, end, name)); }
/// <summary> /// 事务性事件提交 /// 使用该函数前必须开启事务,不然会出现异常 /// </summary> /// <param name="event"></param> /// <param name="uniqueId"></param> protected void TxRaiseEvent(IEvent @event, EventUID uniqueId = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start transactionRaiseEvent, grain Id ={0} and state version = {1},event type = {2} ,event = {3},uniqueueId = {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), uniqueId); } try { if (CurrentTransactionStartVersion == -1) { throw new UnopenedTransactionException(GrainId.ToString(), GrainType, nameof(TxRaiseEvent)); } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var fullyEvent = new FullyEvent <PrimaryKey> { StateId = GrainId, Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 } }; if (uniqueId == default) { uniqueId = EventUID.Empty; } if (string.IsNullOrEmpty(uniqueId.UID)) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } else { fullyEvent.Base.Timestamp = uniqueId.Timestamp; } WaitingForTransactionTransports.Add(new EventTransport <PrimaryKey>(fullyEvent, uniqueId.UID, fullyEvent.StateId.ToString())); SnapshotHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version } catch (Exception ex) { Logger.LogCritical(ex, "Grain Id = {0},event type = {1} and event = {2}", GrainId.ToString(), @event.GetType().FullName, Serializer.SerializeToString(@event)); Snapshot.Base.DecrementDoingVersion();//还原doing Version throw; } }
/// <summary> /// 事务性事件提交 /// 使用该函数前必须开启事务,不然会出现异常 /// </summary> /// <param name="event"></param> /// <param name="eUID"></param> protected void TxRaiseEvent(IEvent @event, EventUID eUID = null) { try { if (CurrentTransactionStartVersion == -1) { throw new UnopenedTransactionException(GrainId.ToString(), GrainType, nameof(TxRaiseEvent)); } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var fullyEvent = new FullyEvent <PrimaryKey> { StateId = GrainId, Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 } }; string unique = default; if (eUID is null) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); unique = fullyEvent.GetEventId(); } else { fullyEvent.Base.Timestamp = eUID.Timestamp; unique = eUID.UID; } WaitingForTransactionTransports.Add(new EventTransport <PrimaryKey>(fullyEvent, unique, fullyEvent.StateId.ToString())); SnapshotHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("TxRaiseEvent completed: {0}->{1}->{2}", GrainType.FullName, Serializer.Serialize(fullyEvent), Serializer.Serialize(Snapshot)); } } catch (Exception ex) { Logger.LogCritical(ex, "TxRaiseEvent failed: {0}->{1}->{2}", GrainType.FullName, Serializer.Serialize(@event, @event.GetType()), Serializer.Serialize(Snapshot)); Snapshot.Base.DecrementDoingVersion();//还原doing Version throw; } }
protected override async Task <bool> RaiseEvent(IEvent @event, EventUID uniqueId = null) { if (await TransactionSemaphore.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { SnapshotCheck(); return(await base.RaiseEvent(@event, uniqueId)); } finally { TransactionSemaphore.Release(); } } else { throw new BeginTxTimeoutException(GrainId.ToString(), -1, GrainType); } }
private void Clr_TypeLoadStop(TypeLoadStopTraceData obj) { IdOfIncompleteAction id = new IdOfIncompleteAction(); id.Identifier = obj.TypeLoadStartID; id.ThreadID = obj.ThreadID; // If we had a TypeLoad start lookup event, capture that start time, otherwise, use the TypeLoadStop // data as both start and stop EventUID startUID = new EventUID(obj); if (_incompleteTypeLoadEvents.TryGetValue(id, out IncompleteActionDesc typeLoadStartData)) { startUID = typeLoadStartData.Start; _incompleteTypeLoadEvents.Remove(id); } AddStartStopData(obj.ProcessID, id.ThreadID, startUID, new EventUID(obj), $"TypeLoad ({obj.TypeName}, {obj.LoadLevel})"); }
/// <summary> /// 不依赖当前状态的的事件的并发处理 /// 如果事件的产生依赖当前状态,请使用<see cref="ConcurrentRaiseEvent(Func{Snapshot{PrimaryKey, SnapshotType}, Func{IEvent, EventUID, Task}, Task}, Func{bool, ValueTask}, Action{Exception})"/> /// </summary> /// <param name="event">不依赖当前状态的事件</param> /// <param name="uniqueId">幂等性判定值</param> /// <param name="hashKey">消息异步分发的唯一hash的key</param> /// <returns></returns> protected async Task <bool> ConcurrentRaiseEvent(IEvent evt, EventUID uniqueId = null) { var taskSource = new TaskCompletionSource <bool>(); var task = ConcurrentRaiseEvent(async(state, eventFunc) => { await eventFunc(evt, uniqueId); }, isOk => { taskSource.TrySetResult(isOk); return(Consts.ValueTaskDone); }, ex => { taskSource.TrySetException(ex); }); if (!task.IsCompletedSuccessfully) { await task; } return(await taskSource.Task); }
public Task EventHandle(TransferEvent evt, EventUID uid) { var toActor = GrainFactory.GetGrain <IAccount>(evt.ToId); return(toActor.TransferArrived(evt.Amount, uid)); }
protected virtual async Task <bool> RaiseEvent(IEvent @event, EventUID uniqueId = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start raise event, grain Id ={0} and state version = {1},event type = {2} ,event ={3},uniqueueId= {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), uniqueId); } if (Snapshot.Base.IsOver) { throw new StateIsOverException(Snapshot.Base.StateId.ToString(), GrainType); } try { var fullyEvent = new FullyEvent <PrimaryKey> { Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 }, StateId = Snapshot.Base.StateId }; if (uniqueId == default) { uniqueId = EventUID.Empty; } if (string.IsNullOrEmpty(uniqueId.UID)) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } else { fullyEvent.Base.Timestamp = uniqueId.Timestamp; } var startTask = OnRaiseStart(fullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var bytesTransport = new EventBytesTransport( TypeContainer.GetTypeCode(@event.GetType()), Snapshot.Base.StateId, fullyEvent.Base.GetBytes(), Serializer.SerializeToBytes(@event) ); if (await EventStorage.Append(fullyEvent, in bytesTransport, uniqueId.UID)) { EventHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version var task = OnRaiseSuccessed(fullyEvent, bytesTransport); if (!task.IsCompletedSuccessfully) { await task; } var saveSnapshotTask = SaveSnapshotAsync(); if (!saveSnapshotTask.IsCompletedSuccessfully) { await saveSnapshotTask; } await PublishToEventBust(bytesTransport); if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Raise event successfully, grain Id= {0} and state version = {1}", GrainId.ToString(), Snapshot.Base.Version); } return(true); } else { Snapshot.Base.DecrementDoingVersion();//还原doing Version if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation("Raise event failure because of idempotency limitation, grain Id = {0},state version = {1},event type = {2} with version = {3}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, fullyEvent.Base.Version); } var task = OnRaiseFailed(fullyEvent); if (!task.IsCompletedSuccessfully) { await task; } } }
protected virtual async Task <bool> RaiseEvent(IEvent @event, EventUID uniqueId = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start raise event, grain Id ={0} and state version = {1},event type = {2} ,event ={3},uniqueueId= {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), uniqueId); } if (Snapshot.Base.IsOver) { throw new StateIsOverException(Snapshot.Base.StateId.ToString(), GrainType); } try { var fullyEvent = new FullyEvent <PrimaryKey> { Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 }, StateId = Snapshot.Base.StateId }; if (uniqueId == default) { uniqueId = EventUID.Empty; } if (string.IsNullOrEmpty(uniqueId.UID)) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } else { fullyEvent.Base.Timestamp = uniqueId.Timestamp; } var startTask = OnRaiseStart(fullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var bytesTransport = new EventBytesTransport { EventType = @event.GetType().FullName, GrainId = Snapshot.Base.StateId, EventBytes = Serializer.SerializeToBytes(@event), BaseBytes = fullyEvent.Base.GetBytes() }; if (await EventStorage.Append(fullyEvent, bytesTransport, uniqueId.UID)) { Snapshot.Apply(EventHandler, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version var task = OnRaiseSuccessed(fullyEvent, bytesTransport); if (!task.IsCompletedSuccessfully) { await task; } var saveSnapshotTask = SaveSnapshotAsync(); if (!saveSnapshotTask.IsCompletedSuccessfully) { await saveSnapshotTask; } var handlers = FollowUnit.GetAllEventHandlers(); if (handlers.Count > 0) { try { if (CoreOptions.PriorityAsyncEventBus) { try { var publishTask = EventBusProducer.Publish(bytesTransport.GetBytes(), GrainId.ToString()); if (!publishTask.IsCompletedSuccessfully) { await publishTask; } } catch (Exception ex) { Logger.LogError(ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); //当消息队列出现问题的时候同步推送 await Task.WhenAll(handlers.Select(func => func(bytesTransport.GetBytes()))); } } else { try { await Task.WhenAll(handlers.Select(func => func(bytesTransport.GetBytes()))); } catch (Exception ex) { Logger.LogError(ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); //当消息队列出现问题的时候异步推送 var publishTask = EventBusProducer.Publish(bytesTransport.GetBytes(), GrainId.ToString()); if (!publishTask.IsCompletedSuccessfully) { await publishTask; } } } } catch (Exception ex) { Logger.LogError(ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); } } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Raise event successfully, grain Id= {0} and state version = {1}}", GrainId.ToString(), Snapshot.Base.Version); } return(true); } else { if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation("Raise event failure because of idempotency limitation, grain Id = {0},state version = {1},event type = {2} with version = {3}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, fullyEvent.Base.Version); } var task = OnRaiseFailed(fullyEvent); if (!task.IsCompletedSuccessfully) { await task; } Snapshot.Base.DecrementDoingVersion();//还原doing Version } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(ex, "Raise event produces errors, state Id = {0}, version ={1},event type = {2},event = {3}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event)); } await RecoverySnapshot();//还原状态 throw; } return(false); }
public Task <bool> AddAmount(decimal amount, EventUID uniqueId = null) { var evt = new AmountAddEvent(amount, Snapshot.State.Balance + amount); return(RaiseEvent(evt, uniqueId)); }
protected virtual async Task <bool> RaiseEvent(IEvent @event, EventUID eUID = null) { if (Snapshot.Base.IsOver) { throw new StateIsOverException(Snapshot.Base.StateId.ToString(), GrainType); } try { var fullyEvent = new FullyEvent <PrimaryKey> { Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 }, StateId = Snapshot.Base.StateId }; string unique = default; if (eUID is null) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); unique = fullyEvent.GetEventId(); } else { fullyEvent.Base.Timestamp = eUID.Timestamp; unique = eUID.UID; } var startTask = OnRaiseStart(fullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var evtType = @event.GetType(); var bytesTransport = new EventBytesTransport( TypeFinder.GetCode(evtType), Snapshot.Base.StateId, fullyEvent.Base.GetBytes(), Serializer.SerializeToUtf8Bytes(@event, evtType) ); if (await EventStorage.Append(fullyEvent, in bytesTransport, unique)) { SnapshotHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version var task = OnRaised(fullyEvent, bytesTransport); if (!task.IsCompletedSuccessfully) { await task; } var saveSnapshotTask = SaveSnapshotAsync(); if (!saveSnapshotTask.IsCompletedSuccessfully) { await saveSnapshotTask; } await PublishToEventBus(bytesTransport.GetBytes(), GrainId.ToString()); if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("RaiseEvent completed: {0}->{1}->{2}", GrainType.FullName, Serializer.Serialize(fullyEvent), Serializer.Serialize(Snapshot)); } return(true); } else { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("RaiseEvent failed: {0}->{1}->{2}", GrainType.FullName, Serializer.Serialize(fullyEvent), Serializer.Serialize(Snapshot)); } Snapshot.Base.DecrementDoingVersion();//还原doing Version var task = OnRaiseFailed(fullyEvent); if (!task.IsCompletedSuccessfully) { await task; } } }
public Task EventHandle(TopupEvent evt, EventBase eventBase, EventUID fullyEvent) { //此处更新db return(Task.CompletedTask); }
public Task AmountAddEventHandler(AmountTransferEvent value, EventUID uid) { var toActor = grainFactory.GetGrain <IAccount>(value.ToAccountId); return(toActor.AddAmount(value.Amount, uid)); }