using Disco.Data.Repository; using Disco.Models.Repository; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Disco.Services.Jobs.JobQueues { internal class Cache { private ConcurrentDictionary _Cache; private Dictionary> _SubjectCache; private ReadOnlyCollection> _SlaOptions; public Cache(DiscoDataContext Database) { Initialize(Database); } private void Initialize(DiscoDataContext Database) { // Queues from Database var queues = Database.JobQueues.ToList(); // Add Queues to In-Memory Cache this._Cache = new ConcurrentDictionary(queues.Select(q => new KeyValuePair(q.Id, JobQueueToken.FromJobQueue(q)))); // Calculate Queue Subject Cache CalculateSubjectCache(); #region Predefined Options // SLA Options if (this._SlaOptions == null) { this._SlaOptions = new List>() { new KeyValuePair(0, ""), new KeyValuePair(15, "15 minutes"), new KeyValuePair(30, "30 minutes"), new KeyValuePair(60, "1 hour"), new KeyValuePair(60 * 2, "2 hours"), new KeyValuePair(60 * 4, "4 hours"), new KeyValuePair(60 * 8, "8 hours"), new KeyValuePair(60 * 24, "1 day"), new KeyValuePair(60 * 24 * 2, "2 days"), new KeyValuePair(60 * 24 * 3, "3 days"), new KeyValuePair(60 * 24 * 4, "4 days"), new KeyValuePair(60 * 24 * 5, "5 days"), new KeyValuePair(60 * 24 * 6, "6 days"), new KeyValuePair(60 * 24 * 7, "1 week"), new KeyValuePair(60 * 24 * 7 * 2, "2 weeks"), new KeyValuePair(60 * 24 * 7 * 3, "3 weeks"), new KeyValuePair(60 * 24 * 7 * 4, "4 weeks"), new KeyValuePair(60 * 24 * 7 * 4 * 2, "2 months"), new KeyValuePair(60 * 24 * 7 * 4 * 3, "3 months"), new KeyValuePair(60 * 24 * 7 * 4 * 4, "4 months"), new KeyValuePair(60 * 24 * 7 * 4 * 5, "5 months"), new KeyValuePair(60 * 24 * 7 * 4 * 6, "6 months") }.AsReadOnly(); } #endregion } private void CalculateSubjectCache() { _SubjectCache = (from c in _Cache.Values.ToList() from s in c.SubjectIds group c by s into subjectId select subjectId).ToDictionary(g => g.Key.ToLower(), g => g.ToList()); } public ReadOnlyCollection> SlaOptions { get { return this._SlaOptions; } } public JobQueueToken UpdateQueue(JobQueue JobQueue) { var token = JobQueueToken.FromJobQueue(JobQueue); JobQueueToken existingToken; if (_Cache.TryGetValue(JobQueue.Id, out existingToken)) { if (_Cache.TryUpdate(JobQueue.Id, token, existingToken)) { if (existingToken.JobQueue.SubjectIds != token.JobQueue.SubjectIds) CalculateSubjectCache(); return token; } else return null; } else { if (_Cache.TryAdd(JobQueue.Id, token)) { CalculateSubjectCache(); return token; } else return null; } } public bool RemoveQueue(int JobQueueId) { JobQueueToken token; if (_Cache.TryRemove(JobQueueId, out token)) { CalculateSubjectCache(); return true; } else { return false; } } public JobQueueToken GetQueue(int JobQueueId) { JobQueueToken token; if (_Cache.TryGetValue(JobQueueId, out token)) return token; else return null; } public ReadOnlyCollection GetQueues() { return _Cache.Values.ToList().AsReadOnly(); } private IEnumerable GetQueuesForSubject(string SubjectId) { List tokens; if (_SubjectCache.TryGetValue(SubjectId.ToLower(), out tokens)) return tokens; else return Enumerable.Empty(); } public ReadOnlyCollection GetQueuesForSubject(IEnumerable SubjectIds) { return SubjectIds.SelectMany(sid => GetQueuesForSubject(sid)).Distinct().ToList().AsReadOnly(); } public void ReInitializeCache(DiscoDataContext Database) { Initialize(Database); } } }