From 6e296c61d16dd1a59bb62836c7766bdd56332556 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Feb 2016 19:06:09 +0000 Subject: [PATCH 1/2] API Key --- src/ConsoleSample/Program.cs | 2 +- src/Hangfire.Raven/Hangfire.Raven.csproj | 1 - src/Hangfire.Raven/Repository.cs | 27 +- src/Hangfire.Raven/SqlServerMonitoringApi.cs | 562 ------------------ .../Storage/RavenStorageExtensions.cs | 20 + 5 files changed, 44 insertions(+), 568 deletions(-) delete mode 100644 src/Hangfire.Raven/SqlServerMonitoringApi.cs diff --git a/src/ConsoleSample/Program.cs b/src/ConsoleSample/Program.cs index 330ef80..1f645a7 100644 --- a/src/ConsoleSample/Program.cs +++ b/src/ConsoleSample/Program.cs @@ -13,7 +13,7 @@ namespace ConsoleSample // you can use Raven Storage and specify the connection string and database name GlobalConfiguration.Configuration .UseColouredConsoleLogProvider() - .UseRavenStorage("http://localhost:9090", "hangfire"); + .UseRavenStorage("http://localhost:8080", "UP-Data", "crap"); // you can use Raven Embedded Storage which runs in memory! //GlobalConfiguration.Configuration diff --git a/src/Hangfire.Raven/Hangfire.Raven.csproj b/src/Hangfire.Raven/Hangfire.Raven.csproj index 031db9a..c1cadc9 100644 --- a/src/Hangfire.Raven/Hangfire.Raven.csproj +++ b/src/Hangfire.Raven/Hangfire.Raven.csproj @@ -114,7 +114,6 @@ - diff --git a/src/Hangfire.Raven/Repository.cs b/src/Hangfire.Raven/Repository.cs index 37ce473..e46fabb 100644 --- a/src/Hangfire.Raven/Repository.cs +++ b/src/Hangfire.Raven/Repository.cs @@ -22,16 +22,20 @@ namespace HangFire.Raven public static string ConnectionString { get; set; } public static string ConnectionUrl { get; set; } public static string DefaultDatabase { get; set; } + public static string APIKey { get; set; } private static IDocumentStore _documentStore; private IDocumentSession _session; private IAsyncDocumentSession _asyncSession; private string _database; + private string _APIKey; public static bool Embedded { get; set; } public string Database => _database ?? DefaultDatabase; + public string APIKeyAccess => _APIKey ?? string.Empty; + public void Destroy() { if (!DocumentStore.DatabaseExists(Database)) { @@ -67,14 +71,17 @@ namespace HangFire.Raven { _documentStore = new DocumentStore { - ConnectionStringName = ConnectionString + ConnectionStringName = ConnectionString, + ApiKey = APIKey + }; } else { _documentStore = new DocumentStore { - Url = ConnectionUrl + Url = ConnectionUrl, + ApiKey = APIKey }; } } @@ -99,15 +106,27 @@ namespace HangFire.Raven public Repository() { _database = DefaultDatabase; + _APIKey = APIKey; } - public Repository(string database) + public Repository(string database, string APIKey) { if (database.IsEmpty()) { _database = DefaultDatabase; } else { - _database = database; + _database = database; } + + if (APIKey.IsEmpty()) + { + _APIKey = APIKeyAccess; + } + else + { + _APIKey = APIKey; + } + + } #endregion diff --git a/src/Hangfire.Raven/SqlServerMonitoringApi.cs b/src/Hangfire.Raven/SqlServerMonitoringApi.cs deleted file mode 100644 index c7df715..0000000 --- a/src/Hangfire.Raven/SqlServerMonitoringApi.cs +++ /dev/null @@ -1,562 +0,0 @@ -//// This file is part of Hangfire. -//// Copyright © 2013-2014 Sergey Odinokov. -//// -//// Hangfire is free software: you can redistribute it and/or modify -//// it under the terms of the GNU Lesser General Public License as -//// published by the Free Software Foundation, either version 3 -//// of the License, or any later version. -//// -//// Hangfire is distributed in the hope that it will be useful, -//// but WITHOUT ANY WARRANTY; without even the implied warranty of -//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//// GNU Lesser General Public License for more details. -//// -//// You should have received a copy of the GNU Lesser General Public -//// License along with Hangfire. If not, see . - -//using System; -//using System.Collections.Generic; -//using System.Data.SqlClient; -//using System.Linq; -//using System.Transactions; -//using Dapper; -//using Hangfire.Annotations; -//using Hangfire.Common; -//using Hangfire.SqlServer.Entities; -//using Hangfire.States; -//using Hangfire.Storage; -//using Hangfire.Storage.Monitoring; - -//namespace Hangfire.SqlServer -//{ -// internal class SqlServerMonitoringApi : IMonitoringApi -// { -// private readonly RavenStorage _storage; -// private readonly int? _jobListLimit; - -// public SqlServerMonitoringApi([NotNull] RavenStorage storage, int? jobListLimit) -// { -// if (storage == null) throw new ArgumentNullException("storage"); - -// _storage = storage; -// _jobListLimit = jobListLimit; -// } - -// public long ScheduledCount() -// { -// return UseConnection(connection => -// GetNumberOfJobsByStateName(connection, ScheduledState.StateName)); -// } - -// public long EnqueuedCount(string queue) -// { -// var queueApi = GetQueueApi(queue); -// var counters = queueApi.GetEnqueuedAndFetchedCount(queue); - -// return counters.EnqueuedCount ?? 0; -// } - -// public long FetchedCount(string queue) -// { -// var queueApi = GetQueueApi(queue); -// var counters = queueApi.GetEnqueuedAndFetchedCount(queue); - -// return counters.FetchedCount ?? 0; -// } - -// public long FailedCount() -// { -// return UseConnection(connection => -// GetNumberOfJobsByStateName(connection, FailedState.StateName)); -// } - -// public long ProcessingCount() -// { -// return UseConnection(connection => -// GetNumberOfJobsByStateName(connection, ProcessingState.StateName)); -// } - -// public JobList ProcessingJobs(int @from, int count) -// { -// return UseConnection(connection => GetJobs( -// connection, -// from, count, -// ProcessingState.StateName, -// (sqlJob, job, stateData) => new ProcessingJobDto -// { -// Job = job, -// ServerId = stateData.ContainsKey("ServerId") ? stateData["ServerId"] : stateData["ServerName"], -// StartedAt = JobHelper.DeserializeDateTime(stateData["StartedAt"]), -// })); -// } - -// public JobList ScheduledJobs(int @from, int count) -// { -// return UseConnection(connection => GetJobs( -// connection, -// from, count, -// ScheduledState.StateName, -// (sqlJob, job, stateData) => new ScheduledJobDto -// { -// Job = job, -// EnqueueAt = JobHelper.DeserializeDateTime(stateData["EnqueueAt"]), -// ScheduledAt = JobHelper.DeserializeDateTime(stateData["ScheduledAt"]) -// })); -// } - -// public IDictionary SucceededByDatesCount() -// { -// return UseConnection(connection => -// GetTimelineStats(connection, "succeeded")); -// } - -// public IDictionary FailedByDatesCount() -// { -// return UseConnection(connection => -// GetTimelineStats(connection, "failed")); -// } - -// public IList Servers() -// { -// return UseConnection>(connection => -// { -// var servers = connection.Query( -// string.Format(@"select * from [{0}].Server", _storage.GetSchemaName())) -// .ToList(); - -// var result = new List(); - -// foreach (var server in servers) -// { -// var data = JobHelper.FromJson(server.Data); -// result.Add(new ServerDto -// { -// Name = server.Id, -// Heartbeat = server.LastHeartbeat, -// Queues = data.Queues, -// StartedAt = data.StartedAt.HasValue ? data.StartedAt.Value : DateTime.MinValue, -// WorkersCount = data.WorkerCount -// }); -// } - -// return result; -// }); -// } - -// public JobList FailedJobs(int @from, int count) -// { -// return UseConnection(connection => GetJobs( -// connection, -// from, -// count, -// FailedState.StateName, -// (sqlJob, job, stateData) => new FailedJobDto -// { -// Job = job, -// Reason = sqlJob.StateReason, -// ExceptionDetails = stateData["ExceptionDetails"], -// ExceptionMessage = stateData["ExceptionMessage"], -// ExceptionType = stateData["ExceptionType"], -// FailedAt = JobHelper.DeserializeNullableDateTime(stateData["FailedAt"]) -// })); -// } - -// public JobList SucceededJobs(int @from, int count) -// { -// return UseConnection(connection => GetJobs( -// connection, -// from, -// count, -// SucceededState.StateName, -// (sqlJob, job, stateData) => new SucceededJobDto -// { -// Job = job, -// Result = stateData.ContainsKey("Result") ? stateData["Result"] : null, -// TotalDuration = stateData.ContainsKey("PerformanceDuration") && stateData.ContainsKey("Latency") -// ? (long?)long.Parse(stateData["PerformanceDuration"]) + (long?)long.Parse(stateData["Latency"]) -// : null, -// SucceededAt = JobHelper.DeserializeNullableDateTime(stateData["SucceededAt"]) -// })); -// } - -// public JobList DeletedJobs(int @from, int count) -// { -// return UseConnection(connection => GetJobs( -// connection, -// from, -// count, -// DeletedState.StateName, -// (sqlJob, job, stateData) => new DeletedJobDto -// { -// Job = job, -// DeletedAt = JobHelper.DeserializeNullableDateTime(stateData["DeletedAt"]) -// })); -// } - -// public IList Queues() -// { -// var tuples = _storage.QueueProviders -// .Select(x => x.GetJobQueueMonitoringApi()) -// .SelectMany(x => x.GetQueues(), (monitoring, queue) => new { Monitoring = monitoring, Queue = queue }) -// .OrderBy(x => x.Queue) -// .ToArray(); - -// var result = new List(tuples.Length); - -// foreach (var tuple in tuples) -// { -// var enqueuedJobIds = tuple.Monitoring.GetEnqueuedJobIds(tuple.Queue, 0, 5); -// var counters = tuple.Monitoring.GetEnqueuedAndFetchedCount(tuple.Queue); - -// var firstJobs = UseConnection(connection => EnqueuedJobs(connection, enqueuedJobIds)); - -// result.Add(new QueueWithTopEnqueuedJobsDto -// { -// Name = tuple.Queue, -// Length = counters.EnqueuedCount ?? 0, -// Fetched = counters.FetchedCount, -// FirstJobs = firstJobs -// }); -// } - -// return result; -// } - -// public JobList EnqueuedJobs(string queue, int @from, int perPage) -// { -// var queueApi = GetQueueApi(queue); -// var enqueuedJobIds = queueApi.GetEnqueuedJobIds(queue, from, perPage); - -// return UseConnection(connection => EnqueuedJobs(connection, enqueuedJobIds)); -// } - -// public JobList FetchedJobs(string queue, int @from, int perPage) -// { -// var queueApi = GetQueueApi(queue); -// var fetchedJobIds = queueApi.GetFetchedJobIds(queue, from, perPage); - -// return UseConnection(connection => FetchedJobs(connection, fetchedJobIds)); -// } - -// public IDictionary HourlySucceededJobs() -// { -// return UseConnection(connection => -// GetHourlyTimelineStats(connection, "succeeded")); -// } - -// public IDictionary HourlyFailedJobs() -// { -// return UseConnection(connection => -// GetHourlyTimelineStats(connection, "failed")); -// } - -// public JobDetailsDto JobDetails(string jobId) -// { -// return UseConnection(connection => -// { - -// string sql = string.Format(@" -//select * from [{0}].Job where Id = @id -//select * from [{0}].JobParameter where JobId = @id -//select * from [{0}].State where JobId = @id order by Id desc", _storage.GetSchemaName()); - -// using (var multi = connection.QueryMultiple(sql, new { id = jobId })) -// { -// var job = multi.Read().SingleOrDefault(); -// if (job == null) return null; - -// var parameters = multi.Read().ToDictionary(x => x.Name, x => x.Value); -// var history = -// multi.Read() -// .ToList() -// .Select(x => new StateHistoryDto -// { -// StateName = x.Name, -// CreatedAt = x.CreatedAt, -// Reason = x.Reason, -// Data = new Dictionary( -// JobHelper.FromJson>(x.Data), -// StringComparer.OrdinalIgnoreCase), -// }) -// .ToList(); - -// return new JobDetailsDto -// { -// CreatedAt = job.CreatedAt, -// ExpireAt = job.ExpireAt, -// Job = DeserializeJob(job.InvocationData, job.Arguments), -// History = history, -// Properties = parameters -// }; -// } -// }); -// } - -// public long SucceededListCount() -// { -// return UseConnection(connection => -// GetNumberOfJobsByStateName(connection, SucceededState.StateName)); -// } - -// public long DeletedListCount() -// { -// return UseConnection(connection => -// GetNumberOfJobsByStateName(connection, DeletedState.StateName)); -// } - -// public StatisticsDto GetStatistics() -// { -// string sql = string.Format(@" -//select count(Id) from [{0}].Job where StateName = N'Enqueued'; -//select count(Id) from [{0}].Job where StateName = N'Failed'; -//select count(Id) from [{0}].Job where StateName = N'Processing'; -//select count(Id) from [{0}].Job where StateName = N'Scheduled'; -//select count(Id) from [{0}].Server; -//select sum(s.[Value]) from ( -// select sum([Value]) as [Value] from [{0}].Counter where [Key] = N'stats:succeeded' -// union all -// select [Value] from [{0}].AggregatedCounter where [Key] = N'stats:succeeded' -//) as s; -//select sum(s.[Value]) from ( -// select sum([Value]) as [Value] from [{0}].Counter where [Key] = N'stats:deleted' -// union all -// select [Value] from [{0}].AggregatedCounter where [Key] = N'stats:deleted' -//) as s; -//select count(*) from [{0}].[Set] where [Key] = N'recurring-jobs'; -//", _storage.GetSchemaName()); - -// var statistics = UseConnection(connection => -// { -// var stats = new StatisticsDto(); -// using (var multi = connection.QueryMultiple(sql)) -// { -// stats.Enqueued = multi.Read().Single(); -// stats.Failed = multi.Read().Single(); -// stats.Processing = multi.Read().Single(); -// stats.Scheduled = multi.Read().Single(); - -// stats.Servers = multi.Read().Single(); - -// stats.Succeeded = multi.Read().SingleOrDefault() ?? 0; -// stats.Deleted = multi.Read().SingleOrDefault() ?? 0; - -// stats.Recurring = multi.Read().Single(); -// } -// return stats; -// }); - -// statistics.Queues = _storage.QueueProviders -// .SelectMany(x => x.GetJobQueueMonitoringApi().GetQueues()) -// .Count(); - -// return statistics; -// } - -// private Dictionary GetHourlyTimelineStats( -// SqlConnection connection, -// string type) -// { -// var endDate = DateTime.UtcNow; -// var dates = new List(); -// for (var i = 0; i < 24; i++) -// { -// dates.Add(endDate); -// endDate = endDate.AddHours(-1); -// } - -// var keyMaps = dates.ToDictionary(x => String.Format("stats:{0}:{1}", type, x.ToString("yyyy-MM-dd-HH")), x => x); - -// return GetTimelineStats(connection, keyMaps); -// } - -// private Dictionary GetTimelineStats( -// SqlConnection connection, -// string type) -// { -// var endDate = DateTime.UtcNow.Date; -// var dates = new List(); -// for (var i = 0; i < 7; i++) -// { -// dates.Add(endDate); -// endDate = endDate.AddDays(-1); -// } - -// var keyMaps = dates.ToDictionary(x => String.Format("stats:{0}:{1}", type, x.ToString("yyyy-MM-dd")), x => x); - -// return GetTimelineStats(connection, keyMaps); -// } - -// private Dictionary GetTimelineStats(SqlConnection connection, -// IDictionary keyMaps) -// { -// string sqlQuery = string.Format(@" -//select [Key], [Value] as [Count] from [{0}].AggregatedCounter -//where [Key] in @keys", _storage.GetSchemaName()); - -// var valuesMap = connection.Query( -// sqlQuery, -// new { keys = keyMaps.Keys }) -// .ToDictionary(x => (string)x.Key, x => (long)x.Count); - -// foreach (var key in keyMaps.Keys) -// { -// if (!valuesMap.ContainsKey(key)) valuesMap.Add(key, 0); -// } - -// var result = new Dictionary(); -// for (var i = 0; i < keyMaps.Count; i++) -// { -// var value = valuesMap[keyMaps.ElementAt(i).Key]; -// result.Add(keyMaps.ElementAt(i).Value, value); -// } - -// return result; -// } - -// private IPersistentJobQueueMonitoringApi GetQueueApi(string queueName) -// { -// var provider = _storage.QueueProviders.GetProvider(queueName); -// var monitoringApi = provider.GetJobQueueMonitoringApi(); - -// return monitoringApi; -// } - -// private T UseConnection(Func action) -// { -// return _storage.UseTransaction(action, IsolationLevel.ReadUncommitted); -// } - -// private JobList EnqueuedJobs( -// SqlConnection connection, -// IEnumerable jobIds) -// { -// string enqueuedJobsSql = string.Format(@" -//select j.*, s.Reason as StateReason, s.Data as StateData -//from [{0}].Job j -//left join [{0}].State s on s.Id = j.StateId -//where j.Id in @jobIds", _storage.GetSchemaName()); - -// var jobs = connection.Query( -// enqueuedJobsSql, -// new { jobIds = jobIds }) -// .ToList(); - -// return DeserializeJobs( -// jobs, -// (sqlJob, job, stateData) => new EnqueuedJobDto -// { -// Job = job, -// State = sqlJob.StateName, -// EnqueuedAt = sqlJob.StateName == EnqueuedState.StateName -// ? JobHelper.DeserializeNullableDateTime(stateData["EnqueuedAt"]) -// : null -// }); -// } - -// private long GetNumberOfJobsByStateName(SqlConnection connection, string stateName) -// { -// var sqlQuery = _jobListLimit.HasValue -// ? string.Format(@"select count(j.Id) from (select top (@limit) Id from [{0}].Job where StateName = @state) as j", _storage.GetSchemaName()) -// : string.Format(@"select count(Id) from [{0}].Job where StateName = @state", _storage.GetSchemaName()); - -// var count = connection.Query( -// sqlQuery, -// new { state = stateName, limit = _jobListLimit }) -// .Single(); - -// return count; -// } - -// private static Job DeserializeJob(string invocationData, string arguments) -// { -// var data = JobHelper.FromJson(invocationData); -// data.Arguments = arguments; - -// try -// { -// return data.Deserialize(); -// } -// catch (JobLoadException) -// { -// return null; -// } -// } - -// private JobList GetJobs( -// SqlConnection connection, -// int from, -// int count, -// string stateName, -// Func, TDto> selector) -// { -// string jobsSql = string.Format(@" -//select * from ( -// select j.*, s.Reason as StateReason, s.Data as StateData, row_number() over (order by j.Id desc) as row_num -// from [{0}].Job j with (forceseek) -// left join [{0}].State s on j.StateId = s.Id -// where j.StateName = @stateName -//) as j where j.row_num between @start and @end -//", _storage.GetSchemaName()); - -// var jobs = connection.Query( -// jobsSql, -// new { stateName = stateName, start = @from + 1, end = @from + count }) -// .ToList(); - -// return DeserializeJobs(jobs, selector); -// } - -// private static JobList DeserializeJobs( -// ICollection jobs, -// Func, TDto> selector) -// { -// var result = new List>(jobs.Count); - -// foreach (var job in jobs) -// { -// var deserializedData = JobHelper.FromJson>(job.StateData); -// var stateData = deserializedData != null -// ? new Dictionary(deserializedData, StringComparer.OrdinalIgnoreCase) -// : null; - -// var dto = selector(job, DeserializeJob(job.InvocationData, job.Arguments), stateData); - -// result.Add(new KeyValuePair( -// job.Id.ToString(), dto)); -// } - -// return new JobList(result); -// } - -// private JobList FetchedJobs( -// SqlConnection connection, -// IEnumerable jobIds) -// { -// string fetchedJobsSql = string.Format(@" -//select j.*, s.Reason as StateReason, s.Data as StateData -//from [{0}].Job j -//left join [{0}].State s on s.Id = j.StateId -//where j.Id in @jobIds", _storage.GetSchemaName()); - -// var jobs = connection.Query( -// fetchedJobsSql, -// new { jobIds = jobIds }) -// .ToList(); - -// var result = new List>(jobs.Count); - -// foreach (var job in jobs) -// { -// result.Add(new KeyValuePair( -// job.Id.ToString(), -// new FetchedJobDto -// { -// Job = DeserializeJob(job.InvocationData, job.Arguments), -// State = job.StateName, -// })); -// } - -// return new JobList(result); -// } -// } -//} diff --git a/src/Hangfire.Raven/Storage/RavenStorageExtensions.cs b/src/Hangfire.Raven/Storage/RavenStorageExtensions.cs index 28f2f70..b25a34b 100644 --- a/src/Hangfire.Raven/Storage/RavenStorageExtensions.cs +++ b/src/Hangfire.Raven/Storage/RavenStorageExtensions.cs @@ -54,6 +54,26 @@ namespace HangFire.Raven.Storage return configuration.UseStorage(storage); } + public static IGlobalConfiguration UseRavenStorage(this IGlobalConfiguration configuration, string connectionUrl, string database, string APIKey) + { + configuration.ThrowIfNull("configuration"); + connectionUrl.ThrowIfNull("connectionUrl"); + database.ThrowIfNull("database"); + + if (!connectionUrl.StartsWith("http")) + { + throw new ArgumentException("Connection Url must begin with http or https!"); + } + + Repository.ConnectionUrl = connectionUrl; + Repository.DefaultDatabase = database; + Repository.APIKey = APIKey; + + var storage = new RavenStorage(); + + return configuration.UseStorage(storage); + } + public static IGlobalConfiguration UseRavenStorage(this IGlobalConfiguration configuration, string connectionUrl, string database, RavenStorageOptions options) { configuration.ThrowIfNull("configuration"); From 21dc970051303120782ee340116b840c57cc90c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Feb 2016 13:35:27 +0000 Subject: [PATCH 2/2] react to apikey overload --- src/ConsoleSample/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConsoleSample/Program.cs b/src/ConsoleSample/Program.cs index 1f645a7..9fb11d5 100644 --- a/src/ConsoleSample/Program.cs +++ b/src/ConsoleSample/Program.cs @@ -13,7 +13,7 @@ namespace ConsoleSample // you can use Raven Storage and specify the connection string and database name GlobalConfiguration.Configuration .UseColouredConsoleLogProvider() - .UseRavenStorage("http://localhost:8080", "UP-Data", "crap"); + .UseRavenStorage("http://localhost:8080", "hangfire", "apikeytest"); // you can use Raven Embedded Storage which runs in memory! //GlobalConfiguration.Configuration