Feature: Thread-blocking task status completion

Thread can be blocked until a task completes (or a timeout period
elapses). Used to wait up to 3 seconds before redirecting to the
TaskStatus when downloading the Plugin Catalogue.
This commit is contained in:
Gary Sharp
2013-12-25 18:35:19 +11:00
parent ab553a05cb
commit 35391ad1a1
7 changed files with 55 additions and 24 deletions
+2
View File
@@ -90,6 +90,8 @@ namespace Disco.Services.Tasks
if (!this.Status.FinishedTimestamp.HasValue) // Scheduled Task Didn't Trigger 'Finished' if (!this.Status.FinishedTimestamp.HasValue) // Scheduled Task Didn't Trigger 'Finished'
this.Status.Finished(); this.Status.Finished();
this.Status.Finally();
var nextTriggerTime = context.NextFireTimeUtc; var nextTriggerTime = context.NextFireTimeUtc;
if (nextTriggerTime.HasValue) if (nextTriggerTime.HasValue)
{ // Continuous Task { // Continuous Task
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using Quartz; using Quartz;
using System.Web.Script.Serialization; using System.Web.Script.Serialization;
using System.Threading;
namespace Disco.Services.Tasks namespace Disco.Services.Tasks
{ {
@@ -15,6 +16,7 @@ namespace Disco.Services.Tasks
private string _triggerKey; private string _triggerKey;
private string _taskName; private string _taskName;
private Type _taskType; private Type _taskType;
private EventWaitHandle _waitHandle;
private bool _isSilent; private bool _isSilent;
private byte _progress; private byte _progress;
@@ -85,6 +87,7 @@ namespace Disco.Services.Tasks
{ {
this._taskName = Task.TaskName; this._taskName = Task.TaskName;
this._taskType = Task.GetType(); this._taskType = Task.GetType();
this._waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
this._sessionId = SessionId; this._sessionId = SessionId;
this._triggerKey = TriggerKey; this._triggerKey = TriggerKey;
@@ -285,8 +288,14 @@ namespace Disco.Services.Tasks
} }
UpdateTriggered(changedProperties.ToArray()); UpdateTriggered(changedProperties.ToArray());
} }
internal void Finally()
{
this._waitHandle.Set();
}
public void Reset(DateTime? NextScheduledTimestamp) public void Reset(DateTime? NextScheduledTimestamp)
{ {
this._waitHandle.Reset();
List<string> changedProperties = new List<string>(); List<string> changedProperties = new List<string>();
if (this._nextScheduledTimestamp != NextScheduledTimestamp) if (this._nextScheduledTimestamp != NextScheduledTimestamp)
@@ -337,6 +346,10 @@ namespace Disco.Services.Tasks
} }
UpdateTriggered(changedProperties.ToArray()); UpdateTriggered(changedProperties.ToArray());
} }
public bool WaitUntilFinished(TimeSpan Timeout)
{
return this._waitHandle.WaitOne(Timeout);
}
#endregion #endregion
private void UpdateTriggered(string[] ChangedProperties) private void UpdateTriggered(string[] ChangedProperties)
@@ -15,13 +15,20 @@ namespace Disco.Web.Areas.API.Controllers
public partial class PluginController : AuthorizedDatabaseController public partial class PluginController : AuthorizedDatabaseController
{ {
[DiscoAuthorize(Claims.Config.Plugin.Install)] [DiscoAuthorize(Claims.Config.Plugin.Install)]
public virtual ActionResult UpdateLibraryCatalogue() public virtual ActionResult UpdateLibraryCatalogue(bool TryWaitingForCompletion = false)
{ {
var status = PluginLibraryUpdateTask.ScheduleNow(); var status = PluginLibraryUpdateTask.ScheduleNow();
status.SetFinishedUrl(Url.Action(MVC.Config.Plugins.Install())); // If upload takes <= 2 seconds, return back to Plugin Install (rather than Task Status)
if (TryWaitingForCompletion && status.WaitUntilFinished(TimeSpan.FromSeconds(3)) && status.TaskException == null)
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); {
return RedirectToAction(MVC.Config.Plugins.Install());
}
else
{
status.SetFinishedUrl(Url.Action(MVC.Config.Plugins.Install()));
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
} }
[DiscoAuthorize(Claims.Config.Plugin.Install)] [DiscoAuthorize(Claims.Config.Plugin.Install)]
@@ -75,7 +75,7 @@ namespace Disco.Web.Areas.Config.Controllers
if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddHours(-1)) if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddHours(-1))
{ {
// Need to Update Catalogue (over 1 hour old) // Need to Update Catalogue (over 1 hour old)
return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue()); return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue(true));
} }
else else
{ {
@@ -8,7 +8,7 @@
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins", MVC.Config.Plugins.Index(), "Install Plugin"); ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins", MVC.Config.Plugins.Index(), "Install Plugin");
} }
<div id="pluginCatalog"> <div id="pluginCatalog">
<h4 id="pluginCatalogHeading">The plugin catalogue [<a href="https://discoict.com.au/">https://discoict.com.au</a>] was last updated @CommonHelpers.FriendlyDate(Model.Catalogue.ResponseTimestamp) <h4 id="pluginCatalogHeading">The plugin catalogue [<a href="https://discoict.com.au/">https://discoict.com.au</a>] was last updated @CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp))
</h4> </h4>
@if (Model.Catalogue.Plugins.Count == 0) @if (Model.Catalogue.Plugins.Count == 0)
{ {
@@ -77,7 +77,7 @@ WriteLiteral(">https://discoict.com.au</a>] was last updated ");
#line 11 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 11 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
Write(CommonHelpers.FriendlyDate(Model.Catalogue.ResponseTimestamp)); Write(CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp)));
#line default #line default
@@ -161,16 +161,16 @@ WriteLiteral(" <td>\r\n");
#line hidden #line hidden
WriteLiteral(" <div"); WriteLiteral(" <div");
WriteAttribute("class", Tuple.Create(" class=\"", 1594), Tuple.Create("\"", 1687) WriteAttribute("class", Tuple.Create(" class=\"", 1662), Tuple.Create("\"", 1755)
, Tuple.Create(Tuple.Create("", 1602), Tuple.Create("pageMenuArea", 1602), true) , Tuple.Create(Tuple.Create("", 1670), Tuple.Create("pageMenuArea", 1670), true)
, Tuple.Create(Tuple.Create(" ", 1614), Tuple.Create("pluginItem", 1615), true) , Tuple.Create(Tuple.Create(" ", 1682), Tuple.Create("pluginItem", 1683), true)
#line 36 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 36 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1625), Tuple.Create<System.Object, System.Int32>(installedPlugin != null ? " pluginInstalled" : string.Empty , Tuple.Create(Tuple.Create("", 1693), Tuple.Create<System.Object, System.Int32>(installedPlugin != null ? " pluginInstalled" : string.Empty
#line default #line default
#line hidden #line hidden
, 1625), false) , 1693), false)
); );
WriteLiteral(">\r\n <h2"); WriteLiteral(">\r\n <h2");
@@ -210,14 +210,14 @@ WriteLiteral(" <a");
WriteLiteral(" class=\"pluginInstallLink button\""); WriteLiteral(" class=\"pluginInstallLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 1967), Tuple.Create("\"", 2022) WriteAttribute("href", Tuple.Create(" href=\"", 2035), Tuple.Create("\"", 2090)
#line 40 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 40 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 1974), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Id)) , Tuple.Create(Tuple.Create("", 2042), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Install(plugin.Id))
#line default #line default
#line hidden #line hidden
, 1974), false) , 2042), false)
); );
WriteLiteral(">Install</a>\r\n"); WriteLiteral(">Install</a>\r\n");
@@ -237,14 +237,14 @@ WriteLiteral(" <a");
WriteLiteral(" class=\"pluginUpdateLink button\""); WriteLiteral(" class=\"pluginUpdateLink button\"");
WriteAttribute("href", Tuple.Create(" href=\"", 2382), Tuple.Create("\"", 2436) WriteAttribute("href", Tuple.Create(" href=\"", 2450), Tuple.Create("\"", 2504)
#line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 46 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 2389), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Id)) , Tuple.Create(Tuple.Create("", 2457), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.Plugin.Update(plugin.Id))
#line default #line default
#line hidden #line hidden
, 2389), false) , 2457), false)
); );
WriteLiteral(">Update</a> \r\n"); WriteLiteral(">Update</a> \r\n");
@@ -328,14 +328,14 @@ WriteLiteral("</span> | ");
#line hidden #line hidden
WriteLiteral(" | <a"); WriteLiteral(" | <a");
WriteAttribute("href", Tuple.Create(" href=\"", 3143), Tuple.Create("\"", 3161) WriteAttribute("href", Tuple.Create(" href=\"", 3211), Tuple.Create("\"", 3229)
#line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line 56 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
, Tuple.Create(Tuple.Create("", 3150), Tuple.Create<System.Object, System.Int32>(plugin.Url , Tuple.Create(Tuple.Create("", 3218), Tuple.Create<System.Object, System.Int32>(plugin.Url
#line default #line default
#line hidden #line hidden
, 3150), false) , 3218), false)
); );
WriteLiteral(" title=\"More Information\""); WriteLiteral(" title=\"More Information\"");
+12 -3
View File
@@ -7930,6 +7930,14 @@ namespace Disco.Web.Areas.API.Controllers
} }
static readonly ActionParamsClass_UpdateLibraryCatalogue s_params_UpdateLibraryCatalogue = new ActionParamsClass_UpdateLibraryCatalogue();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_UpdateLibraryCatalogue UpdateLibraryCatalogueParams { get { return s_params_UpdateLibraryCatalogue; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_UpdateLibraryCatalogue
{
public readonly string TryWaitingForCompletion = "TryWaitingForCompletion";
}
static readonly ActionParamsClass_Update s_params_Update = new ActionParamsClass_Update(); static readonly ActionParamsClass_Update s_params_Update = new ActionParamsClass_Update();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Update UpdateParams { get { return s_params_Update; } } public ActionParamsClass_Update UpdateParams { get { return s_params_Update; } }
@@ -7991,12 +7999,13 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public T4MVC_PluginController() : base(Dummy.Instance) { } public T4MVC_PluginController() : base(Dummy.Instance) { }
partial void UpdateLibraryCatalogueOverride(T4MVC_System_Web_Mvc_ActionResult callInfo); partial void UpdateLibraryCatalogueOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, bool TryWaitingForCompletion);
public override System.Web.Mvc.ActionResult UpdateLibraryCatalogue() public override System.Web.Mvc.ActionResult UpdateLibraryCatalogue(bool TryWaitingForCompletion)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLibraryCatalogue); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.UpdateLibraryCatalogue);
UpdateLibraryCatalogueOverride(callInfo); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "TryWaitingForCompletion", TryWaitingForCompletion);
UpdateLibraryCatalogueOverride(callInfo, TryWaitingForCompletion);
return callInfo; return callInfo;
} }