Update: Cached Job Index Data
Take advantage of repository monitor for change notification; in-memory cache rather than retrieving data on each request.
This commit is contained in:
@@ -7,6 +7,9 @@ using Disco.Models.BI.Job.Statistics;
|
||||
using Disco.Data.Repository;
|
||||
using Quartz.Impl;
|
||||
using Disco.Services.Tasks;
|
||||
using System.Reactive.Linq;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository.Monitor;
|
||||
|
||||
namespace Disco.BI.JobBI.Statistics
|
||||
{
|
||||
@@ -15,6 +18,7 @@ namespace Disco.BI.JobBI.Statistics
|
||||
|
||||
private static List<DailyOpenedClosedItem> _data;
|
||||
private static object _dataLock = new object();
|
||||
private static IDisposable _streamSubscription;
|
||||
|
||||
|
||||
public override string TaskName { get { return "Job Statistics - Daily Opened/Closed Task"; } }
|
||||
@@ -65,7 +69,7 @@ namespace Disco.BI.JobBI.Statistics
|
||||
|
||||
private static void UpdateDataHistory(DiscoDataContext dbContext, bool Refresh = false)
|
||||
{
|
||||
DateTime historyEnd = DateTime.Now.AddDays(-1).Date;
|
||||
DateTime historyEnd = DateTime.Now.Date;
|
||||
|
||||
if (Refresh || _data == null || _data.Count == 0 || _data.Last().Timestamp < historyEnd)
|
||||
{
|
||||
@@ -97,8 +101,62 @@ namespace Disco.BI.JobBI.Statistics
|
||||
resultData.Add(Data(dbContext, processDate));
|
||||
processDate = processDate.AddDays(1);
|
||||
}
|
||||
|
||||
_data = resultData;
|
||||
|
||||
// Subscribe to Live Repository Events
|
||||
if (_streamSubscription != null)
|
||||
_streamSubscription.Dispose();
|
||||
_streamSubscription = Disco.Data.Repository.Monitor.RepositoryMonitor.StreamBeforeCommit.Where(
|
||||
e => e.EntityType == typeof(Job) &&
|
||||
(e.EventType == RepositoryMonitorEventType.Added || (e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Contains("ClosedDate")))).Subscribe(RepositoryEvent_JobChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RepositoryEvent_JobChange(RepositoryMonitorEvent e)
|
||||
{
|
||||
|
||||
if (e.EventType == RepositoryMonitorEventType.Added)
|
||||
{
|
||||
// New Job
|
||||
var todaysStats = _data.Last();
|
||||
todaysStats.OpenedJobs += 1;
|
||||
todaysStats.TotalJobs += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DateTime? previousValue = e.GetPreviousPropertyValue<DateTime?>("ClosedDate");
|
||||
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
|
||||
|
||||
if (previousValue.HasValue)
|
||||
{
|
||||
// Remove Statistics
|
||||
var statItem = _data.FirstOrDefault(i => i.Timestamp == previousValue.Value.Date);
|
||||
if (statItem != null)
|
||||
{
|
||||
statItem.ClosedJobs -= 1;
|
||||
statItem.TotalJobs += 1;
|
||||
}
|
||||
foreach (var affectedStat in _data.Where(i => i.Timestamp > previousValue))
|
||||
{
|
||||
affectedStat.TotalJobs += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentValue.HasValue)
|
||||
{
|
||||
// Add Statistics
|
||||
// Remove Statistics
|
||||
var statItem = _data.FirstOrDefault(i => i.Timestamp == currentValue.Value.Date);
|
||||
if (statItem != null)
|
||||
{
|
||||
statItem.ClosedJobs += 1;
|
||||
statItem.TotalJobs -= 1;
|
||||
}
|
||||
foreach (var affectedStat in _data.Where(i => i.Timestamp > currentValue))
|
||||
{
|
||||
affectedStat.TotalJobs -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +192,8 @@ namespace Disco.BI.JobBI.Statistics
|
||||
else
|
||||
resultData = _data.ToList();
|
||||
|
||||
resultData.Add(Data(dbContext, DateTime.Today));
|
||||
// Removed - Live Updated via Repository Monitor; See: RepositoryEvent_JobChange
|
||||
//resultData.Add(Data(dbContext, DateTime.Today));
|
||||
|
||||
return resultData;
|
||||
}
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.2.0411.1833")]
|
||||
[assembly: AssemblyFileVersion("1.2.0411.1833")]
|
||||
[assembly: AssemblyVersion("1.2.0430.1219")]
|
||||
[assembly: AssemblyFileVersion("1.2.0430.1219")]
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.2.0411.1833")]
|
||||
[assembly: AssemblyFileVersion("1.2.0411.1833")]
|
||||
[assembly: AssemblyVersion("1.2.0430.1219")]
|
||||
[assembly: AssemblyFileVersion("1.2.0430.1219")]
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Disco.Web.Controllers
|
||||
|
||||
m.OpenJobs = jobList_OpenJobs;
|
||||
m.LongRunningJobs = jobList_LongRunning;
|
||||
m.DailyOpenedClosedStatistics = Disco.BI.JobBI.Statistics.DailyOpenedClosed.Data(dbContext, true);
|
||||
|
||||
// UI Extensions
|
||||
UIExtensions.ExecuteExtensions<JobIndexModel>(this.ControllerContext, m);
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
<h2>Daily Opened & Closed Jobs</h2>
|
||||
<div id="chartHostJobDailyOpenedClosed" style="height: 175px;">
|
||||
</div>
|
||||
@{
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
}
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
|
||||
var chartData;
|
||||
|
||||
function buildChart() {
|
||||
@@ -105,12 +107,8 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$.getJSON('@(Url.Action(MVC.API.Job.StatisticsDailyOpenedClosed()))', function (data) {
|
||||
chartData = data;
|
||||
buildChart();
|
||||
});
|
||||
chartData = $.parseJSON('@(jsonData)');
|
||||
buildChart();
|
||||
}());
|
||||
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
// Runtime Version:4.0.30319.18033
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -31,9 +31,9 @@ namespace Disco.Web.Views.Job
|
||||
using Disco.Web;
|
||||
using Disco.Web.Extensions;
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.0.0")]
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.5.4.0")]
|
||||
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Job/Index.cshtml")]
|
||||
public class Index : System.Web.Mvc.WebViewPage<Disco.Web.Models.Job.IndexModel>
|
||||
public partial class Index : System.Web.Mvc.WebViewPage<Disco.Web.Models.Job.IndexModel>
|
||||
{
|
||||
public Index()
|
||||
{
|
||||
@@ -78,77 +78,92 @@ WriteLiteral(" id=\"chartHostJobDailyOpenedClosed\"");
|
||||
|
||||
WriteLiteral(" style=\"height: 175px;\"");
|
||||
|
||||
WriteLiteral(">\r\n </div>\r\n <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(">\r\n (function () {\r\n\r\n var chartData;\r\n\r\n " +
|
||||
" function buildChart() {\r\n $(function () {\r\n\r\n " +
|
||||
" var data = chartData;\r\n\r\n var dataTotalOpenJobs" +
|
||||
" = [];\r\n var dataOpenedJobs = [];\r\n " +
|
||||
" var dataClosedJobs = [];\r\n for (var i = 0; i < data.len" +
|
||||
"gth; i++) {\r\n var dataItem = data[i];\r\n " +
|
||||
" var dataItemDate = new Date(parseInt(dataItem.Timestamp.substr(6, " +
|
||||
"dataItem.Timestamp.length - 8))).getTime(); // $.datepicker.parseDate(\'yy-mm-dd\'" +
|
||||
", dataItem.Timestamp.substr(0, 10)).getTime();\r\n data" +
|
||||
"TotalOpenJobs.push([dataItemDate, dataItem.TotalJobs]);\r\n " +
|
||||
" dataOpenedJobs.push([dataItemDate, dataItem.OpenedJobs]);\r\n " +
|
||||
" dataClosedJobs.push([dataItemDate, dataItem.ClosedJobs]);\r\n " +
|
||||
" }\r\n Highcharts.setOptions({\r\n " +
|
||||
" global: {\r\n useUTC: false\r\n " +
|
||||
" }\r\n });\r\n new" +
|
||||
" Highcharts.Chart({\r\n chart: {\r\n " +
|
||||
" renderTo: \'chartHostJobDailyOpenedClosed\',\r\n " +
|
||||
" height: 175,\r\n animation: false\r\n " +
|
||||
" },\r\n colors: [\'#BBBBBB\', \'#005fab\'" +
|
||||
", \'#DB761D\'],\r\n title: {\r\n " +
|
||||
" text: null\r\n },\r\n plo" +
|
||||
"tOptions: {\r\n series: {\r\n " +
|
||||
" marker: {\r\n radius: 3\r\n " +
|
||||
" },\r\n animation:" +
|
||||
" false\r\n }\r\n },\r\n " +
|
||||
" legend: {\r\n align: \'left\'," +
|
||||
"\r\n verticalAlign: \'top\',\r\n " +
|
||||
" y: 0,\r\n floating: true,\r\n " +
|
||||
" borderWidth: 0\r\n },\r\n " +
|
||||
" xAxis: {\r\n type: \'datetime\',\r\n " +
|
||||
" tickInterval: 7 * 24 * 3600 * 1000, // week\r\n " +
|
||||
" tickWidth: 1,\r\n gridLineWi" +
|
||||
"dth: 1,\r\n dateTimeLabelFormats: {\r\n " +
|
||||
" week: \'%e %b\'\r\n }\r\n " +
|
||||
" },\r\n yAxis: [{\r\n " +
|
||||
" title: {\r\n text: null\r\n " +
|
||||
" },\r\n labels: {\r\n " +
|
||||
" enabled: false\r\n },\r\n" +
|
||||
" min: 0\r\n }, {\r\n " +
|
||||
" title: {\r\n text: nu" +
|
||||
"ll\r\n },\r\n labels: " +
|
||||
"{\r\n enabled: false\r\n " +
|
||||
" },\r\n min: 0\r\n }" +
|
||||
"],\r\n series: [{\r\n name" +
|
||||
": \'Total Open Jobs\',\r\n data: dataTotalOpenJobs,\r\n" +
|
||||
" yAxis: 1\r\n }, {\r\n " +
|
||||
" name: \'Closed Jobs\',\r\n " +
|
||||
" data: dataClosedJobs\r\n }, {\r\n " +
|
||||
" name: \'Opened Jobs\',\r\n data: dataOpened" +
|
||||
"Jobs\r\n }],\r\n credits: {\r\n " +
|
||||
" enabled: false\r\n }\r\n " +
|
||||
" });\r\n });\r\n }\r\n\r\n\r\n " +
|
||||
" $.getJSON(\'");
|
||||
WriteLiteral(">\r\n </div>\r\n");
|
||||
|
||||
|
||||
#line 110 "..\..\Views\Job\Index.cshtml"
|
||||
Write(Url.Action(MVC.API.Job.StatisticsDailyOpenedClosed()));
|
||||
#line 15 "..\..\Views\Job\Index.cshtml"
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\', function (data) {\r\n chartData = data;\r\n " +
|
||||
"buildChart();\r\n });\r\n }());\r\n\r\n </script>\r\n " +
|
||||
"</div>\r\n</div>\r\n<h2>Open Jobs Awaiting Technician Action (");
|
||||
|
||||
#line 15 "..\..\Views\Job\Index.cshtml"
|
||||
|
||||
var jsonData = new HtmlString(Json.Encode(Model.DailyOpenedClosedStatistics));
|
||||
|
||||
|
||||
#line 119 "..\..\Views\Job\Index.cshtml"
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n <script");
|
||||
|
||||
WriteLiteral(" type=\"text/javascript\"");
|
||||
|
||||
WriteLiteral(">\r\n (function () {\r\n var chartData;\r\n\r\n " +
|
||||
"function buildChart() {\r\n $(function () {\r\n\r\n " +
|
||||
" var data = chartData;\r\n\r\n var dataTotalOpenJobs =" +
|
||||
" [];\r\n var dataOpenedJobs = [];\r\n " +
|
||||
"var dataClosedJobs = [];\r\n for (var i = 0; i < data.lengt" +
|
||||
"h; i++) {\r\n var dataItem = data[i];\r\n " +
|
||||
" var dataItemDate = new Date(parseInt(dataItem.Timestamp.substr(6, da" +
|
||||
"taItem.Timestamp.length - 8))).getTime(); // $.datepicker.parseDate(\'yy-mm-dd\', " +
|
||||
"dataItem.Timestamp.substr(0, 10)).getTime();\r\n dataTo" +
|
||||
"talOpenJobs.push([dataItemDate, dataItem.TotalJobs]);\r\n " +
|
||||
" dataOpenedJobs.push([dataItemDate, dataItem.OpenedJobs]);\r\n " +
|
||||
" dataClosedJobs.push([dataItemDate, dataItem.ClosedJobs]);\r\n " +
|
||||
" }\r\n Highcharts.setOptions({\r\n " +
|
||||
" global: {\r\n useUTC: false\r\n " +
|
||||
" }\r\n });\r\n new H" +
|
||||
"ighcharts.Chart({\r\n chart: {\r\n " +
|
||||
" renderTo: \'chartHostJobDailyOpenedClosed\',\r\n " +
|
||||
" height: 175,\r\n animation: false\r\n " +
|
||||
" },\r\n colors: [\'#BBBBBB\', \'#005fab\', " +
|
||||
"\'#DB761D\'],\r\n title: {\r\n " +
|
||||
" text: null\r\n },\r\n plotO" +
|
||||
"ptions: {\r\n series: {\r\n " +
|
||||
" marker: {\r\n radius: 3\r\n " +
|
||||
" },\r\n animation: f" +
|
||||
"alse\r\n }\r\n },\r\n " +
|
||||
" legend: {\r\n align: \'left\',\r\n" +
|
||||
" verticalAlign: \'top\',\r\n " +
|
||||
" y: 0,\r\n floating: true,\r\n " +
|
||||
" borderWidth: 0\r\n },\r\n " +
|
||||
" xAxis: {\r\n type: \'datetime\',\r\n " +
|
||||
" tickInterval: 7 * 24 * 3600 * 1000, // week\r\n " +
|
||||
" tickWidth: 1,\r\n gridLineWidt" +
|
||||
"h: 1,\r\n dateTimeLabelFormats: {\r\n " +
|
||||
" week: \'%e %b\'\r\n }\r\n " +
|
||||
" },\r\n yAxis: [{\r\n " +
|
||||
" title: {\r\n text: null\r\n " +
|
||||
" },\r\n labels: {\r\n " +
|
||||
" enabled: false\r\n },\r\n " +
|
||||
" min: 0\r\n }, {\r\n " +
|
||||
" title: {\r\n text: null" +
|
||||
"\r\n },\r\n labels: {\r" +
|
||||
"\n enabled: false\r\n " +
|
||||
" },\r\n min: 0\r\n }]," +
|
||||
"\r\n series: [{\r\n name: " +
|
||||
"\'Total Open Jobs\',\r\n data: dataTotalOpenJobs,\r\n " +
|
||||
" yAxis: 1\r\n }, {\r\n " +
|
||||
" name: \'Closed Jobs\',\r\n " +
|
||||
"data: dataClosedJobs\r\n }, {\r\n " +
|
||||
" name: \'Opened Jobs\',\r\n data: dataOpenedJo" +
|
||||
"bs\r\n }],\r\n credits: {\r\n " +
|
||||
" enabled: false\r\n }\r\n " +
|
||||
" });\r\n });\r\n }\r\n " +
|
||||
" chartData = $.parseJSON(\'");
|
||||
|
||||
|
||||
#line 110 "..\..\Views\Job\Index.cshtml"
|
||||
Write(jsonData);
|
||||
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\');\r\n buildChart();\r\n }());\r\n\r\n </script>\r\n <" +
|
||||
"/div>\r\n</div>\r\n<h2>Open Jobs Awaiting Technician Action (");
|
||||
|
||||
|
||||
#line 117 "..\..\Views\Job\Index.cshtml"
|
||||
Write(Model.OpenJobs.Items.Count);
|
||||
|
||||
|
||||
@@ -157,7 +172,7 @@ WriteLiteral("\', function (data) {\r\n chartData = data;\r\n
|
||||
WriteLiteral(")</h2>\r\n");
|
||||
|
||||
|
||||
#line 120 "..\..\Views\Job\Index.cshtml"
|
||||
#line 118 "..\..\Views\Job\Index.cshtml"
|
||||
Write(Html.Partial(MVC.Shared.Views._JobTable, Model.OpenJobs, new ViewDataDictionary()));
|
||||
|
||||
|
||||
@@ -166,7 +181,7 @@ Write(Html.Partial(MVC.Shared.Views._JobTable, Model.OpenJobs, new ViewDataDicti
|
||||
WriteLiteral("\r\n<h2>Long Running Jobs (");
|
||||
|
||||
|
||||
#line 121 "..\..\Views\Job\Index.cshtml"
|
||||
#line 119 "..\..\Views\Job\Index.cshtml"
|
||||
Write(Model.LongRunningJobs.Items.Count);
|
||||
|
||||
|
||||
@@ -175,7 +190,7 @@ WriteLiteral("\r\n<h2>Long Running Jobs (");
|
||||
WriteLiteral(")</h2>\r\n");
|
||||
|
||||
|
||||
#line 122 "..\..\Views\Job\Index.cshtml"
|
||||
#line 120 "..\..\Views\Job\Index.cshtml"
|
||||
Write(Html.Partial(MVC.Shared.Views._JobTable, Model.LongRunningJobs, new ViewDataDictionary()));
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user