From 28dd127076b34bc01bedf2c2b351102674d5b7ea Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Sat, 29 Apr 2017 17:09:06 -0400 Subject: [PATCH 01/12] DocumentType property --- Hangfire.AzureDocumentDB/Entities/Counter.cs | 5 ++++- .../Entities/DocumentEntity.cs | 16 ++++++++++++++++ Hangfire.AzureDocumentDB/Entities/Hash.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/Job.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/List.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/Lock.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/Parameter.cs | 2 +- Hangfire.AzureDocumentDB/Entities/Queue.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/Server.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/Set.cs | 2 ++ Hangfire.AzureDocumentDB/Entities/State.cs | 4 +++- 11 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Hangfire.AzureDocumentDB/Entities/Counter.cs b/Hangfire.AzureDocumentDB/Entities/Counter.cs index 7163c15..74f1809 100644 --- a/Hangfire.AzureDocumentDB/Entities/Counter.cs +++ b/Hangfire.AzureDocumentDB/Entities/Counter.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using System; +using Newtonsoft.Json; namespace Hangfire.AzureDocumentDB.Entities { @@ -12,6 +13,8 @@ internal class Counter : DocumentEntity [JsonProperty("country_type")] public CounterTypes Type { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Counter; } internal enum CounterTypes diff --git a/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs b/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs index f5402d4..01c259b 100644 --- a/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs +++ b/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs @@ -15,5 +15,21 @@ internal abstract class DocumentEntity [JsonProperty("expire_on")] [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime? ExpireOn { get; set; } + + [JsonProperty("type")] + public abstract DocumentTypes DocumentType { get; set; } + } + + internal enum DocumentTypes + { + Server, + Job, + Queue, + Counter, + List, + Hash, + Set, + State, + Lock } } diff --git a/Hangfire.AzureDocumentDB/Entities/Hash.cs b/Hangfire.AzureDocumentDB/Entities/Hash.cs index 8dd1698..2c5f608 100644 --- a/Hangfire.AzureDocumentDB/Entities/Hash.cs +++ b/Hangfire.AzureDocumentDB/Entities/Hash.cs @@ -12,5 +12,7 @@ internal class Hash : DocumentEntity [JsonProperty("value")] public string Value { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Hash; } } \ No newline at end of file diff --git a/Hangfire.AzureDocumentDB/Entities/Job.cs b/Hangfire.AzureDocumentDB/Entities/Job.cs index eaec256..2e2e8e0 100644 --- a/Hangfire.AzureDocumentDB/Entities/Job.cs +++ b/Hangfire.AzureDocumentDB/Entities/Job.cs @@ -25,5 +25,7 @@ internal class Job : DocumentEntity [JsonProperty("created_on")] [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime CreatedOn { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Job; } } diff --git a/Hangfire.AzureDocumentDB/Entities/List.cs b/Hangfire.AzureDocumentDB/Entities/List.cs index e1a4860..bc30b69 100644 --- a/Hangfire.AzureDocumentDB/Entities/List.cs +++ b/Hangfire.AzureDocumentDB/Entities/List.cs @@ -9,5 +9,7 @@ internal class List : DocumentEntity [JsonProperty("value")] public string Value { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.List; } } diff --git a/Hangfire.AzureDocumentDB/Entities/Lock.cs b/Hangfire.AzureDocumentDB/Entities/Lock.cs index 4c116a0..27fc751 100644 --- a/Hangfire.AzureDocumentDB/Entities/Lock.cs +++ b/Hangfire.AzureDocumentDB/Entities/Lock.cs @@ -6,5 +6,7 @@ internal class Lock : DocumentEntity { [JsonProperty("name")] public string Name { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Lock; } } diff --git a/Hangfire.AzureDocumentDB/Entities/Parameter.cs b/Hangfire.AzureDocumentDB/Entities/Parameter.cs index 22404d3..55fb74b 100644 --- a/Hangfire.AzureDocumentDB/Entities/Parameter.cs +++ b/Hangfire.AzureDocumentDB/Entities/Parameter.cs @@ -2,7 +2,7 @@ namespace Hangfire.AzureDocumentDB.Entities { - internal class Parameter : DocumentEntity + internal class Parameter { [JsonProperty("name")] public string Name { get; set; } diff --git a/Hangfire.AzureDocumentDB/Entities/Queue.cs b/Hangfire.AzureDocumentDB/Entities/Queue.cs index 91525e4..06ade67 100644 --- a/Hangfire.AzureDocumentDB/Entities/Queue.cs +++ b/Hangfire.AzureDocumentDB/Entities/Queue.cs @@ -9,5 +9,7 @@ class Queue : DocumentEntity [JsonProperty("job_id")] public string JobId { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Queue; } } diff --git a/Hangfire.AzureDocumentDB/Entities/Server.cs b/Hangfire.AzureDocumentDB/Entities/Server.cs index 117bbdb..7b46e49 100644 --- a/Hangfire.AzureDocumentDB/Entities/Server.cs +++ b/Hangfire.AzureDocumentDB/Entities/Server.cs @@ -22,5 +22,7 @@ internal class Server : DocumentEntity [JsonProperty("last_heartbeat")] [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime LastHeartbeat { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Server; } } \ No newline at end of file diff --git a/Hangfire.AzureDocumentDB/Entities/Set.cs b/Hangfire.AzureDocumentDB/Entities/Set.cs index d9ba1b2..c5f0022 100644 --- a/Hangfire.AzureDocumentDB/Entities/Set.cs +++ b/Hangfire.AzureDocumentDB/Entities/Set.cs @@ -12,5 +12,7 @@ internal class Set : DocumentEntity [JsonProperty("score")] public double? Score { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.Set; } } \ No newline at end of file diff --git a/Hangfire.AzureDocumentDB/Entities/State.cs b/Hangfire.AzureDocumentDB/Entities/State.cs index ca9f5a5..14f81c1 100644 --- a/Hangfire.AzureDocumentDB/Entities/State.cs +++ b/Hangfire.AzureDocumentDB/Entities/State.cs @@ -20,8 +20,10 @@ internal class State : DocumentEntity [JsonProperty("created_on")] [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime CreatedOn { get; set; } - + [JsonProperty("data")] public Dictionary Data { get; set; } + + public override DocumentTypes DocumentType { get; set; } = DocumentTypes.State; } } \ No newline at end of file From 7924ae3310330ddf52689adc39c85e3a62dc4c8e Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Sat, 29 Apr 2017 17:09:32 -0400 Subject: [PATCH 02/12] removed the lower case name converter. --- .../Hangfire.AzureDocumentDB.csproj | 1 - ...eDelimitedPropertyNamesContractResovler.cs | 62 ------------------- 2 files changed, 63 deletions(-) delete mode 100644 Hangfire.AzureDocumentDB/Json/LowerCaseDelimitedPropertyNamesContractResovler.cs diff --git a/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj b/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj index 326e9af..5c3982e 100644 --- a/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj +++ b/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj @@ -90,7 +90,6 @@ - diff --git a/Hangfire.AzureDocumentDB/Json/LowerCaseDelimitedPropertyNamesContractResovler.cs b/Hangfire.AzureDocumentDB/Json/LowerCaseDelimitedPropertyNamesContractResovler.cs deleted file mode 100644 index 74b4092..0000000 --- a/Hangfire.AzureDocumentDB/Json/LowerCaseDelimitedPropertyNamesContractResovler.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Linq; -using System.Collections; -using System.Globalization; - -using Newtonsoft.Json.Serialization; - -namespace Hangfire.AzureDocumentDB.Json -{ - internal class LowerCaseDelimitedPropertyNamesContractResovler : DefaultContractResolver - { - private readonly char _delimiter; - - public LowerCaseDelimitedPropertyNamesContractResovler() : this('_') { } - - private LowerCaseDelimitedPropertyNamesContractResovler(char delimiter) - { - _delimiter = delimiter; - } - - protected override string ResolvePropertyName(string propertyName) - { - string camelCaseString = ToCamelCase(propertyName); - return new string(InsertDelimiterBeforeCaps(camelCaseString, _delimiter).OfType().ToArray()); - } - - private static IEnumerable InsertDelimiterBeforeCaps(IEnumerable input, char delimiter) - { - bool lastCharWasUppper = false; - foreach (char c in input) - { - if (char.IsUpper(c)) - { - if (!lastCharWasUppper) - { - yield return delimiter; - lastCharWasUppper = true; - } - yield return char.ToLower(c); - continue; - } - yield return c; - lastCharWasUppper = false; - } - } - - private static string ToCamelCase(string s) - { - if (string.IsNullOrEmpty(s)) - return s; - - if (!char.IsUpper(s[0])) - return s; - - string camelCase = char.ToLower(s[0], CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture); - if (s.Length > 1) - camelCase += s.Substring(1); - - return camelCase; - } - - } -} \ No newline at end of file From a7b84295777bb528c01e6951c42e233e3f91b2c7 Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Sat, 29 Apr 2017 17:13:50 -0400 Subject: [PATCH 03/12] two new properties DefaultCollectionName, CollectionPrefix --- .../AzureDocumentDbStorageOptions.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbStorageOptions.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbStorageOptions.cs index 5659feb..ca3a195 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbStorageOptions.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbStorageOptions.cs @@ -10,13 +10,18 @@ namespace Hangfire.AzureDocumentDB public class AzureDocumentDbStorageOptions { internal Uri Endpoint { get; set; } - internal string AuthSecret { get; set; } + internal string DatabaseName { get; set; } /// - /// Get or sets the name of the database to connect. + /// Get or sets the default collection to be used for all the documents /// - internal string DatabaseName { get; set; } + public string DefaultCollectionName { get; set; } + + /// + /// Get or sets the prefix before the document collections. It will only applied of DefaultCollection name is empty + /// + public string CollectionPrefix { get; set; } /// /// Get or sets the request timemout for IFirebaseConfig. Default value set to 30 seconds From ed66c3520a6297b6b0d8173ddeb06b5cd8913927 Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Sat, 29 Apr 2017 17:14:43 -0400 Subject: [PATCH 04/12] consolidated the collection Uri and use defualt collection if defined --- .../AzureDocumentDbStorage.cs | 85 ++++++++++++++----- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbStorage.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbStorage.cs index 26cc6c5..7018e57 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbStorage.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbStorage.cs @@ -22,6 +22,8 @@ public sealed class AzureDocumentDbStorage : JobStorage internal DocumentClient Client { get; } + internal DocumentCollections Collections { get; set; } + /// /// Initializes the FirebaseStorage form the url auth secret provide. /// @@ -58,7 +60,7 @@ private AzureDocumentDbStorage(AzureDocumentDbStorageOptions options) Client = new DocumentClient(options.Endpoint, options.AuthSecret, connectionPolicy); Client.OpenAsync().GetAwaiter().GetResult(); - // create the database all the collections + Collections = new DocumentCollections(options.DatabaseName, options.CollectionPrefix, options.DefaultCollectionName); Initialize(); Newtonsoft.Json.JsonConvert.DefaultSettings = () => new Newtonsoft.Json.JsonSerializerSettings @@ -126,24 +128,33 @@ private void Initialize() // create database logger.Info($"Creating database : {Options.DatabaseName}"); Client.CreateDatabaseIfNotExistsAsync(new Database { Id = Options.DatabaseName }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : servers"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "servers" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : queues"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "queues" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : hashes"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "hashes" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : lists"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "lists" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : counters"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "counters" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : jobs"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "jobs" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : states"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "states" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : sets"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "sets" }).GetAwaiter().GetResult(); - logger.Info("Creating document collection : locks"); - Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = "locks" }).GetAwaiter().GetResult(); + + if (string.IsNullOrEmpty(Options.DefaultCollectionName)) + { + logger.Info("Creating document collection : servers"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}servers" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : queues"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}queues" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : hashes"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}hashes" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : lists"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}lists" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : counters"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}counters" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : jobs"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}jobs" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : states"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}states" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : sets"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}sets" }).GetAwaiter().GetResult(); + logger.Info("Creating document collection : locks"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = $"{Options.CollectionPrefix}locks" }).GetAwaiter().GetResult(); + } + else + { + logger.Info($"Creating document collection : {Options.DefaultCollectionName}"); + Client.CreateDocumentCollectionIfNotExistsAsync(databaseUri, new DocumentCollection { Id = Options.DefaultCollectionName }).GetAwaiter().GetResult(); + } } private static AzureDocumentDbStorageOptions Transform(string url, string authSecret, string database, AzureDocumentDbStorageOptions options) @@ -154,8 +165,44 @@ private static AzureDocumentDbStorageOptions Transform(string url, string authSe options.AuthSecret = authSecret; options.DatabaseName = database; + if (!string.IsNullOrEmpty(options.CollectionPrefix)) + { + options.CollectionPrefix = $"{options.CollectionPrefix}_"; + } + + if (string.IsNullOrEmpty(options.DefaultCollectionName)) + { + options.DefaultCollectionName = null; + } + return options; } } + + internal class DocumentCollections + { + public readonly Uri JobDocumentCollectionUri; + public readonly Uri StateDocumentCollectionUri; + public readonly Uri SetDocumentCollectionUri; + public readonly Uri CounterDocumentCollectionUri; + public readonly Uri ServerDocumentCollectionUri; + public readonly Uri HashDocumentCollectionUri; + public readonly Uri ListDocumentCollectionUri; + public readonly Uri LockDocumentCollectionUri; + public readonly Uri QueueDocumentCollectionUri; + + public DocumentCollections(string databaseName, string prefix, string defaultCollectionName) + { + JobDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}jobs"); + StateDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}states"); + SetDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}sets"); + CounterDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}counters"); + ServerDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}servers"); + HashDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}hashes"); + ListDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}lists"); + LockDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}locks"); + QueueDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(databaseName, defaultCollectionName ?? $"{prefix}queues"); + } + } } From dd3be944bc6f0142b515db8c72e6c997c6418f95 Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Thu, 11 May 2017 20:58:41 -0400 Subject: [PATCH 05/12] assigned underlying value to enums --- .../Entities/DocumentEntity.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs b/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs index 01c259b..d24a97a 100644 --- a/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs +++ b/Hangfire.AzureDocumentDB/Entities/DocumentEntity.cs @@ -22,14 +22,14 @@ internal abstract class DocumentEntity internal enum DocumentTypes { - Server, - Job, - Queue, - Counter, - List, - Hash, - Set, - State, - Lock + Server = 1, + Job = 2, + Queue = 3, + Counter = 4, + List = 5, + Hash = 6, + Set = 7, + State = 8, + Lock = 9 } } From bcb4a140b44a2734c9ed6c2a1dfb4b84f74cd423 Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Thu, 11 May 2017 21:01:19 -0400 Subject: [PATCH 06/12] changed for use of single document collection URI --- .../AzureDocumentDbConnection.cs | 115 +++++++++--------- .../AzureDocumentDbDistributedLock.cs | 12 +- .../AzureDocumentDbMonitoringApi.cs | 84 ++++++------- .../AzureDocumentDbWriteOnlyTransaction.cs | 68 +++++------ .../CountersAggregator.cs | 16 ++- Hangfire.AzureDocumentDB/ExpirationManager.cs | 72 +++++++---- .../Queue/Entities/FetchedJob.cs | 12 +- Hangfire.AzureDocumentDB/Queue/JobQueue.cs | 8 +- .../Queue/JobQueueMonitoringApi.cs | 22 ++-- 9 files changed, 204 insertions(+), 205 deletions(-) diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbConnection.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbConnection.cs index 503c95b..78034e4 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbConnection.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbConnection.cs @@ -22,26 +22,11 @@ internal sealed class AzureDocumentDbConnection : JobStorageConnection public PersistentJobQueueProviderCollection QueueProviders { get; } private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = -1 }; - private readonly Uri JobDocumentCollectionUri; - private readonly Uri StateDocumentCollectionUri; - private readonly Uri SetDocumentCollectionUri; - private readonly Uri CounterDocumentCollectionUri; - private readonly Uri ServerDocumentCollectionUri; - private readonly Uri HashDocumentCollectionUri; - private readonly Uri ListDocumentCollectionUri; public AzureDocumentDbConnection(AzureDocumentDbStorage storage) { Storage = storage; QueueProviders = storage.QueueProviders; - - JobDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "jobs"); - StateDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "states"); - SetDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "sets"); - CounterDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "counters"); - ServerDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "servers"); - HashDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "hashes"); - ListDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(Storage.Options.DatabaseName, "lists"); } public override IDisposable AcquireDistributedLock(string resource, TimeSpan timeout) => new AzureDocumentDbDistributedLock(resource, timeout, Storage); @@ -69,7 +54,7 @@ public override string CreateExpiredJob(Common.Job job, IDictionary response = Storage.Client.CreateDocumentAsync(JobDocumentCollectionUri, entityJob).GetAwaiter().GetResult(); + ResourceResponse response = Storage.Client.CreateDocumentAsync(Storage.Collections.JobDocumentCollectionUri, entityJob).GetAwaiter().GetResult(); if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.OK) { return entityJob.Id; @@ -100,7 +85,7 @@ public override JobData GetJobData(string jobId) { if (jobId == null) throw new ArgumentNullException(nameof(jobId)); - Entities.Job data = Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + Entities.Job data = Storage.Client.CreateDocumentQuery(Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .AsEnumerable() .FirstOrDefault(); @@ -138,7 +123,8 @@ public override StateData GetStateData(string jobId) { if (jobId == null) throw new ArgumentNullException(nameof(jobId)); - string stateId = Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + string stateId = Storage.Client.CreateDocumentQuery(Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .Select(j => j.StateId) .AsEnumerable() @@ -146,8 +132,8 @@ public override StateData GetStateData(string jobId) if (!string.IsNullOrEmpty(stateId)) { - State state = Storage.Client.CreateDocumentQuery(StateDocumentCollectionUri, QueryOptions) - .Where(j => j.Id == stateId) + State state = Storage.Client.CreateDocumentQuery(Storage.Collections.StateDocumentCollectionUri, QueryOptions) + .Where(s => s.Id == stateId) .AsEnumerable() .FirstOrDefault(); @@ -174,7 +160,7 @@ public override string GetJobParameter(string id, string name) if (id == null) throw new ArgumentNullException(nameof(id)); if (name == null) throw new ArgumentNullException(nameof(name)); - List parameters = Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + List parameters = Storage.Client.CreateDocumentQuery(Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == id) .AsEnumerable() .SelectMany(j => j.Parameters) @@ -188,7 +174,7 @@ public override void SetJobParameter(string id, string name, string value) if (id == null) throw new ArgumentNullException(nameof(id)); if (name == null) throw new ArgumentNullException(nameof(name)); - Entities.Job job = Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + Entities.Job job = Storage.Client.CreateDocumentQuery(Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == id) .AsEnumerable() .FirstOrDefault(); @@ -222,8 +208,8 @@ public override TimeSpan GetSetTtl(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - DateTime? expireOn = Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key) + DateTime? expireOn = Storage.Client.CreateDocumentQuery(Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.DocumentType == DocumentTypes.Set) .Min(s => s.ExpireOn); return expireOn.HasValue ? expireOn.Value - DateTime.UtcNow : TimeSpan.FromSeconds(-1); @@ -233,8 +219,8 @@ public override List GetRangeFromSet(string key, int startingFrom, int e { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.DocumentType == DocumentTypes.Set) .AsEnumerable() .Skip(startingFrom).Take(endingAt) .Select(c => c.Value) @@ -245,8 +231,8 @@ public override long GetCounter(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(CounterDocumentCollectionUri, QueryOptions) - .Where(c => c.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.CounterDocumentCollectionUri, QueryOptions) + .Where(c => c.Key == key && c.DocumentType == DocumentTypes.Counter) .Sum(c => c.Value); } @@ -254,9 +240,9 @@ public override long GetSetCount(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key) - .Select(s => s.Id) + return Storage.Client.CreateDocumentQuery(Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.DocumentType == DocumentTypes.Set) + .Select(s => 1) .AsEnumerable() .LongCount(); } @@ -265,8 +251,8 @@ public override HashSet GetAllItemsFromSet(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - List sets = Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key) + List sets = Storage.Client.CreateDocumentQuery(Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.DocumentType == DocumentTypes.Set) .Select(s => s.Value) .AsEnumerable() .ToList(); @@ -279,8 +265,8 @@ public override string GetFirstByLowestScoreFromSet(string key, double fromScore if (key == null) throw new ArgumentNullException(nameof(key)); if (toScore < fromScore) throw new ArgumentException("The `toScore` value must be higher or equal to the `fromScore` value."); - return Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.DocumentType == DocumentTypes.Set) .OrderBy(s => s.Score) .Where(s => s.Score >= fromScore && s.Score <= toScore) .Select(s => s.Value) @@ -297,7 +283,8 @@ public override void AnnounceServer(string serverId, ServerContext context) if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (context == null) throw new ArgumentNullException(nameof(context)); - Entities.Server server = Storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + Entities.Server server = Storage.Client.CreateDocumentQuery(Storage.Collections.ServerDocumentCollectionUri, QueryOptions) .Where(s => s.ServerId == serverId) .AsEnumerable() .FirstOrDefault(); @@ -320,14 +307,15 @@ public override void AnnounceServer(string serverId, ServerContext context) }; } - Storage.Client.UpsertDocumentAsync(ServerDocumentCollectionUri, server).GetAwaiter().GetResult(); + Storage.Client.UpsertDocumentAsync(Storage.Collections.ServerDocumentCollectionUri, server).GetAwaiter().GetResult(); } public override void Heartbeat(string serverId) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); - Entities.Server server = Storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + Entities.Server server = Storage.Client.CreateDocumentQuery(Storage.Collections.ServerDocumentCollectionUri, QueryOptions) .Where(s => s.ServerId == serverId) .AsEnumerable() .FirstOrDefault(); @@ -343,7 +331,8 @@ public override void RemoveServer(string serverId) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); - Entities.Server server = Storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + Entities.Server server = Storage.Client.CreateDocumentQuery(Storage.Collections.ServerDocumentCollectionUri, QueryOptions) .Where(s => s.ServerId == serverId) .AsEnumerable() .FirstOrDefault(); @@ -362,7 +351,10 @@ public override int RemoveTimedOutServers(TimeSpan timeOut) } DateTime lastHeartbeat = DateTime.UtcNow.Add(timeOut.Negate()); - string[] selfLinks = Storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) + + // TODO: move to stored procedure + string[] selfLinks = Storage.Client.CreateDocumentQuery(Storage.Collections.ServerDocumentCollectionUri, QueryOptions) + .Where(s => s.DocumentType == DocumentTypes.Server) .AsEnumerable() .Where(s => s.LastHeartbeat < lastHeartbeat) .Select(s => s.SelfLink) @@ -380,8 +372,8 @@ public override Dictionary GetAllEntriesFromHash(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) .AsEnumerable() .ToDictionary(h => h.Field, h => h.Value); } @@ -391,6 +383,7 @@ public override void SetRangeInHash(string key, IEnumerable epoch = s => { DateTime date; @@ -412,8 +405,8 @@ public override void SetRangeInHash(string key, IEnumerable hashes = Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + List hashes = Storage.Client.CreateDocumentQuery(Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) .AsEnumerable() .ToList(); @@ -423,15 +416,17 @@ public override void SetRangeInHash(string key, IEnumerable Storage.Client.UpsertDocumentAsync(HashDocumentCollectionUri, hash).GetAwaiter().GetResult()); + sources.ForEach(hash => Storage.Client.UpsertDocumentAsync(Storage.Collections.HashDocumentCollectionUri, hash).GetAwaiter().GetResult()); } public override long GetHashCount(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) + .Select(h => 1) + .AsEnumerable() .LongCount(); } @@ -440,8 +435,8 @@ public override string GetValueFromHash(string key, string name) if (key == null) throw new ArgumentNullException(nameof(key)); if (name == null) throw new ArgumentNullException(nameof(name)); - return Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key && h.Field == name) + return Storage.Client.CreateDocumentQuery(Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.Field == name && h.DocumentType == DocumentTypes.Hash) .Select(h => h.Value) .AsEnumerable() .FirstOrDefault(); @@ -451,8 +446,8 @@ public override TimeSpan GetHashTtl(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - DateTime? expireOn = Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + DateTime? expireOn = Storage.Client.CreateDocumentQuery(Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) .Min(h => h.ExpireOn); return expireOn.HasValue ? expireOn.Value - DateTime.UtcNow : TimeSpan.FromSeconds(-1); @@ -466,8 +461,8 @@ public override List GetAllItemsFromList(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.DocumentType == DocumentTypes.List) .Select(l => l.Value) .AsEnumerable() .ToList(); @@ -477,8 +472,8 @@ public override List GetRangeFromList(string key, int startingFrom, int { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.DocumentType == DocumentTypes.List) .AsEnumerable() .OrderBy(l => l.ExpireOn) .Skip(startingFrom).Take(endingAt) @@ -490,8 +485,8 @@ public override TimeSpan GetListTtl(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - DateTime? expireOn = Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key) + DateTime? expireOn = Storage.Client.CreateDocumentQuery(Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.DocumentType == DocumentTypes.List) .Min(l => l.ExpireOn); return expireOn.HasValue ? expireOn.Value - DateTime.UtcNow : TimeSpan.FromSeconds(-1); @@ -501,8 +496,10 @@ public override long GetListCount(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); - return Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key) + return Storage.Client.CreateDocumentQuery(Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.DocumentType == DocumentTypes.List) + .Select(l => 1) + .AsEnumerable() .LongCount(); } diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbDistributedLock.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbDistributedLock.cs index 8cba7ec..9aad618 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbDistributedLock.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbDistributedLock.cs @@ -24,23 +24,21 @@ public AzureDocumentDbDistributedLock(string resource, TimeSpan timeout, AzureDo private void Acquire(string name, TimeSpan timeout) { - Uri documentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "locks"); FeedOptions queryOptions = new FeedOptions { MaxItemCount = 1 }; - System.Diagnostics.Stopwatch acquireStart = new System.Diagnostics.Stopwatch(); acquireStart.Start(); while (true) { - Lock @lock = storage.Client.CreateDocumentQuery(documentCollectionUri, queryOptions) - .Where(l => l.Name == name) - .AsEnumerable() - .FirstOrDefault(); + Lock @lock = storage.Client.CreateDocumentQuery(storage.Collections.LockDocumentCollectionUri, queryOptions) + .Where(l => l.Name == name && l.DocumentType == DocumentTypes.Lock) + .AsEnumerable() + .FirstOrDefault(); if (@lock == null) { @lock = new Lock { Name = name, ExpireOn = DateTime.UtcNow.Add(timeout) }; - ResourceResponse response = storage.Client.CreateDocumentAsync(documentCollectionUri, @lock).GetAwaiter().GetResult(); + ResourceResponse response = storage.Client.CreateDocumentAsync(storage.Collections.LockDocumentCollectionUri, @lock).GetAwaiter().GetResult(); if (response.StatusCode == HttpStatusCode.Created) { selfLink = response.Resource.SelfLink; diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbMonitoringApi.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbMonitoringApi.cs index 7f0be63..06113ae 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbMonitoringApi.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbMonitoringApi.cs @@ -15,25 +15,11 @@ namespace Hangfire.AzureDocumentDB internal sealed class AzureDocumentDbMonitoringApi : IMonitoringApi { private readonly AzureDocumentDbStorage storage; - private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = -1 }; - private readonly Uri JobDocumentCollectionUri; - private readonly Uri StateDocumentCollectionUri; - private readonly Uri SetDocumentCollectionUri; - private readonly Uri CounterDocumentCollectionUri; - private readonly Uri ServerDocumentCollectionUri; - private readonly Uri QueueDocumentCollectionUri; public AzureDocumentDbMonitoringApi(AzureDocumentDbStorage storage) { this.storage = storage; - - JobDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "jobs"); - StateDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "states"); - SetDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "sets"); - CounterDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "counters"); - ServerDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "servers"); - QueueDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "queues"); } public IList Queues() @@ -58,25 +44,24 @@ public IList Queues() public IList Servers() { - List servers = storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) + return storage.Client.CreateDocumentQuery(storage.Collections.ServerDocumentCollectionUri, QueryOptions) + .Where(s => s.DocumentType == DocumentTypes.Server) .AsEnumerable() - .ToList(); - - return servers.Select(server => new ServerDto - { - Name = server.ServerId, - Heartbeat = server.LastHeartbeat, - Queues = server.Queues, - StartedAt = server.CreatedOn, - WorkersCount = server.Workers - }).ToList(); + .Select(server => new ServerDto + { + Name = server.ServerId, + Heartbeat = server.LastHeartbeat, + Queues = server.Queues, + StartedAt = server.CreatedOn, + WorkersCount = server.Workers + }).ToList(); } public JobDetailsDto JobDetails(string jobId) { if (string.IsNullOrEmpty(jobId)) throw new ArgumentNullException(nameof(jobId)); - Entities.Job job = storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + Entities.Job job = storage.Client.CreateDocumentQuery(storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .AsEnumerable() .FirstOrDefault(); @@ -86,7 +71,7 @@ public JobDetailsDto JobDetails(string jobId) InvocationData invocationData = job.InvocationData; invocationData.Arguments = job.Arguments; - List states = storage.Client.CreateDocumentQuery(StateDocumentCollectionUri, QueryOptions) + List states = storage.Client.CreateDocumentQuery(storage.Collections.StateDocumentCollectionUri, QueryOptions) .Where(s => s.JobId == jobId) .AsEnumerable() .Select(s => new StateHistoryDto @@ -112,10 +97,12 @@ public JobDetailsDto JobDetails(string jobId) public StatisticsDto GetStatistics() { + // TODO: move to stored procedure Dictionary results = new Dictionary(); // get counts of jobs groupby on state - Dictionary states = storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + Dictionary states = storage.Client.CreateDocumentQuery(storage.Collections.JobDocumentCollectionUri, QueryOptions) + .Where(j => j.DocumentType == DocumentTypes.Job) .Select(j => j.StateName) .AsEnumerable() .Where(j => !string.IsNullOrEmpty(j)) @@ -125,15 +112,16 @@ public StatisticsDto GetStatistics() results = results.Concat(states).ToDictionary(k => k.Key, v => v.Value); // get counts of servers - long servers = storage.Client.CreateDocumentQuery(ServerDocumentCollectionUri, QueryOptions) - .Select(s => s.Id) + long servers = storage.Client.CreateDocumentQuery(storage.Collections.ServerDocumentCollectionUri, QueryOptions) + .Where(s => s.DocumentType == DocumentTypes.Server) + .Select(s => 1) .AsEnumerable() .LongCount(); results.Add("Servers", servers); // get sum of stats:succeeded counters raw / aggregate - Dictionary counters = storage.Client.CreateDocumentQuery(CounterDocumentCollectionUri, QueryOptions) - .Where(c => c.Key == "stats:succeeded" || c.Key == "stats:deleted") + Dictionary counters = storage.Client.CreateDocumentQuery(storage.Collections.CounterDocumentCollectionUri, QueryOptions) + .Where(c => (c.Key == "stats:succeeded" || c.Key == "stats:deleted") && c.DocumentType == DocumentTypes.Counter) .AsEnumerable() .GroupBy(c => c.Key) .ToDictionary(g => g.Key, g => (long)g.Sum(c => c.Value)); @@ -141,9 +129,9 @@ public StatisticsDto GetStatistics() results = results.Concat(counters).ToDictionary(k => k.Key, v => v.Value); long count = 0; - count += storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == "recurring-jobs") - .Select(s => s.Id) + count += storage.Client.CreateDocumentQuery(storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == "recurring-jobs" && s.DocumentType == DocumentTypes.Set) + .Select(s => 1) .AsEnumerable() .LongCount(); @@ -241,15 +229,17 @@ public JobList DeletedJobs(int from, int count) private JobList GetJobsOnState(string stateName, int from, int count, Func selector) { + // TODO: move to stored procedure List> jobs = new List>(); - List filterJobs = storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) - .Where(j => j.StateName == stateName) + List filterJobs = storage.Client.CreateDocumentQuery(storage.Collections.JobDocumentCollectionUri, QueryOptions) + .Where(j => j.DocumentType == DocumentTypes.Job && j.StateName == stateName) .AsEnumerable() .Skip(from).Take(count) .ToList(); - List states = storage.Client.CreateDocumentQuery(StateDocumentCollectionUri, QueryOptions) + List states = storage.Client.CreateDocumentQuery(storage.Collections.StateDocumentCollectionUri, QueryOptions) + .Where(s => s.DocumentType == DocumentTypes.State) .AsEnumerable() .Where(s => filterJobs.Any(j => j.StateId == s.Id)) .ToList(); @@ -273,15 +263,17 @@ private JobList GetJobsOnQueue(string queue, int from, int count, Func> jobs = new List>(); - List queues = storage.Client.CreateDocumentQuery(QueueDocumentCollectionUri, QueryOptions) - .Where(q => q.Name == queue) + List queues = storage.Client.CreateDocumentQuery(storage.Collections.QueueDocumentCollectionUri, QueryOptions) + .Where(q => q.Name == queue && q.DocumentType == DocumentTypes.Queue) .AsEnumerable() .Skip(from).Take(count) .ToList(); - List filterJobs = storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + List filterJobs = storage.Client.CreateDocumentQuery(storage.Collections.JobDocumentCollectionUri, QueryOptions) + .Where(j => j.DocumentType == DocumentTypes.Job) .AsEnumerable() .Where(j => queues.Any(q => q.JobId == j.Id)) .ToList(); @@ -326,9 +318,9 @@ public long EnqueuedCount(string queue) private long GetNumberOfJobsByStateName(string state) { - return storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) - .Where(j => j.StateName == state) - .Select(s => s.Id) + return storage.Client.CreateDocumentQuery(storage.Collections.JobDocumentCollectionUri, QueryOptions) + .Where(j => j.DocumentType == DocumentTypes.Job && j.StateName == state) + .Select(s => 1) .AsEnumerable() .LongCount(); } @@ -359,8 +351,8 @@ private Dictionary GetTimelineStats(Dictionary { Dictionary result = keys.ToDictionary(k => k.Value, v => default(long)); - Dictionary data = storage.Client.CreateDocumentQuery(CounterDocumentCollectionUri, QueryOptions) - .Where(c => c.Type == CounterTypes.Aggregrate) + Dictionary data = storage.Client.CreateDocumentQuery(storage.Collections.CounterDocumentCollectionUri, QueryOptions) + .Where(c => c.Type == CounterTypes.Aggregrate && c.DocumentType == DocumentTypes.Counter) .AsEnumerable() .Where(c => keys.ContainsKey(c.Key)) .ToDictionary(k => k.Key, k => k.Value); diff --git a/Hangfire.AzureDocumentDB/AzureDocumentDbWriteOnlyTransaction.cs b/Hangfire.AzureDocumentDB/AzureDocumentDbWriteOnlyTransaction.cs index 663ba56..d92787a 100644 --- a/Hangfire.AzureDocumentDB/AzureDocumentDbWriteOnlyTransaction.cs +++ b/Hangfire.AzureDocumentDB/AzureDocumentDbWriteOnlyTransaction.cs @@ -19,24 +19,10 @@ internal class AzureDocumentDbWriteOnlyTransaction : IWriteOnlyTransaction private readonly List commands = new List(); private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 100 }; - private readonly Uri JobDocumentCollectionUri; - private readonly Uri SetDocumentCollectionUri; - private readonly Uri StateDocumentCollectionUri; - private readonly Uri CounterDocumentCollectionUri; - private readonly Uri HashDocumentCollectionUri; - private readonly Uri ListDocumentCollectionUri; public AzureDocumentDbWriteOnlyTransaction(AzureDocumentDbConnection connection) { this.connection = connection; - - AzureDocumentDbStorage storage = connection.Storage; - JobDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "jobs"); - SetDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "sets"); - StateDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "states"); - CounterDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "counters"); - HashDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "hashes"); - ListDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "lists"); } private void QueueCommand(Action command) => commands.Add(command); @@ -72,7 +58,7 @@ public void DecrementCounter(string key) Value = -1 }; - connection.Storage.Client.CreateDocumentAsync(CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -91,7 +77,7 @@ public void DecrementCounter(string key, TimeSpan expireIn) ExpireOn = DateTime.UtcNow.Add(expireIn) }; - connection.Storage.Client.CreateDocumentAsync(CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -108,7 +94,7 @@ public void IncrementCounter(string key) Value = 1 }; - connection.Storage.Client.CreateDocumentAsync(CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -127,7 +113,7 @@ public void IncrementCounter(string key, TimeSpan expireIn) ExpireOn = DateTime.UtcNow.Add(expireIn) }; - connection.Storage.Client.CreateDocumentAsync(CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.CounterDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -142,7 +128,8 @@ public void ExpireJob(string jobId, TimeSpan expireIn) QueueCommand(() => { - Job job = connection.Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + Job job = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .AsEnumerable() .FirstOrDefault(); @@ -161,7 +148,7 @@ public void PersistJob(string jobId) QueueCommand(() => { - Job job = connection.Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + Job job = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .AsEnumerable() .FirstOrDefault(); @@ -185,7 +172,8 @@ public void SetJobState(string jobId, IState state) QueueCommand(() => { - Job job = connection.Storage.Client.CreateDocumentQuery(JobDocumentCollectionUri, QueryOptions) + // TODO: move to stored procedure + Job job = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.Id == jobId) .AsEnumerable() .FirstOrDefault(); @@ -201,7 +189,7 @@ public void SetJobState(string jobId, IState state) Data = state.SerializeData() }; - ResourceResponse response = connection.Storage.Client.CreateDocumentAsync(StateDocumentCollectionUri, data).GetAwaiter().GetResult(); + ResourceResponse response = connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.StateDocumentCollectionUri, data).GetAwaiter().GetResult(); job.StateId = response.Resource.Id; job.StateName = state.Name; @@ -227,7 +215,7 @@ public void AddJobState(string jobId, IState state) Data = state.SerializeData() }; - connection.Storage.Client.CreateDocumentAsync(StateDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.StateDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -242,8 +230,8 @@ public void RemoveFromSet(string key, string value) QueueCommand(() => { - Set set = connection.Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key && s.Value == value) + Set set = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.Value == value && s.DocumentType == DocumentTypes.Set) .AsEnumerable() .FirstOrDefault(); @@ -263,8 +251,8 @@ public void AddToSet(string key, string value, double score) QueueCommand(() => { - Set set = connection.Storage.Client.CreateDocumentQuery(SetDocumentCollectionUri, QueryOptions) - .Where(s => s.Key == key && s.Value == value) + Set set = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.SetDocumentCollectionUri, QueryOptions) + .Where(s => s.Key == key && s.Value == value && s.DocumentType == DocumentTypes.Set) .AsEnumerable() .FirstOrDefault(); @@ -284,7 +272,7 @@ public void AddToSet(string key, string value, double score) }; } - connection.Storage.Client.UpsertDocumentAsync(SetDocumentCollectionUri, set).GetAwaiter().GetResult(); + connection.Storage.Client.UpsertDocumentAsync(connection.Storage.Collections.SetDocumentCollectionUri, set).GetAwaiter().GetResult(); }); } @@ -298,8 +286,9 @@ public void RemoveHash(string key) QueueCommand(() => { - List hashes = connection.Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + // TODO: move to stored procedure + List hashes = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) .AsEnumerable() .ToList(); @@ -314,6 +303,7 @@ public void SetRangeInHash(string key, IEnumerable> QueueCommand(() => { + // TODO: move to stored procedure Func epoch = s => { DateTime date; @@ -334,8 +324,8 @@ public void SetRangeInHash(string key, IEnumerable> Value = epoch(k.Value) }).ToList(); - List hashes = connection.Storage.Client.CreateDocumentQuery(HashDocumentCollectionUri, QueryOptions) - .Where(h => h.Key == key) + List hashes = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.HashDocumentCollectionUri, QueryOptions) + .Where(h => h.Key == key && h.DocumentType == DocumentTypes.Hash) .AsEnumerable() .ToList(); @@ -345,7 +335,7 @@ public void SetRangeInHash(string key, IEnumerable> if (hash != null) source.Id = hash.Id; }); - sources.ForEach(hash => connection.Storage.Client.UpsertDocumentAsync(HashDocumentCollectionUri, hash).GetAwaiter().GetResult()); + sources.ForEach(hash => connection.Storage.Client.UpsertDocumentAsync(connection.Storage.Collections.HashDocumentCollectionUri, hash).GetAwaiter().GetResult()); }); } @@ -366,7 +356,7 @@ public void InsertToList(string key, string value) Value = value }; - connection.Storage.Client.CreateDocumentAsync(ListDocumentCollectionUri, data).GetAwaiter().GetResult(); + connection.Storage.Client.CreateDocumentAsync(connection.Storage.Collections.ListDocumentCollectionUri, data).GetAwaiter().GetResult(); }); } @@ -377,8 +367,9 @@ public void RemoveFromList(string key, string value) QueueCommand(() => { - List data = connection.Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key && l.Value == value) + // TODO: move to stored procedure + List data = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.Value == value && l.DocumentType == DocumentTypes.List) .AsEnumerable() .FirstOrDefault(); @@ -395,8 +386,9 @@ public void TrimList(string key, int keepStartingFrom, int keepEndingAt) QueueCommand(() => { - List lists = connection.Storage.Client.CreateDocumentQuery(ListDocumentCollectionUri, QueryOptions) - .Where(l => l.Key == key) + // TODO: move to stored procedure + List lists = connection.Storage.Client.CreateDocumentQuery(connection.Storage.Collections.ListDocumentCollectionUri, QueryOptions) + .Where(l => l.Key == key && l.DocumentType == DocumentTypes.List) .AsEnumerable() .Skip(keepStartingFrom).Take(keepEndingAt) .ToList(); diff --git a/Hangfire.AzureDocumentDB/CountersAggregator.cs b/Hangfire.AzureDocumentDB/CountersAggregator.cs index 872f429..4a17efa 100644 --- a/Hangfire.AzureDocumentDB/CountersAggregator.cs +++ b/Hangfire.AzureDocumentDB/CountersAggregator.cs @@ -23,9 +23,7 @@ internal class CountersAggregator : IServerComponent private readonly TimeSpan checkInterval; private readonly AzureDocumentDbStorage storage; - private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 1000 }; - private readonly Uri CounterDocumentCollectionUri; public CountersAggregator(AzureDocumentDbStorage storage) { @@ -33,17 +31,17 @@ public CountersAggregator(AzureDocumentDbStorage storage) this.storage = storage; checkInterval = storage.Options.CountersAggregateInterval; - CounterDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "counters"); } public void Execute(CancellationToken cancellationToken) { + // TODO: move to stored procedure Logger.Debug("Aggregating records in 'Counter' table."); using (new AzureDocumentDbDistributedLock(distributedLockKey, defaultLockTimeout, storage)) { - List rawCounters = storage.Client.CreateDocumentQuery(CounterDocumentCollectionUri, QueryOptions) - .Where(c => c.Type == CounterTypes.Raw) + List rawCounters = storage.Client.CreateDocumentQuery(storage.Collections.CounterDocumentCollectionUri, QueryOptions) + .Where(c => c.Type == CounterTypes.Raw && c.DocumentType == DocumentTypes.Counter) .AsEnumerable() .ToList(); @@ -57,8 +55,8 @@ public void Execute(CancellationToken cancellationToken) Tuple data; if (counters.TryGetValue(key, out data)) { - Counter aggregated = storage.Client.CreateDocumentQuery(CounterDocumentCollectionUri, QueryOptions) - .Where(c => c.Key == key && c.Type == CounterTypes.Aggregrate) + Counter aggregated = storage.Client.CreateDocumentQuery(storage.Collections.CounterDocumentCollectionUri, QueryOptions) + .Where(c => c.Key == key && c.Type == CounterTypes.Aggregrate && c.DocumentType == DocumentTypes.Counter) .AsEnumerable() .FirstOrDefault(); @@ -78,8 +76,8 @@ public void Execute(CancellationToken cancellationToken) aggregated.ExpireOn = data.Item2; } - ResourceResponse response = storage.Client.UpsertDocumentAsync(CounterDocumentCollectionUri, aggregated).GetAwaiter().GetResult(); - if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.OK) + ResourceResponse response = storage.Client.UpsertDocumentAsync(storage.Collections.CounterDocumentCollectionUri, aggregated).GetAwaiter().GetResult(); + if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.OK) { List deleteCountersr = rawCounters.Where(c => c.Key == key).ToList(); deleteCountersr.ForEach(counter => storage.Client.DeleteDocumentAsync(counter.SelfLink).GetAwaiter().GetResult()); diff --git a/Hangfire.AzureDocumentDB/ExpirationManager.cs b/Hangfire.AzureDocumentDB/ExpirationManager.cs index 2376109..261e56a 100644 --- a/Hangfire.AzureDocumentDB/ExpirationManager.cs +++ b/Hangfire.AzureDocumentDB/ExpirationManager.cs @@ -37,36 +37,30 @@ public void Execute(CancellationToken cancellationToken) foreach (string document in documents) { Logger.Debug($"Removing outdated records from the '{document}' document."); + DocumentTypes type = document.ToDocumentType(); using (new AzureDocumentDbDistributedLock(distributedLockKey, defaultLockTimeout, storage)) { - string responseContinuation = null; - Uri collectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, document); + Uri collectionUri = document.ToDocumentCollectionUri(storage); + FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 50, }; + IDocumentQuery query = storage.Client.CreateDocumentQuery(collectionUri, QueryOptions) + .Where(d => d.DocumentType == type) + .AsDocumentQuery(); - do + while (query.HasMoreResults) { - FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 50, RequestContinuation = responseContinuation }; - IDocumentQuery query = storage.Client.CreateDocumentQuery(collectionUri, QueryOptions) - .AsDocumentQuery(); + FeedResponse response = query.ExecuteNextAsync(cancellationToken).GetAwaiter().GetResult(); - if (query.HasMoreResults) + List entities = response + .Where(c => c.ExpireOn < DateTime.UtcNow) + .Where(entity => document != "counters" || !(entity is Counter) || ((Counter)entity).Type != CounterTypes.Raw).ToList(); + + foreach (DocumentEntity entity in entities) { - FeedResponse response = query.ExecuteNextAsync(cancellationToken).GetAwaiter().GetResult(); - responseContinuation = response.ResponseContinuation; - - List entities = response - .Where(c => c.ExpireOn < DateTime.UtcNow) - .Where(entity => document != "counters" || !(entity is Counter) || ((Counter)entity).Type != CounterTypes.Raw).ToList(); - - foreach (DocumentEntity entity in entities) - { - cancellationToken.ThrowIfCancellationRequested(); - storage.Client.DeleteDocumentAsync(entity.SelfLink).GetAwaiter().GetResult(); - } + cancellationToken.ThrowIfCancellationRequested(); + storage.Client.DeleteDocumentAsync(entity.SelfLink).GetAwaiter().GetResult(); } - - } while (!string.IsNullOrEmpty(responseContinuation)); - + } } Logger.Trace($"Outdated records removed from the '{document}' document."); @@ -74,4 +68,38 @@ public void Execute(CancellationToken cancellationToken) } } } + + internal static class ExpirationManagerExtenison + { + internal static DocumentTypes ToDocumentType(this string document) + { + switch (document) + { + case "locks": return DocumentTypes.Lock; + case "jobs": return DocumentTypes.Job; + case "lists": return DocumentTypes.List; + case "sets": return DocumentTypes.Set; + case "hashes": return DocumentTypes.Hash; + case "counters": return DocumentTypes.Counter; + } + + throw new ArgumentException("invalid document type", nameof(document)); + } + + internal static Uri ToDocumentCollectionUri(this string document, AzureDocumentDbStorage storage) + { + switch (document) + { + case "locks": return storage.Collections.LockDocumentCollectionUri; + case "jobs": return storage.Collections.JobDocumentCollectionUri; + case "lists": return storage.Collections.ListDocumentCollectionUri; + case "sets": return storage.Collections.SetDocumentCollectionUri; + case "hashes": return storage.Collections.HashDocumentCollectionUri; + case "counters": return storage.Collections.CounterDocumentCollectionUri; + } + + throw new ArgumentException("invalid document type", nameof(document)); + + } + } } \ No newline at end of file diff --git a/Hangfire.AzureDocumentDB/Queue/Entities/FetchedJob.cs b/Hangfire.AzureDocumentDB/Queue/Entities/FetchedJob.cs index 6fb54d6..fe03b5c 100644 --- a/Hangfire.AzureDocumentDB/Queue/Entities/FetchedJob.cs +++ b/Hangfire.AzureDocumentDB/Queue/Entities/FetchedJob.cs @@ -10,7 +10,6 @@ namespace Hangfire.AzureDocumentDB.Queue internal class FetchedJob : IFetchedJob { private readonly AzureDocumentDbStorage storage; - private readonly Uri QueueDocumentCollectionUri; private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 1 }; public FetchedJob(AzureDocumentDbStorage storage, Entities.Queue data) @@ -20,7 +19,6 @@ public FetchedJob(AzureDocumentDbStorage storage, Entities.Queue data) JobId = data.JobId; Queue = data.Name; SelfLink = data.SelfLink; - QueueDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "queues"); } private string Id { get; } @@ -37,10 +35,10 @@ public void Dispose() public void RemoveFromQueue() { - bool exists = storage.Client.CreateDocumentQuery(QueueDocumentCollectionUri, QueryOptions) - .Where(d => d.Id == Id) - .AsEnumerable() - .Any(); + bool exists = storage.Client.CreateDocumentQuery(storage.Collections.QueueDocumentCollectionUri, QueryOptions) + .Where(d => d.Id == Id) + .AsEnumerable() + .Any(); if (exists) storage.Client.DeleteDocumentAsync(SelfLink).GetAwaiter().GetResult(); } @@ -53,7 +51,7 @@ public void Requeue() Name = Queue, JobId = JobId }; - storage.Client.UpsertDocumentAsync(QueueDocumentCollectionUri, data).GetAwaiter().GetResult(); + storage.Client.UpsertDocumentAsync(storage.Collections.QueueDocumentCollectionUri, data).GetAwaiter().GetResult(); } } } diff --git a/Hangfire.AzureDocumentDB/Queue/JobQueue.cs b/Hangfire.AzureDocumentDB/Queue/JobQueue.cs index 0477312..dededc7 100644 --- a/Hangfire.AzureDocumentDB/Queue/JobQueue.cs +++ b/Hangfire.AzureDocumentDB/Queue/JobQueue.cs @@ -16,14 +16,12 @@ internal class JobQueue : IPersistentJobQueue private readonly TimeSpan checkInterval; private readonly object syncLock = new object(); - private readonly Uri QueueDocumentCollectionUri; private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 1 }; public JobQueue(AzureDocumentDbStorage storage) { this.storage = storage; checkInterval = storage.Options.QueuePollInterval; - QueueDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "queues"); } public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken) @@ -38,8 +36,8 @@ public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken) { string queue = queues.ElementAt(index); - Entities.Queue data = storage.Client.CreateDocumentQuery(QueueDocumentCollectionUri, QueryOptions) - .Where(q => q.Name == queue) + Entities.Queue data = storage.Client.CreateDocumentQuery(storage.Collections.QueueDocumentCollectionUri, QueryOptions) + .Where(q => q.Name == queue && q.DocumentType == Entities.DocumentTypes.Queue) .AsEnumerable() .FirstOrDefault(); @@ -63,7 +61,7 @@ public void Enqueue(string queue, string jobId) Name = queue, JobId = jobId }; - storage.Client.CreateDocumentAsync(QueueDocumentCollectionUri, data).GetAwaiter().GetResult(); + storage.Client.CreateDocumentAsync(storage.Collections.QueueDocumentCollectionUri, data).GetAwaiter().GetResult(); } } } \ No newline at end of file diff --git a/Hangfire.AzureDocumentDB/Queue/JobQueueMonitoringApi.cs b/Hangfire.AzureDocumentDB/Queue/JobQueueMonitoringApi.cs index 73e17da..12392ea 100644 --- a/Hangfire.AzureDocumentDB/Queue/JobQueueMonitoringApi.cs +++ b/Hangfire.AzureDocumentDB/Queue/JobQueueMonitoringApi.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using System.Collections.Generic; using Microsoft.Azure.Documents.Client; @@ -10,34 +9,33 @@ internal class JobQueueMonitoringApi : IPersistentJobQueueMonitoringApi { private readonly AzureDocumentDbStorage storage; private readonly IEnumerable queues; - private readonly Uri QueueDocumentCollectionUri; private readonly FeedOptions QueryOptions = new FeedOptions { MaxItemCount = 100 }; public JobQueueMonitoringApi(AzureDocumentDbStorage storage) { this.storage = storage; queues = storage.Options.Queues; - QueueDocumentCollectionUri = UriFactory.CreateDocumentCollectionUri(storage.Options.DatabaseName, "queues"); } public IEnumerable GetQueues() => queues; public int GetEnqueuedCount(string queue) { - return storage.Client.CreateDocumentQuery(QueueDocumentCollectionUri, QueryOptions) - .Where(q => q.Name == queue) + return storage.Client.CreateDocumentQuery(storage.Collections.QueueDocumentCollectionUri, QueryOptions) + .Where(q => q.Name == queue && q.DocumentType == Entities.DocumentTypes.Queue) .AsEnumerable() + .Select(q => 1) .Count(); } public IEnumerable GetEnqueuedJobIds(string queue, int from, int perPage) { - return storage.Client.CreateDocumentQuery(QueueDocumentCollectionUri, QueryOptions) - .Where(q => q.Name == queue) - .AsEnumerable() - .Skip(from).Take(perPage) - .Select(c => c.JobId) - .ToList(); + return storage.Client.CreateDocumentQuery(storage.Collections.QueueDocumentCollectionUri, QueryOptions) + .Where(q => q.Name == queue && q.DocumentType == Entities.DocumentTypes.Queue) + .AsEnumerable() + .Skip(from).Take(perPage) + .Select(c => c.JobId) + .ToList(); } public IEnumerable GetFetchedJobIds(string queue, int from, int perPage) => GetEnqueuedJobIds(queue, from, perPage); From fada4bceb53b55e5e89f16ca88c2a639ef895a32 Mon Sep 17 00:00:00 2001 From: Imran Momin Date: Thu, 11 May 2017 21:05:49 -0400 Subject: [PATCH 07/12] azure documentdb package update --- .../Hangfire.AzureDocumentDB.csproj | 12 +++++++----- Hangfire.AzureDocumentDB/packages.config | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj b/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj index 5c3982e..4453f92 100644 --- a/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj +++ b/Hangfire.AzureDocumentDB/Hangfire.AzureDocumentDB.csproj @@ -44,8 +44,8 @@ ..\packages\Hangfire.Core.1.6.12\lib\net45\Hangfire.Core.dll True - - ..\packages\Microsoft.Azure.DocumentDB.1.13.2\lib\net45\Microsoft.Azure.Documents.Client.dll + + ..\packages\Microsoft.Azure.DocumentDB.1.14.0\lib\net45\Microsoft.Azure.Documents.Client.dll True @@ -108,7 +108,9 @@ True Resources.resx - + + Designer + SettingsSingleFileGenerator Settings.Designer.cs @@ -130,10 +132,10 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - +