Files
2016-12-08 17:01:13 +11:00

201 lines
7.9 KiB
C#

using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Extensions;
using Disco.Services.Tasks;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web;
namespace Disco.Services.Jobs.JobQueues
{
public static class JobQueueService
{
private const string _cacheHttpRequestKey = "Disco_UserQueuesToken_{0}";
private static Cache _cache;
public static void Initialize(DiscoDataContext Database)
{
_cache = new Cache(Database);
}
public static ReadOnlyCollection<KeyValuePair<int, string>> SlaOptions { get { return _cache.SlaOptions; } }
public static ReadOnlyCollection<JobQueueToken> GetQueues() { return _cache.GetQueues(); }
public static JobQueueToken GetQueue(int JobQueueId) { return _cache.GetQueue(JobQueueId); }
#region Job Queues Maintenance
public static JobQueueToken CreateJobQueue(DiscoDataContext Database, JobQueue JobQueue)
{
// Verify
if (string.IsNullOrWhiteSpace(JobQueue.Name))
throw new ArgumentException("The Job Queue Name is required");
// Name Unique
if (_cache.GetQueues().Any(q => q.JobQueue.Name == JobQueue.Name))
throw new ArgumentException("Another Job Queue already exists with that name", "JobQueue");
// Sanitize Subject Ids
if (string.IsNullOrWhiteSpace(JobQueue.SubjectIds))
{
JobQueue.SubjectIds = null;
}
else
{
var subjectIds = JobQueue.SubjectIds.Split(',');
foreach (var subjectId in subjectIds)
{
UserService.GetUser(subjectId, Database);
}
JobQueue.SubjectIds = string.Join(",", Database.Users.Where(u => subjectIds.Contains(u.UserId)).Select(u => u.UserId));
}
// Clone to break reference
var queue = new JobQueue()
{
Name = JobQueue.Name,
Description = JobQueue.Description,
Icon = JobQueue.Icon,
IconColour = JobQueue.IconColour,
DefaultSLAExpiry = JobQueue.DefaultSLAExpiry,
Priority = JobQueue.Priority,
SubjectIds = JobQueue.SubjectIds
};
Database.JobQueues.Add(queue);
Database.SaveChanges();
return _cache.UpdateQueue(queue);
}
public static JobQueueToken UpdateJobQueue(DiscoDataContext Database, JobQueue JobQueue)
{
// Verify
if (string.IsNullOrWhiteSpace(JobQueue.Name))
throw new ArgumentException("The Job Queue Name is required");
// Name Unique
if (_cache.GetQueues().Any(q => q.JobQueue.Id != JobQueue.Id && q.JobQueue.Name == JobQueue.Name))
throw new ArgumentException("Another Job Queue already exists with that name", "JobQueue");
// Sanitize Subject Ids
if (string.IsNullOrWhiteSpace(JobQueue.SubjectIds))
{
JobQueue.SubjectIds = null;
}
else
{
var subjectIds = JobQueue.SubjectIds.Split(',');
foreach (var subjectId in subjectIds)
{
UserService.GetUser(subjectId, Database);
}
JobQueue.SubjectIds = string.Join(",", Database.Users.Where(u => subjectIds.Contains(u.UserId)).Select(u => u.UserId));
}
Database.SaveChanges();
return _cache.UpdateQueue(JobQueue);
}
public static void DeleteJobQueue(DiscoDataContext Database, int JobQueueId, IScheduledTaskStatus Status)
{
JobQueue queue = Database.JobQueues.Find(JobQueueId);
// Validate: Current Jobs?
var currentJobs = Database.JobQueueJobs.Any(jqj => jqj.JobQueueId == queue.Id && !jqj.RemovedDate.HasValue);
if (currentJobs)
throw new InvalidOperationException("The Job Queue cannot be deleted because it contains jobs");
// Delete History
Status.UpdateStatus(0, string.Format("Removing '{0}' [{1}] Job Queue", queue.Name, queue.Id), "Starting");
var jobQueueJobs = Database.JobQueueJobs.Include("Job").Where(jsj => jsj.JobQueueId == queue.Id).ToList();
if (jobQueueJobs.Count > 0)
{
double progressInterval = 90 / jobQueueJobs.Count;
for (int jqjIndex = 0; jqjIndex < jobQueueJobs.Count; jqjIndex++)
{
var jqj = jobQueueJobs[jqjIndex];
Status.UpdateStatus(jqjIndex * progressInterval, string.Format("Merging history into job #{0} logs", jqj.JobId));
// Write Logs
Database.JobLogs.Add(new JobLog()
{
JobId = jqj.JobId,
TechUserId = jqj.AddedUserId,
Timestamp = jqj.AddedDate,
Comments = string.Format("# Added to Queue\r\n**{0}**\r\nPriority: **{1}**\r\n{2}", Environment.NewLine, queue.Name, jqj.Priority.ToString(), string.IsNullOrWhiteSpace(jqj.AddedComment) ? "<no comment>" : jqj.AddedComment)
});
Database.JobLogs.Add(new JobLog()
{
JobId = jqj.JobId,
TechUserId = jqj.RemovedUserId,
Timestamp = jqj.RemovedDate.Value,
Comments = string.Format("# Removed from Queue\r\n**{0}**\r\n{1}", queue.Name, string.IsNullOrWhiteSpace(jqj.RemovedComment) ? "<no comment>" : jqj.RemovedComment)
});
// Delete JQJ
Database.JobQueueJobs.Remove(jqj);
// Save Changes
Database.SaveChanges();
}
}
// Delete Queue
Status.UpdateStatus(90, "Deleting Queue");
Database.JobQueues.Remove(queue);
Database.SaveChanges();
// Remove from Cache
_cache.RemoveQueue(JobQueueId);
Status.Finished(string.Format("Successfully Deleted Job Queue: '{0}' [{1}]", queue.Name, queue.Id));
}
#endregion
public static ReadOnlyCollection<JobQueueToken> UsersQueues(User User)
{
return UsersQueues(User.UserId);
}
public static ReadOnlyCollection<JobQueueToken> UsersQueues(string UserId)
{
var userAuth = UserService.GetAuthorization(UserId);
return UsersQueues(userAuth);
}
public static ReadOnlyCollection<JobQueueToken> UsersQueues(AuthorizationToken UserAuthorization)
{
string cacheKey = string.Format(_cacheHttpRequestKey, UserAuthorization.User.UserId);
ReadOnlyCollection<JobQueueToken> tokens = null;
// Check for ASP.NET
if (HttpContext.Current != null)
{
tokens = (ReadOnlyCollection<JobQueueToken>)HttpContext.Current.Items[_cacheHttpRequestKey];
}
if (tokens == null)
{
var subjectIds = (new string[] { UserAuthorization.User.UserId }).Concat(UserAuthorization.GroupMembership);
tokens = _cache.GetQueuesForSubject(subjectIds);
HttpContext.Current.Items[_cacheHttpRequestKey] = tokens;
}
return tokens;
}
public static string RandomUnusedIcon()
{
return UIHelpers.RandomIcon(_cache.GetQueues().Select(q => q.JobQueue.Icon));
}
public static string RandomUnusedThemeColour()
{
return UIHelpers.RandomThemeColour(_cache.GetQueues().Select(q => q.JobQueue.IconColour));
}
}
}