protected async ValueTask BeginTransaction() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Begin transaction with id {0},transaction start state version {1}", GrainId.ToString(), TransactionStartVersion.ToString()); } try { if (TransactionPending) { if ((DateTimeOffset.UtcNow - BeginTransactionTime).TotalSeconds > CoreOptions.TransactionTimeoutSeconds) { var rollBackTask = RollbackTransaction();//事务阻赛超过一分钟自动回滚 if (!rollBackTask.IsCompletedSuccessfully) { await rollBackTask; } Logger.LogError("Transaction timeout, automatic rollback,grain id = {1}", GrainId.ToString()); } else { throw new RepeatedTransactionException(GrainId.ToString(), GetType()); } } var checkTask = TransactionStateCheck(); if (!checkTask.IsCompletedSuccessfully) { await checkTask; } TransactionPending = true; TransactionStartVersion = Snapshot.Base.Version; BeginTransactionTime = DateTimeOffset.UtcNow; if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Begin transaction successfully with id {0},transaction start state version {1}", GrainId.ToString(), TransactionStartVersion.ToString()); } } catch (Exception ex) { Logger.LogCritical(ex, "Begin transaction failed, grain Id = {1}", GrainId.ToString()); throw; } }
protected async Task CommitTransaction() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Commit transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionEvents.Count.ToString(), TransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (WaitingForTransactionEvents.Count > 0) { try { foreach (var transport in WaitingForTransactionEvents) { var startTask = OnRaiseStart(transport.FullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } transport.BytesTransport = new EventBytesTransport { EventType = transport.FullyEvent.Event.GetType().FullName, ActorId = GrainId, EventBytes = Serializer.SerializeToBytes(transport.FullyEvent.Event), BaseBytes = transport.FullyEvent.Base.GetBytes() }; } await EventStorage.TransactionBatchAppend(WaitingForTransactionEvents); foreach (var transport in WaitingForTransactionEvents) { var task = OnRaiseSuccessed(transport.FullyEvent, transport.BytesTransport); if (!task.IsCompletedSuccessfully) { await task; } } var saveSnapshotTask = SaveSnapshotAsync(); if (!saveSnapshotTask.IsCompletedSuccessfully) { await saveSnapshotTask; } var handlers = FollowUnit.GetAllEventHandlers(); if (handlers.Count > 0) { try { foreach (var transport in WaitingForTransactionEvents) { if (CoreOptions.PriorityAsyncEventBus) { try { var publishTask = EventBusProducer.Publish(transport.BytesTransport.GetBytes(), transport.HashKey); 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(transport.BytesTransport.GetBytes()))); } } else { try { await Task.WhenAll(handlers.Select(func => func(transport.BytesTransport.GetBytes()))); } catch (Exception ex) { Logger.LogError(ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); //当消息队列出现问题的时候异步推送 var publishTask = EventBusProducer.Publish(transport.BytesTransport.GetBytes(), transport.HashKey); 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("Commit transaction with id {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionEvents.Count.ToString(), TransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } } catch (Exception ex) { Logger.LogError(ex, "Commit transaction failed, grain Id = {1}", GrainId.ToString()); throw; } finally { WaitingForTransactionEvents.Clear(); TransactionPending = false; } } }
protected async ValueTask RollbackTransaction() { if (TransactionPending) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Rollback transaction successfully with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionEvents.Count.ToString(), TransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } try { if (BackupSnapshot.Base.Version == TransactionStartVersion) { Snapshot = new Snapshot <PrimaryKey, State>(GrainId) { Base = BackupSnapshot.Base.Clone(), State = BackupSnapshot.State.Clone() }; } else { await RecoveryState(); } WaitingForTransactionEvents.Clear(); TransactionPending = false; if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Rollback transaction successfully with id = {0},state version = {1}", GrainId.ToString(), Snapshot.Base.Version.ToString()); } } catch (Exception ex) { Logger.LogCritical(ex, "Rollback transaction failed with Id = {1}", GrainId.ToString()); throw; } } }