3c1f479b9d
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
178 lines
7.2 KiB
C#
178 lines
7.2 KiB
C#
//----------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//----------------------------------------------------------------
|
|
namespace System.Activities.Statements
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime;
|
|
using System.Threading;
|
|
using System.Collections.ObjectModel;
|
|
|
|
sealed class WorkflowCompensationBehavior : NativeActivity
|
|
{
|
|
Variable<CompensationToken> currentCompensationToken;
|
|
|
|
public WorkflowCompensationBehavior()
|
|
: base()
|
|
{
|
|
currentCompensationToken = new Variable<CompensationToken>
|
|
{
|
|
Name = "currentCompensationToken",
|
|
};
|
|
|
|
DefaultCompensation = new DefaultCompensation()
|
|
{
|
|
Target = new InArgument<CompensationToken>(this.currentCompensationToken),
|
|
};
|
|
|
|
DefaultConfirmation = new DefaultConfirmation()
|
|
{
|
|
Target = new InArgument<CompensationToken>(this.currentCompensationToken),
|
|
};
|
|
}
|
|
|
|
Activity DefaultCompensation
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
Activity DefaultConfirmation
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
protected override bool CanInduceIdle
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
protected override void CacheMetadata(NativeActivityMetadata metadata)
|
|
{
|
|
Fx.Assert(this.DefaultCompensation != null, "DefaultCompensation must be valid");
|
|
Fx.Assert(this.DefaultConfirmation != null, "DefaultConfirmation must be valid");
|
|
metadata.SetImplementationChildrenCollection(
|
|
new Collection<Activity>
|
|
{
|
|
this.DefaultCompensation,
|
|
this.DefaultConfirmation
|
|
});
|
|
|
|
metadata.SetImplementationVariablesCollection(new Collection<Variable> { this.currentCompensationToken });
|
|
}
|
|
|
|
protected override void Execute(NativeActivityContext context)
|
|
{
|
|
Bookmark mainRootCompleteBookmark = context.CreateBookmark(OnMainRootComplete, BookmarkOptions.NonBlocking);
|
|
context.RegisterMainRootCompleteCallback(mainRootCompleteBookmark);
|
|
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
compensationExtension.WorkflowCompensation = context.CreateBookmark(new BookmarkCallback(OnCompensate));
|
|
compensationExtension.WorkflowConfirmation = context.CreateBookmark(new BookmarkCallback(OnConfirm));
|
|
|
|
Fx.Assert(compensationExtension.WorkflowCompensationScheduled != null, "compensationExtension.WorkflowCompensationScheduled bookmark must be setup by now");
|
|
context.ResumeBookmark(compensationExtension.WorkflowCompensationScheduled, null);
|
|
}
|
|
|
|
protected override void Cancel(NativeActivityContext context)
|
|
{
|
|
context.CancelChildren();
|
|
}
|
|
|
|
void OnMainRootComplete(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
CompensationTokenData rootHandle = compensationExtension.Get(CompensationToken.RootCompensationId);
|
|
Fx.Assert(rootHandle != null, "rootToken must be valid");
|
|
|
|
ActivityInstanceState completionState = (ActivityInstanceState)value;
|
|
|
|
if (completionState == ActivityInstanceState.Closed)
|
|
{
|
|
context.ResumeBookmark(compensationExtension.WorkflowConfirmation, new CompensationToken(rootHandle));
|
|
}
|
|
else if (completionState == ActivityInstanceState.Canceled)
|
|
{
|
|
context.ResumeBookmark(compensationExtension.WorkflowCompensation, new CompensationToken(rootHandle));
|
|
}
|
|
else if (completionState == ActivityInstanceState.Faulted)
|
|
{
|
|
// Do nothing. Neither Compensate nor Confirm.
|
|
// Remove the bookmark to complete the WorkflowCompensationBehavior execution.
|
|
context.RemoveBookmark(compensationExtension.WorkflowConfirmation);
|
|
context.RemoveBookmark(compensationExtension.WorkflowCompensation);
|
|
}
|
|
}
|
|
|
|
void OnCompensate(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
CompensationToken rootToken = (CompensationToken)value;
|
|
Fx.Assert(rootToken != null, "rootToken must be passed");
|
|
|
|
this.currentCompensationToken.Set(context, rootToken);
|
|
|
|
CompensationTokenData rootTokenData = compensationExtension.Get(rootToken.CompensationId);
|
|
if (rootTokenData.ExecutionTracker.Count > 0)
|
|
{
|
|
context.ScheduleActivity(DefaultCompensation, new CompletionCallback(OnCompensationComplete));
|
|
}
|
|
else
|
|
{
|
|
OnCompensationComplete(context, null);
|
|
}
|
|
}
|
|
|
|
void OnCompensationComplete(NativeActivityContext context, ActivityInstance completedInstance)
|
|
{
|
|
// Remove bookmark.... have a cleanup book mark method...
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
context.RemoveBookmark(compensationExtension.WorkflowConfirmation);
|
|
}
|
|
|
|
void OnConfirm(NativeActivityContext context, Bookmark bookmark, object value)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
CompensationToken rootToken = (CompensationToken)value;
|
|
Fx.Assert(rootToken != null, "rootToken must be passed");
|
|
|
|
this.currentCompensationToken.Set(context, rootToken);
|
|
|
|
CompensationTokenData rootTokenData = compensationExtension.Get(rootToken.CompensationId);
|
|
if (rootTokenData.ExecutionTracker.Count > 0)
|
|
{
|
|
context.ScheduleActivity(DefaultConfirmation, new CompletionCallback(OnConfirmationComplete));
|
|
}
|
|
else
|
|
{
|
|
OnConfirmationComplete(context, null);
|
|
}
|
|
}
|
|
|
|
void OnConfirmationComplete(NativeActivityContext context, ActivityInstance completedInstance)
|
|
{
|
|
CompensationExtension compensationExtension = context.GetExtension<CompensationExtension>();
|
|
Fx.Assert(compensationExtension != null, "CompensationExtension must be valid");
|
|
|
|
context.RemoveBookmark(compensationExtension.WorkflowCompensation);
|
|
}
|
|
}
|
|
}
|
|
|
|
|