public async Task RollbackTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start rollback transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionTransports.Count.ToString(), CurrentTransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (CurrentTransactionId == transactionId && CurrentTransactionStartVersion != -1 && Snapshot.Base.Version >= CurrentTransactionStartVersion) { try { if (BackupSnapshot.Base.Version == CurrentTransactionStartVersion - 1) { Snapshot = new Snapshot <PrimaryKey, StateType>(GrainId) { Base = BackupSnapshot.Base.Clone(), State = BackupSnapshot.State.Clone() }; } else { if (BackupSnapshot.Base.Version >= CurrentTransactionStartVersion) { await EventStorage.DeleteEnd(Snapshot.Base.StateId, CurrentTransactionStartVersion, Snapshot.Base.LatestMinEventTimestamp); } await RecoverySnapshot(); } WaitingForTransactionTransports.Clear(); RestoreTransactionTemporaryState(); TransactionSemaphore.Release(); 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; } } }
protected async Task BeginTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Begin transaction with grainid {0} and transactionId {1},transaction start state version {2}", GrainId.ToString(), transactionId, CurrentTransactionStartVersion.ToString()); } if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { if (await TransactionTimeoutLock.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { await RollbackTransaction(CurrentTransactionId);//事务超时自动回滚 Logger.LogError("Transaction timeout, automatic rollback,grain id = {1}", GrainId.ToString()); } } finally { TransactionTimeoutLock.Release(); } } } if (await TransactionSemaphore.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { SnapshotCheck(); CurrentTransactionStartVersion = Snapshot.Base.Version + 1; CurrentTransactionId = transactionId; TransactionStartMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } catch { TransactionSemaphore.Release(); throw; } } else { throw new BeginTxTimeoutException(GrainId.ToString(), transactionId, GrainType); } }
public async Task CommitTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Commit transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionTransports.Count.ToString(), CurrentTransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (WaitingForTransactionTransports.Count > 0) { if (CurrentTransactionId != transactionId) { throw new TxCommitException(); } try { var onCommitTask = OnCommitTransaction(transactionId); if (!onCommitTask.IsCompletedSuccessfully) { await onCommitTask; } foreach (var transport in WaitingForTransactionTransports) { var startTask = OnRaiseStart(transport.FullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } transport.BytesTransport = new EventBytesTransport( TypeContainer.GetTypeCode(transport.FullyEvent.Event.GetType()), GrainId, transport.FullyEvent.Base.GetBytes(), Serializer.SerializeToBytes(transport.FullyEvent.Event) ); } await EventStorage.TransactionBatchAppend(WaitingForTransactionTransports); } catch (Exception ex) { Logger.LogError(ex, "Commit transaction failed, grain Id = {1}", GrainId.ToString()); throw; } } }
public async Task CommitTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Commit transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionTransports.Count.ToString(), CurrentTransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (WaitingForTransactionTransports.Count > 0) { if (CurrentTransactionId != transactionId) { throw new TransactionCommitException(); } try { //如果是带Id的事务,则加入事务事件,等待Complete if (transactionId > 0) { TransactionRaiseEvent(new TransactionCommitEvent(CurrentTransactionId, CurrentTransactionStartVersion + 1, WaitingForTransactionTransports.Min(t => t.FullyEvent.Base.Timestamp))); } foreach (var transport in WaitingForTransactionTransports) { var startTask = OnRaiseStart(transport.FullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } transport.BytesTransport = new EventBytesTransport { EventType = transport.FullyEvent.Event.GetType().FullName, GrainId = GrainId, EventBytes = Serializer.SerializeToBytes(transport.FullyEvent.Event), BaseBytes = transport.FullyEvent.Base.GetBytes() }; } await EventStorage.TransactionBatchAppend(WaitingForTransactionTransports); } catch (Exception ex) { Logger.LogError(ex, "Commit transaction failed, grain Id = {1}", GrainId.ToString()); throw; } } }