Bug Fix: Error when assigning devices

The noticeboard listens for updates to user assignments (including who
was previously assigned the device), but was requesting data which no
longer existed (as updates are delayed and buffered for up to 500ms).
This commit is contained in:
Gary Sharp
2014-07-26 12:25:20 +10:00
parent 81d024618a
commit b78ce003a7
+101 -77
View File
@@ -5,7 +5,9 @@ using Disco.Models.Services.Jobs.Noticeboards;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace Disco.Services.Jobs.Noticeboards namespace Disco.Services.Jobs.Noticeboards
{ {
@@ -41,10 +43,19 @@ namespace Disco.Services.Jobs.Noticeboards
"DisplayName" "DisplayName"
}; };
private static Subject<Tuple<List<string>, List<string>>> BufferedUpdateStream;
static HeldDevices() static HeldDevices()
{ {
BufferedUpdateStream = new Subject<Tuple<List<string>, List<string>>>();
BufferedUpdateStream
.DelayBuffer(TimeSpan.FromMilliseconds(500))
.SubscribeOn(TaskPoolScheduler.Default)
.Subscribe(ProcessUpdates);
// Subscribe to Repository Notifications // Subscribe to Repository Notifications
RepositoryMonitor.StreamAfterCommit.Where(e => RepositoryMonitor.StreamBeforeCommit.Where(e =>
(e.EntityType == typeof(Job) && (e.EntityType == typeof(Job) &&
(e.EventType == RepositoryMonitorEventType.Added || (e.EventType == RepositoryMonitorEventType.Added ||
e.EventType == RepositoryMonitorEventType.Deleted || e.EventType == RepositoryMonitorEventType.Deleted ||
@@ -65,93 +76,105 @@ namespace Disco.Services.Jobs.Noticeboards
(e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Any(p => MonitorUserProperties.Contains(p))) (e.EventType == RepositoryMonitorEventType.Modified && e.ModifiedProperties.Any(p => MonitorUserProperties.Contains(p)))
) )
) )
.DelayBuffer(TimeSpan.FromMilliseconds(500))
.Subscribe(RepositoryEvent); .Subscribe(RepositoryEvent);
} }
private static void RepositoryEvent(IEnumerable<RepositoryMonitorEvent> e) private static void RepositoryEvent(RepositoryMonitorEvent i)
{ {
List<string> deviceSerialNumbers = new List<string>(); List<string> deviceSerialNumbers = new List<string>();
List<string> userIds = new List<string>(); List<string> userIds = new List<string>();
using (DiscoDataContext Database = new DiscoDataContext()) if (i.EntityType == typeof(Job))
{ {
foreach (var i in e) if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("DeviceSerialNumber"))
{ {
if (i.EntityType == typeof(Job)) var p = i.GetPreviousPropertyValue<string>("DeviceSerialNumber");
{ if (p != null)
if (i.EventType == RepositoryMonitorEventType.Modified && deviceSerialNumbers.Add(p);
i.ModifiedProperties.Contains("DeviceSerialNumber"))
{
var p = i.GetPreviousPropertyValue<string>("DeviceSerialNumber");
if (p != null)
deviceSerialNumbers.Add(p);
}
var j = (Job)i.Entity;
if (j.DeviceSerialNumber != null)
deviceSerialNumbers.Add(j.DeviceSerialNumber);
}
else if (i.EntityType == typeof(JobMetaNonWarranty))
{
var jmnw = (JobMetaNonWarranty)i.Entity;
if (jmnw.Job != null)
{
if (jmnw.Job.DeviceSerialNumber != null)
deviceSerialNumbers.Add(jmnw.Job.DeviceSerialNumber);
}
else
{
var sn = Database.Jobs.Where(j => j.Id == jmnw.JobId).Select(j => j.DeviceSerialNumber).FirstOrDefault();
if (sn != null)
deviceSerialNumbers.Add(sn);
}
}
else if (i.EntityType == typeof(Device))
{
var d = (Device)i.Entity;
deviceSerialNumbers.Add(d.SerialNumber);
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("AssignedUserId"))
{
var p = i.GetPreviousPropertyValue<string>("AssignedUserId");
if (p != null)
userIds.Add(p);
}
}
else if (i.EntityType == typeof(DeviceProfile))
{
var dp = (DeviceProfile)i.Entity;
deviceSerialNumbers.AddRange(
Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceProfileId == dp.Id)
.Select(j => j.DeviceSerialNumber)
);
}
else if (i.EntityType == typeof(User))
{
var u = (User)i.Entity;
deviceSerialNumbers.AddRange(
Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.AssignedUserId == u.UserId)
.Select(j => j.DeviceSerialNumber)
);
}
} }
deviceSerialNumbers = deviceSerialNumbers.Distinct().ToList(); var j = (Job)i.Entity;
if (j.DeviceSerialNumber != null)
deviceSerialNumbers.Add(j.DeviceSerialNumber);
}
else if (i.EntityType == typeof(JobMetaNonWarranty))
{
var jmnw = (JobMetaNonWarranty)i.Entity;
if (jmnw.Job != null)
{
if (jmnw.Job.DeviceSerialNumber != null)
deviceSerialNumbers.Add(jmnw.Job.DeviceSerialNumber);
}
else
{
var sn = i.Database.Jobs.Where(j => j.Id == jmnw.JobId).Select(j => j.DeviceSerialNumber).FirstOrDefault();
if (sn != null)
deviceSerialNumbers.Add(sn);
}
}
else if (i.EntityType == typeof(Device))
{
var d = (Device)i.Entity;
deviceSerialNumbers.Add(d.SerialNumber);
if (i.EventType == RepositoryMonitorEventType.Modified &&
i.ModifiedProperties.Contains("AssignedUserId"))
{
var p = i.GetPreviousPropertyValue<string>("AssignedUserId");
if (p != null)
userIds.Add(p);
}
}
else if (i.EntityType == typeof(DeviceProfile))
{
var dp = (DeviceProfile)i.Entity;
deviceSerialNumbers.AddRange(
i.Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceProfileId == dp.Id)
.Select(j => j.DeviceSerialNumber)
);
}
else if (i.EntityType == typeof(User))
{
var u = (User)i.Entity;
deviceSerialNumbers.AddRange(
i.Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.AssignedUserId == u.UserId)
.Select(j => j.DeviceSerialNumber)
);
}
if (deviceSerialNumbers.Count > 0 || userIds.Count > 0)
{
i.ExecuteAfterCommit(e =>
{
BufferedUpdateStream.OnNext(Tuple.Create(deviceSerialNumbers, userIds));
});
}
}
private static void ProcessUpdates(IEnumerable<Tuple<List<string>, List<string>>> e)
{
using (DiscoDataContext Database = new DiscoDataContext())
{
var deviceSerialNumbers = e.SelectMany(i => i.Item1).Distinct().ToList();
var userIds = e.SelectMany(i => i.Item2).Distinct().ToList();
// Determine Held Devices for Users // Determine Held Devices for Users
userIds.AddRange( if (deviceSerialNumbers.Count > 0)
Database.Devices {
.Where(d => d.AssignedUserId != null && deviceSerialNumbers.Contains(d.SerialNumber)) userIds.AddRange(
.Select(d => d.AssignedUserId) Database.Devices
); .Where(d => d.AssignedUserId != null && deviceSerialNumbers.Contains(d.SerialNumber))
userIds = userIds.Distinct().ToList(); .Select(d => d.AssignedUserId)
);
}
if (userIds.Count > 0)
userIds = userIds.Distinct().ToList();
// Notify Held Devices // Notify Held Devices
@@ -172,8 +195,9 @@ namespace Disco.Services.Jobs.Noticeboards
{ {
var updates = DeviceSerialNumbers var updates = DeviceSerialNumbers
.Skip(skipAmount).Take(30) .Skip(skipAmount).Take(30)
.ToDictionary(dsn => dsn, .ToDictionary(dsn => dsn,
dsn => { dsn =>
{
IHeldDeviceItem item; IHeldDeviceItem item;
items.TryGetValue(dsn, out item); items.TryGetValue(dsn, out item);
return item; return item;