private static async Task StartSession <TStepId, TData>(ITransactionSession <TStepId, TData> session) #endif { try { session.TransactionContext.Definition.NotifyTransactionStarted(); #if NET35 || NOASYNC session.TransactionContext.SessionStorage.SessionStarted(session); #else await session.TransactionContext.SessionStorage.SessionStarted(session); #endif } catch (Exception e) { session.TransactionContext.Logger.ErrorFormat(e, "An error occurred during starting a session for transaction '{0}'.", session.TransactionContext.Info.Name); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, RunPostActions = false, Result = ResultType.Failed } .AddError(e)); } }
public static async Task PrepareStep <TStepId, TData>(this ITransactionSession <TStepId, TData> session) #endif { try { #if NET35 || NOASYNC session.TransactionContext.SessionStorage.StepPrepared(session); #else await session.TransactionContext.SessionStorage.StepPrepared(session); #endif } catch (Exception e) { string info = string.Format("Transaction '{0}': an error occurred during notifying ste prepared.", session.TransactionContext.Info.Name); session.TransactionContext.Logger.ErrorFormat(e, info); session.StepEnumerator.MovePrevious(); #if NET35 || NOASYNC RunUndoOperation.RunUndo(new RunUndoContext <TStepId, TData>() #else await RunUndoOperation.RunUndo(new RunUndoContext <TStepId, TData>() #endif { Session = session, CaughtException = e, Result = ResultType.Failed }); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, RunPostActions = false, Result = ResultType.Failed } .AddError(e)); } }
/// <summary> /// Creates a session. /// </summary> /// <param name="runSettings">The run settings.</param> /// <returns>The session.</returns> private async Task <ITransactionSession <TStepId, TData> > CreateSession(IRunSettings <TStepId, TData> runSettings) #endif { TransactionSession <TStepId, TData> session = new TransactionSession <TStepId, TData> { RunSettings = runSettings, TransactionContext = this.context }; session.StepEnumeratorInstance = new StepEnumerator <TStepId, TData>(session) { Data = runSettings.Data }; switch (runSettings.Mode) { case RunMode.Run: break; case RunMode.RecoverAndUndoAndRun: case RunMode.RecoverAndContinue: ITransactionData <TData> recoveredData = null; try { #if NET35 || NOASYNC recoveredData = this.context.SessionStorage.RecoverTransaction(); #else recoveredData = await this.context.SessionStorage.RecoverTransaction(); #endif } catch (Exception e) { this.context.Logger.ErrorFormat(e, "An error occurred during recovering the transaction '{0}'.", this.context.Info.Name); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, RunPostActions = false, Result = ResultType.Failed } .AddError(e)); return(session); } if (recoveredData == null) { this.context.Logger.InfoFormat("Transaction '{0}': no session to recover.", this.context.Info.Name); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, Result = ResultType.NoTransactionToRecover, RunPostActions = false }); return(session); } else { session.Recover(recoveredData); } break; default: throw new ArgumentException(string.Format("Transaction '{0}': unknown run mode '{1}'.", this.context.Info.Name, runSettings.Mode)); } session.StepEnumeratorInstance.FillStep(); return(session); }
public static async Task ProcessUndo <TStepId, TData>(RunUndoContext <TStepId, TData> context) #endif { ITransactionStep <TStepId, TData> currentStep = context.Session.StepEnumerator.CurrentStep; ITransactionSession <TStepId, TData> session = context.Session; Stopwatch watch = new Stopwatch(); try { watch.Start(); #if NET35 || NOASYNC currentStep.UndoAction(session.StepEnumerator.Data, session); #else if (currentStep.UndoAction != null) { currentStep.UndoAction(session.StepEnumerator.Data, session); } else { await currentStep.AsyncUndoAction(session.StepEnumerator.Data, session); } #endif watch.Stop(); #if NET35 || NOASYNC context.Session.TransactionContext.SessionStorage.StepReceding(session); #else await context.Session.TransactionContext.SessionStorage.StepReceding(session); #endif if (session.ShouldLogStepExecution()) { session.TransactionContext .Logger .LogExecutionTime( watch.Elapsed, "Transaction '{0}': execution time for undo step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id); } } catch (Exception e) { watch.Stop(); string info = string.Format( "Transaction '{0}': an error occurred during processing undo step action for step '{1}' with id '{2}', execution time '{3}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, currentStep.Id, watch.Elapsed); session.TransactionContext.Logger.ErrorFormat(e, info); #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = context.Session, RunPostActions = false, Result = ResultType.Failed } .AddError(context.CaughtException) .AddError(e)); } }
public static async Task RunSession <TStepId, TData>(ITransactionSession <TStepId, TData> session) #endif { while (true) { ITransactionStep <TStepId, TData> step = session.StepEnumerator.CurrentStep; if (step == null) { #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { Session = session, RunPostActions = true, Result = ResultType.Success }); return; } #if NET35 || NOASYNC session.PrepareStep(); #else await session.PrepareStep(); #endif if (session.Ended) { return; } if (session.Recovered && step.Settings.NotRunOnRecovered()) { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': ignoring step '{1}' with id '{2}' as the step cannot be executed on a recovered transaction.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MoveNext(); continue; } session.TransactionContext .Logger .DebugFormat( "Transaction '{0}: running step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); IExecutor executor = session.StepEnumerator.CurrentStep.StepActionExecutor; if (executor != null && executor.ShouldRun) { #if NET35 || NOASYNC executor.Run(() => { session.ProcessStep(); if (!session.Ended) { RunSessionOperation.MoveToNextStep(session, true); } }); #else executor.Run(async() => { await session.ProcessStep(); if (!session.Ended) { await RunSessionOperation.MoveToNextStep(session, true); } }); #endif return; } else { #if NET35 || NOASYNC session.ProcessStep(); #else await session.ProcessStep(); #endif if (session.Ended) { return; } #if NET35 || NOASYNC RunSessionOperation.MoveToNextStep(session, false); #else await RunSessionOperation.MoveToNextStep(session, false); #endif } } }
public static async Task RunUndo <TStepId, TData>(RunUndoContext <TStepId, TData> context) #endif { while (context.ProcessStepPredicate(context.Session.StepEnumerator.CurrentStep)) { ITransactionStep <TStepId, TData> step = context.Session.StepEnumerator.CurrentStep; if (step == null) { if (context.NoSessionEnd) { #if NET35 || NOASYNC context.UndoFinishAction(); #else await context.UndoFinishAction(); #endif return; } #if NET35 || NOASYNC SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #else await SessionEndPreparationOperation.PrepareEndSession(new SessionEndContext <TStepId, TData>() #endif { RunPostActions = false, Session = context.Session, Result = context.Result } .AddError(context.CaughtException)); return; } ITransactionSession <TStepId, TData> session = context.Session; if (session.Recovered && step.Settings.NotRunOnRecovered()) { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': ignoring the undo step action for step '{1}' with id '{2}' as the step cannot be executed on a recovered transaction.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MovePrevious(); continue; } #if NET35 || NOASYNC if (step.UndoAction == null) #else if (step.UndoAction == null && step.AsyncUndoAction == null) #endif { session.TransactionContext .Logger .DebugFormat( "Transaction '{0}': no undo step action for step '{1}' with id '{2}'.", session.TransactionContext.Info.Name, session.StepEnumerator.CurrentStepIndex, session.StepEnumerator.CurrentStep.Id); session.StepEnumerator.MovePrevious(); continue; } IExecutor executor = step.UndoActionExecutor != null ? step.UndoActionExecutor : step.Settings.SameExecutorForAllActions() ? step.StepActionExecutor : null; if (executor != null && executor.ShouldRun) { #if NET35 || NOASYNC executor.Run(() => { ProcessUndoOperation.ProcessUndo(context); if (!session.Ended) { session.StepEnumerator.MovePrevious(); RunUndoOperation.RunUndo(context); } }); #else executor.Run(async() => { await ProcessUndoOperation.ProcessUndo(context); if (!session.Ended) { session.StepEnumerator.MovePrevious(); await RunUndoOperation.RunUndo(context); } }); #endif return; } else { #if NET35 || NOASYNC ProcessUndoOperation.ProcessUndo(context); #else await ProcessUndoOperation.ProcessUndo(context); #endif session.StepEnumerator.MovePrevious(); } } #if NET35 || NOASYNC context.UndoFinishAction(); #else await context.UndoFinishAction(); #endif }