Fixing random exceptions in Orchard.Workflows

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2013-02-20 12:19:00 -08:00
parent ab9d9d2d79
commit 9d081860cb
5 changed files with 97 additions and 90 deletions

View File

@@ -43,7 +43,11 @@ namespace Orchard.Workflows.Models {
} }
public object GetState(string key) { public object GetState(string key) {
return GetState<object>(key); if (State == null) {
return null;
}
return State[key];
} }
public void SetStateFor<T>(ActivityRecord record, string key, T value) { public void SetStateFor<T>(ActivityRecord record, string key, T value) {

View File

@@ -19,8 +19,9 @@ namespace Orchard.Workflows {
builder.Add().DefineStyle("WorkflowsActivities-SendEmail").SetUrl("workflows-activity-sendemail.css").SetDependencies("WorkflowsAdmin"); builder.Add().DefineStyle("WorkflowsActivities-SendEmail").SetUrl("workflows-activity-sendemail.css").SetDependencies("WorkflowsAdmin");
builder.Add().DefineStyle("WorkflowsActivities-Timer").SetUrl("workflows-activity-timer.css").SetDependencies("WorkflowsAdmin"); builder.Add().DefineStyle("WorkflowsActivities-Timer").SetUrl("workflows-activity-timer.css").SetDependencies("WorkflowsAdmin");
builder.Add().DefineStyle("WorkflowsActivities-UserTask").SetUrl("workflows-activity-usertask.css").SetDependencies("WorkflowsAdmin"); builder.Add().DefineStyle("WorkflowsActivities-UserTask").SetUrl("workflows-activity-usertask.css").SetDependencies("WorkflowsAdmin");
builder.Add().DefineStyle("WorkflowsActivities").SetDependencies( builder.Add().DefineStyle("WorkflowsActivities").SetUrl("workflows-activity.css")
.SetDependencies(
"WorkflowsActivities-Branch", "WorkflowsActivities-Branch",
"WorkflowsActivities-ContentCreate", "WorkflowsActivities-ContentCreate",
"WorkflowsActivities-ContentPublished", "WorkflowsActivities-ContentPublished",

View File

@@ -17,7 +17,6 @@ namespace Orchard.Workflows.Services {
private readonly IRepository<ActivityRecord> _activityRepository; private readonly IRepository<ActivityRecord> _activityRepository;
private readonly IRepository<WorkflowRecord> _workflowRepository; private readonly IRepository<WorkflowRecord> _workflowRepository;
private readonly IRepository<AwaitingActivityRecord> _awaitingActivityRepository; private readonly IRepository<AwaitingActivityRecord> _awaitingActivityRepository;
private readonly IRepository<WorkflowDefinitionRecord> _workflowDefinitionRepository;
private readonly ITokenizer _tokenizer; private readonly ITokenizer _tokenizer;
public WorkflowManager( public WorkflowManager(
@@ -25,13 +24,11 @@ namespace Orchard.Workflows.Services {
IRepository<ActivityRecord> activityRepository, IRepository<ActivityRecord> activityRepository,
IRepository<WorkflowRecord> workflowRepository, IRepository<WorkflowRecord> workflowRepository,
IRepository<AwaitingActivityRecord> awaitingActivityRepository, IRepository<AwaitingActivityRecord> awaitingActivityRepository,
IRepository<WorkflowDefinitionRecord> workflowDefinitionRepository,
ITokenizer tokenizer) { ITokenizer tokenizer) {
_activitiesManager = activitiesManager; _activitiesManager = activitiesManager;
_activityRepository = activityRepository; _activityRepository = activityRepository;
_workflowRepository = workflowRepository; _workflowRepository = workflowRepository;
_awaitingActivityRepository = awaitingActivityRepository; _awaitingActivityRepository = awaitingActivityRepository;
_workflowDefinitionRepository = workflowDefinitionRepository;
_tokenizer = tokenizer; _tokenizer = tokenizer;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
@@ -75,41 +72,6 @@ namespace Orchard.Workflows.Services {
return; return;
} }
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens
};
// evaluate processing condition
awaitingActivities = awaitingActivities.Where(a => {
var activityContext = CreateActivityContext(a.ActivityRecord, tokens);
// check the condition
try {
return activity.CanExecute(workflowContext, activityContext);
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
return false;
}
}).ToList();
// evaluate processing condition
startedWorkflows = startedWorkflows.Where(a => {
var activityContext = CreateActivityContext(a, tokens);
// check the condition
try {
return activity.CanExecute(workflowContext, activityContext);
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
return false;
}
}).ToList();
// if no activity record is matching the event, do nothing // if no activity record is matching the event, do nothing
if (!startedWorkflows.Any() && !awaitingActivities.Any()) { if (!startedWorkflows.Any() && !awaitingActivities.Any()) {
return; return;
@@ -117,11 +79,57 @@ namespace Orchard.Workflows.Services {
// resume halted workflows // resume halted workflows
foreach (var awaitingActivityRecord in awaitingActivities) { foreach (var awaitingActivityRecord in awaitingActivities) {
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens,
Record = awaitingActivityRecord.WorkflowRecord
};
var activityContext = CreateActivityContext(awaitingActivityRecord.ActivityRecord, tokens);
// check the condition
try {
if (!activity.CanExecute(workflowContext, activityContext)) {
continue;
}
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
continue;
}
ResumeWorkflow(awaitingActivityRecord, workflowContext, tokens); ResumeWorkflow(awaitingActivityRecord, workflowContext, tokens);
} }
// start new workflows // start new workflows
foreach (var activityRecord in startedWorkflows) { foreach (var activityRecord in startedWorkflows) {
var workflowContext = new WorkflowContext {
Content = target,
Tokens = tokens,
};
var workflowRecord = new WorkflowRecord {
WorkflowDefinitionRecord = activityRecord.WorkflowDefinitionRecord,
State = "{}",
ContentItemRecord = workflowContext.Content.ContentItem.Record
};
workflowContext.Record = workflowRecord;
var activityContext = CreateActivityContext(activityRecord, tokens);
// check the condition
try {
if(!activity.CanExecute(workflowContext, activityContext)) {
continue;
}
}
catch (Exception e) {
Logger.Error("Error while evaluating an activity condition on {0}: {1}", name, e.ToString());
continue;
}
StartWorkflow(workflowContext, activityRecord, tokens); StartWorkflow(workflowContext, activityRecord, tokens);
} }
} }
@@ -135,16 +143,7 @@ namespace Orchard.Workflows.Services {
} }
private void StartWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) { private void StartWorkflow(WorkflowContext workflowContext, ActivityRecord activityRecord, IDictionary<string, object> tokens) {
// workflow halted, create a workflow state
var workflow = new WorkflowRecord {
WorkflowDefinitionRecord = activityRecord.WorkflowDefinitionRecord,
State = "{}",
ContentItemRecord = workflowContext.Content.ContentItem.Record
};
workflowContext.Record = workflow;
// signal every activity that the workflow is about to start // signal every activity that the workflow is about to start
var cancellationToken = new CancellationToken(); var cancellationToken = new CancellationToken();
InvokeActivities(activity => activity.OnWorkflowStarting(workflowContext, cancellationToken)); InvokeActivities(activity => activity.OnWorkflowStarting(workflowContext, cancellationToken));
@@ -165,11 +164,12 @@ namespace Orchard.Workflows.Services {
} }
else { else {
// workflow halted, create a workflow state // workflow halted, create a workflow state
_workflowRepository.Create(workflow); _workflowRepository.Create(workflowContext.Record);
foreach (var blocking in blockedOn) { foreach (var blocking in blockedOn) {
workflow.AwaitingActivities.Add(new AwaitingActivityRecord { workflowContext.Record.AwaitingActivities.Add(new AwaitingActivityRecord {
ActivityRecord = blocking, ActivityRecord = blocking,
WorkflowRecord = workflowContext.Record
}); });
} }
} }

View File

@@ -2,41 +2,42 @@
@using Orchard.Workflows.Models @using Orchard.Workflows.Models
<h1>@Html.TitleForPage(T("Running workflows").ToString()) </h1> <h1>@Html.TitleForPage(T("Running workflows").ToString()) </h1>
<fieldset> @using (Html.BeginFormAntiForgeryPost()) {
<table class="items"> <fieldset>
<thead> <table class="items">
<tr> <thead>
<th scope="col" class="checkbox">&nbsp;&darr;</th> <tr>
<th scope="col">@T("Worfklow Definition")</th> <th scope="col" class="checkbox">&nbsp;&darr;</th>
<th scope="col">Blocking activities</th> <th scope="col">@T("Worfklow Definition")</th>
<th scope="col" class="actions">&nbsp;</th> <th scope="col">Blocking activities</th>
</tr> <th scope="col" class="actions">&nbsp;</th>
</thead> </tr>
@if (Model.Workflows.Count == 0) { </thead>
@T("No workflows associated with this content item.") @if (Model.Workflows.Count == 0) {
} @T("No workflows associated with this content item.")
}
@foreach (WorkflowRecord workflow in Model.Workflows) { @foreach (WorkflowRecord workflow in Model.Workflows) {
<tr> <tr>
<td> <td>
&nbsp; &nbsp;
</td> </td>
<td> <td>
@Html.ActionLink(workflow.WorkflowDefinitionRecord.Name, "Edit", new { id = workflow.WorkflowDefinitionRecord.Id }) @Html.ActionLink(workflow.WorkflowDefinitionRecord.Name, "Edit", new {id = workflow.WorkflowDefinitionRecord.Id})
</td> </td>
<td> <td>
@foreach (AwaitingActivityRecord awaiting in workflow.AwaitingActivities) { @foreach (AwaitingActivityRecord awaiting in workflow.AwaitingActivities) {
@awaiting.ActivityRecord.Name.CamelFriendly() @awaiting.ActivityRecord.Name.CamelFriendly()
<br/> <br/>
} }
&nbsp; &nbsp;
</td> </td>
<td> <td>
@Html.ActionLink(T("Status").ToString(), "Edit", new { id = workflow.WorkflowDefinitionRecord.Id, workflowId = workflow.Id, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) | @Html.ActionLink(T("Status").ToString(), "Edit", new {id = workflow.WorkflowDefinitionRecord.Id, workflowId = workflow.Id, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl}) |
@Html.ActionLink(T("Delete").ToString(), "DeleteWorkflow", new { id = workflow.Id }, new { itemprop = "RemoveUrl UnsafeUrl", ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }) @Html.ActionLink(T("Delete").ToString(), "DeleteWorkflow", new {id = workflow.Id}, new {itemprop = "RemoveUrl UnsafeUrl", ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl})
</td> </td>
</tr> </tr>
} }
</table> </table>
</fieldset> </fieldset>
}