diff --git a/samples/Sample.Kafka.SqlServer/Startup.cs b/samples/Sample.Kafka.SqlServer/Startup.cs index c7b0e4e..de9962c 100644 --- a/samples/Sample.Kafka.SqlServer/Startup.cs +++ b/samples/Sample.Kafka.SqlServer/Startup.cs @@ -20,7 +20,7 @@ namespace Sample.Kafka.SqlServer x.UseDiscovery(d => { d.DiscoveryServerHostName = "localhost"; - d.DiscoveryServerProt = 8500; + d.DiscoveryServerPort = 8500; d.CurrentNodeHostName = "localhost"; d.CurrentNodePort = 5820; d.NodeName = "CAP 2号节点"; @@ -40,8 +40,6 @@ namespace Sample.Kafka.SqlServer app.UseMvc(); app.UseCap(); - - app.UseCapDashboard(); } } } \ No newline at end of file diff --git a/samples/Sample.RabbitMQ.MySql/Startup.cs b/samples/Sample.RabbitMQ.MySql/Startup.cs index 347558f..3ffdd7d 100644 --- a/samples/Sample.RabbitMQ.MySql/Startup.cs +++ b/samples/Sample.RabbitMQ.MySql/Startup.cs @@ -27,7 +27,7 @@ namespace Sample.RabbitMQ.MySql x.UseDiscovery(d => { d.DiscoveryServerHostName = "localhost"; - d.DiscoveryServerProt = 8500; + d.DiscoveryServerPort = 8500; d.CurrentNodeHostName = "localhost"; d.CurrentNodePort = 5800; d.NodeName = "CAP 1号节点"; @@ -45,7 +45,6 @@ namespace Sample.RabbitMQ.MySql app.UseMvc(); app.UseCap(); - app.UseCapDashboard(); } } } diff --git a/samples/Sample.RabbitMQ.PostgreSql/Startup.cs b/samples/Sample.RabbitMQ.PostgreSql/Startup.cs index e0a1b4f..4c0d950 100644 --- a/samples/Sample.RabbitMQ.PostgreSql/Startup.cs +++ b/samples/Sample.RabbitMQ.PostgreSql/Startup.cs @@ -26,7 +26,7 @@ namespace Sample.RabbitMQ.PostgreSql x.UseDiscovery(d => { d.DiscoveryServerHostName = "localhost"; - d.DiscoveryServerProt = 8500; + d.DiscoveryServerPort = 8500; d.CurrentNodeHostName = "localhost"; d.CurrentNodePort = 5800; d.NodeName = "CAP一号节点"; diff --git a/samples/Sample.RabbitMQ.SqlServer/Startup.cs b/samples/Sample.RabbitMQ.SqlServer/Startup.cs index 6cd19cd..bea6082 100644 --- a/samples/Sample.RabbitMQ.SqlServer/Startup.cs +++ b/samples/Sample.RabbitMQ.SqlServer/Startup.cs @@ -29,7 +29,7 @@ namespace Sample.RabbitMQ.SqlServer x.UseDiscovery(d => { d.DiscoveryServerHostName = "localhost"; - d.DiscoveryServerProt = 8500; + d.DiscoveryServerPort = 8500; d.CurrentNodeHostName = "localhost"; d.CurrentNodePort = 5800; d.NodeName = "CAP一号节点"; diff --git a/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs b/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs index 18d2b13..411e4b4 100644 --- a/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs +++ b/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs @@ -10,14 +10,6 @@ namespace DotNetCore.CAP /// public class KafkaOptions { - private IEnumerable> _kafkaConfig; - - - public KafkaOptions() - { - MainConfig = new Dictionary(); - } - /// /// librdkafka configuration parameters (refer to https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md). /// @@ -26,22 +18,28 @@ namespace DotNetCore.CAP /// public readonly IDictionary MainConfig; + private IEnumerable> _kafkaConfig; + + + public KafkaOptions() + { + MainConfig = new Dictionary(); + } + /// - /// The `bootstrap.servers` item config of . + /// The `bootstrap.servers` item config of . /// /// Initial list of brokers as a CSV list of broker host or host:port. /// /// public string Servers { get; set; } - internal IEnumerable> AskafkaConfig() + internal IEnumerable> AsKafkaConfig() { if (_kafkaConfig == null) { if (string.IsNullOrWhiteSpace(Servers)) - { throw new ArgumentNullException(nameof(Servers)); - } MainConfig["bootstrap.servers"] = Servers; MainConfig["queue.buffering.max.ms"] = "10"; diff --git a/src/DotNetCore.CAP.Kafka/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.Kafka/CAP.Options.Extensions.cs index 5bf11b1..be980d6 100644 --- a/src/DotNetCore.CAP.Kafka/CAP.Options.Extensions.cs +++ b/src/DotNetCore.CAP.Kafka/CAP.Options.Extensions.cs @@ -9,18 +9,17 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Configuration to use kafka in CAP. /// + /// CAP configuration options /// Kafka bootstrap server urls. public static CapOptions UseKafka(this CapOptions options, string bootstrapServers) { - return options.UseKafka(opt => - { - opt.Servers = bootstrapServers; - }); + return options.UseKafka(opt => { opt.Servers = bootstrapServers; }); } /// /// Configuration to use kafka in CAP. /// + /// CAP configuration options /// Provides programmatic configuration for the kafka . /// public static CapOptions UseKafka(this CapOptions options, Action configure) diff --git a/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs b/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs index e06c77f..55fcd50 100644 --- a/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs +++ b/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs @@ -13,12 +13,6 @@ namespace DotNetCore.CAP.Kafka private readonly KafkaOptions _kafkaOptions; private Consumer _consumerClient; - public event EventHandler OnMessageReceieved; - - public event EventHandler OnError; - - public IDeserializer StringDeserializer { get; set; } - public KafkaConsumerClient(string groupId, KafkaOptions options) { _groupId = groupId; @@ -26,15 +20,19 @@ namespace DotNetCore.CAP.Kafka StringDeserializer = new StringDeserializer(Encoding.UTF8); } + public IDeserializer StringDeserializer { get; set; } + + public event EventHandler OnMessageReceived; + + public event EventHandler OnError; + public void Subscribe(IEnumerable topics) { if (topics == null) throw new ArgumentNullException(nameof(topics)); if (_consumerClient == null) - { InitKafkaClient(); - } //_consumerClient.Assign(topics.Select(x=> new TopicPartition(x, 0))); _consumerClient.Subscribe(topics); @@ -65,7 +63,7 @@ namespace DotNetCore.CAP.Kafka { _kafkaOptions.MainConfig["group.id"] = _groupId; - var config = _kafkaOptions.AskafkaConfig(); + var config = _kafkaOptions.AsKafkaConfig(); _consumerClient = new Consumer(config, null, StringDeserializer); _consumerClient.OnMessage += ConsumerClient_OnMessage; @@ -81,7 +79,7 @@ namespace DotNetCore.CAP.Kafka Content = e.Value }; - OnMessageReceieved?.Invoke(sender, message); + OnMessageReceived?.Invoke(sender, message); } private void ConsumerClient_OnError(object sender, Error e) diff --git a/src/DotNetCore.CAP.Kafka/PublishQueueExecutor.cs b/src/DotNetCore.CAP.Kafka/PublishQueueExecutor.cs index 8b455d7..82740a4 100644 --- a/src/DotNetCore.CAP.Kafka/PublishQueueExecutor.cs +++ b/src/DotNetCore.CAP.Kafka/PublishQueueExecutor.cs @@ -9,8 +9,8 @@ namespace DotNetCore.CAP.Kafka { internal class PublishQueueExecutor : BasePublishQueueExecutor { - private readonly ILogger _logger; private readonly KafkaOptions _kafkaOptions; + private readonly ILogger _logger; public PublishQueueExecutor( CapOptions options, @@ -27,7 +27,7 @@ namespace DotNetCore.CAP.Kafka { try { - var config = _kafkaOptions.AskafkaConfig(); + var config = _kafkaOptions.AsKafkaConfig(); var contentBytes = Encoding.UTF8.GetBytes(content); using (var producer = new Producer(config)) { @@ -39,19 +39,17 @@ namespace DotNetCore.CAP.Kafka return Task.FromResult(OperateResult.Success); } - else + return Task.FromResult(OperateResult.Failed(new OperateError { - return Task.FromResult(OperateResult.Failed(new OperateError - { - Code = message.Error.Code.ToString(), - Description = message.Error.Reason - })); - } + Code = message.Error.Code.ToString(), + Description = message.Error.Reason + })); } } catch (Exception ex) { - _logger.LogError($"kafka topic message [{keyName}] has benn raised an exception of sending. the exception is: {ex.Message}"); + _logger.LogError( + $"kafka topic message [{keyName}] has benn raised an exception of sending. the exception is: {ex.Message}"); return Task.FromResult(OperateResult.Failed(ex)); } diff --git a/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs b/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs index d7a8ffa..3cd77a3 100644 --- a/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs +++ b/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs @@ -6,7 +6,7 @@ namespace DotNetCore.CAP public class EFOptions { /// - /// EF dbcontext type. + /// EF db context type. /// internal Type DbContextType { get; set; } } diff --git a/src/DotNetCore.CAP.MySql/CAP.MySqlCapOptionsExtension.cs b/src/DotNetCore.CAP.MySql/CAP.MySqlCapOptionsExtension.cs index 79ae85f..1369e13 100644 --- a/src/DotNetCore.CAP.MySql/CAP.MySqlCapOptionsExtension.cs +++ b/src/DotNetCore.CAP.MySql/CAP.MySqlCapOptionsExtension.cs @@ -29,22 +29,18 @@ namespace DotNetCore.CAP _configure(mysqlOptions); if (mysqlOptions.DbContextType != null) - { services.AddSingleton(x => { using (var scope = x.CreateScope()) { var provider = scope.ServiceProvider; - var dbContext = (DbContext)provider.GetService(mysqlOptions.DbContextType); + var dbContext = (DbContext) provider.GetService(mysqlOptions.DbContextType); mysqlOptions.ConnectionString = dbContext.Database.GetDbConnection().ConnectionString; return mysqlOptions; } }); - } else - { services.AddSingleton(mysqlOptions); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs b/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs index 7ad3801..5bec849 100644 --- a/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs +++ b/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs @@ -1,4 +1,5 @@ // ReSharper disable once CheckNamespace + namespace DotNetCore.CAP { public class MySqlOptions : EFOptions diff --git a/src/DotNetCore.CAP.MySql/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.MySql/CAP.Options.Extensions.cs index f838262..5f66f6c 100644 --- a/src/DotNetCore.CAP.MySql/CAP.Options.Extensions.cs +++ b/src/DotNetCore.CAP.MySql/CAP.Options.Extensions.cs @@ -9,10 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection { public static CapOptions UseMySql(this CapOptions options, string connectionString) { - return options.UseMySql(opt => - { - opt.ConnectionString = connectionString; - }); + return options.UseMySql(opt => { opt.ConnectionString = connectionString; }); } public static CapOptions UseMySql(this CapOptions options, Action configure) @@ -27,10 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection public static CapOptions UseEntityFramework(this CapOptions options) where TContext : DbContext { - return options.UseEntityFramework(opt => - { - opt.DbContextType = typeof(TContext); - }); + return options.UseEntityFramework(opt => { opt.DbContextType = typeof(TContext); }); } public static CapOptions UseEntityFramework(this CapOptions options, Action configure) @@ -38,7 +32,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (configure == null) throw new ArgumentNullException(nameof(configure)); - var efOptions = new EFOptions { DbContextType = typeof(TContext) }; + var efOptions = new EFOptions {DbContextType = typeof(TContext)}; configure(efOptions); options.RegisterExtension(new MySqlCapOptionsExtension(configure)); diff --git a/src/DotNetCore.CAP.MySql/CapPublisher.cs b/src/DotNetCore.CAP.MySql/CapPublisher.cs index 27adc48..dd990c1 100644 --- a/src/DotNetCore.CAP.MySql/CapPublisher.cs +++ b/src/DotNetCore.CAP.MySql/CapPublisher.cs @@ -13,9 +13,9 @@ namespace DotNetCore.CAP.MySql { public class CapPublisher : CapPublisherBase, ICallbackPublisher { + private readonly DbContext _dbContext; private readonly ILogger _logger; private readonly MySqlOptions _options; - private readonly DbContext _dbContext; public CapPublisher(IServiceProvider provider, ILogger logger, @@ -28,7 +28,15 @@ namespace DotNetCore.CAP.MySql if (_options.DbContextType != null) { IsUsingEF = true; - _dbContext = (DbContext)ServiceProvider.GetService(_options.DbContextType); + _dbContext = (DbContext) ServiceProvider.GetService(_options.DbContextType); + } + } + + public async Task PublishAsync(CapPublishedMessage message) + { + using (var conn = new MySqlConnection(_options.ConnectionString)) + { + await conn.ExecuteAsync(PrepareSql(), message); } } @@ -45,36 +53,31 @@ namespace DotNetCore.CAP.MySql dbContextTransaction = _dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted); dbTrans = dbContextTransaction.GetDbTransaction(); } - DbTranasaction = dbTrans; + DbTransaction = dbTrans; } - protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { dbConnection.Execute(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { await dbConnection.ExecuteAsync(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - public async Task PublishAsync(CapPublishedMessage message) - { - using (var conn = new MySqlConnection(_options.ConnectionString)) - { - await conn.ExecuteAsync(PrepareSql(), message); - } - } - #region private methods private string PrepareSql() { - return $"INSERT INTO `{_options.TableNamePrefix}.published` (`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`)VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; + return + $"INSERT INTO `{_options.TableNamePrefix}.published` (`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`)VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; } #endregion private methods diff --git a/src/DotNetCore.CAP.MySql/IAdditionalProcessor.Default.cs b/src/DotNetCore.CAP.MySql/IAdditionalProcessor.Default.cs index b21013b..a59d9e2 100644 --- a/src/DotNetCore.CAP.MySql/IAdditionalProcessor.Default.cs +++ b/src/DotNetCore.CAP.MySql/IAdditionalProcessor.Default.cs @@ -9,11 +9,10 @@ namespace DotNetCore.CAP.MySql { internal class DefaultAdditionalProcessor : IAdditionalProcessor { - private readonly ILogger _logger; - private readonly MySqlOptions _options; - private const int MaxBatch = 1000; private readonly TimeSpan _delay = TimeSpan.FromSeconds(1); + private readonly ILogger _logger; + private readonly MySqlOptions _options; private readonly TimeSpan _waitingInterval = TimeSpan.FromMinutes(5); public DefaultAdditionalProcessor(ILogger logger, @@ -27,7 +26,8 @@ namespace DotNetCore.CAP.MySql { _logger.LogDebug("Collecting expired entities."); - var tables = new[]{ + var tables = new[] + { $"{_options.TableNamePrefix}.published", $"{_options.TableNamePrefix}.received" }; @@ -39,8 +39,9 @@ namespace DotNetCore.CAP.MySql { using (var connection = new MySqlConnection(_options.ConnectionString)) { - removedCount = await connection.ExecuteAsync($@"DELETE FROM `{table}` WHERE ExpiresAt < @now limit @count;", - new { now = DateTime.Now, count = MaxBatch }); + removedCount = await connection.ExecuteAsync( + $@"DELETE FROM `{table}` WHERE ExpiresAt < @now limit @count;", + new {now = DateTime.Now, count = MaxBatch}); } if (removedCount != 0) diff --git a/src/DotNetCore.CAP.MySql/MySqlFetchedMessage.cs b/src/DotNetCore.CAP.MySql/MySqlFetchedMessage.cs index f9a4ce1..8e4934e 100644 --- a/src/DotNetCore.CAP.MySql/MySqlFetchedMessage.cs +++ b/src/DotNetCore.CAP.MySql/MySqlFetchedMessage.cs @@ -8,11 +8,11 @@ namespace DotNetCore.CAP.MySql { public class MySqlFetchedMessage : IFetchedMessage { - private readonly IDbConnection _connection; - private readonly IDbTransaction _transaction; - private readonly Timer _timer; private static readonly TimeSpan KeepAliveInterval = TimeSpan.FromMinutes(1); + private readonly IDbConnection _connection; private readonly object _lockObject = new object(); + private readonly Timer _timer; + private readonly IDbTransaction _transaction; public MySqlFetchedMessage(int messageId, MessageType type, diff --git a/src/DotNetCore.CAP.MySql/MySqlStorage.cs b/src/DotNetCore.CAP.MySql/MySqlStorage.cs index 8b36b5e..4068edf 100644 --- a/src/DotNetCore.CAP.MySql/MySqlStorage.cs +++ b/src/DotNetCore.CAP.MySql/MySqlStorage.cs @@ -11,9 +11,9 @@ namespace DotNetCore.CAP.MySql { public class MySqlStorage : IStorage { - private readonly MySqlOptions _options; - private readonly ILogger _logger; private readonly IDbConnection _existingConnection = null; + private readonly ILogger _logger; + private readonly MySqlOptions _options; public MySqlStorage(ILogger logger, MySqlOptions options) { @@ -46,7 +46,7 @@ namespace DotNetCore.CAP.MySql protected virtual string CreateDbTablesScript(string prefix) { var batchSql = - $@" + $@" CREATE TABLE IF NOT EXISTS `{prefix}.queue` ( `MessageId` int(11) NOT NULL, `MessageType` tinyint(4) NOT NULL @@ -97,9 +97,7 @@ CREATE TABLE IF NOT EXISTS `{prefix}.published` ( var connection = _existingConnection ?? new MySqlConnection(_options.ConnectionString); if (connection.State == ConnectionState.Closed) - { connection.Open(); - } return connection; } @@ -112,9 +110,7 @@ CREATE TABLE IF NOT EXISTS `{prefix}.published` ( internal void ReleaseConnection(IDbConnection connection) { if (connection != null && !IsExistingConnection(connection)) - { connection.Dispose(); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.MySql/MySqlStorageConnection.cs b/src/DotNetCore.CAP.MySql/MySqlStorageConnection.cs index 19ae559..13adb95 100644 --- a/src/DotNetCore.CAP.MySql/MySqlStorageConnection.cs +++ b/src/DotNetCore.CAP.MySql/MySqlStorageConnection.cs @@ -5,23 +5,21 @@ using System.Threading.Tasks; using Dapper; using DotNetCore.CAP.Infrastructure; using DotNetCore.CAP.Models; -using DotNetCore.CAP.Processor.States; using MySql.Data.MySqlClient; namespace DotNetCore.CAP.MySql { public class MySqlStorageConnection : IStorageConnection { - private readonly MySqlOptions _options; private readonly string _prefix; public MySqlStorageConnection(MySqlOptions options) { - _options = options; - _prefix = _options.TableNamePrefix; + Options = options; + _prefix = Options.TableNamePrefix; } - public MySqlOptions Options => _options; + public MySqlOptions Options { get; } public IStorageTransaction CreateTransaction() { @@ -32,7 +30,7 @@ namespace DotNetCore.CAP.MySql { var sql = $@"SELECT * FROM `{_prefix}.published` WHERE `Id`={id};"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryFirstOrDefaultAsync(sql); } @@ -59,7 +57,7 @@ DELETE FROM `{_prefix}.queue` LIMIT 1;"; { var sql = $"SELECT * FROM `{_prefix}.published` WHERE `StatusName` = '{StatusName.Scheduled}' LIMIT 1;"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryFirstOrDefaultAsync(sql); } @@ -69,14 +67,12 @@ DELETE FROM `{_prefix}.queue` LIMIT 1;"; { var sql = $"SELECT * FROM `{_prefix}.published` WHERE `StatusName` = '{StatusName.Failed}';"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryAsync(sql); } } - // CapReceviedMessage - public async Task StoreReceivedMessageAsync(CapReceivedMessage message) { if (message == null) throw new ArgumentNullException(nameof(message)); @@ -85,7 +81,7 @@ DELETE FROM `{_prefix}.queue` LIMIT 1;"; INSERT INTO `{_prefix}.received`(`Name`,`Group`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`) VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { await connection.ExecuteAsync(sql, message); } @@ -94,25 +90,25 @@ VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; public async Task GetReceivedMessageAsync(int id) { var sql = $@"SELECT * FROM `{_prefix}.received` WHERE Id={id};"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryFirstOrDefaultAsync(sql); } } - public async Task GetNextReceviedMessageToBeEnqueuedAsync() + public async Task GetNextReceivedMessageToBeEnqueuedAsync() { var sql = $"SELECT * FROM `{_prefix}.received` WHERE `StatusName` = '{StatusName.Scheduled}' LIMIT 1;"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryFirstOrDefaultAsync(sql); } } - public async Task> GetFailedReceviedMessages() + public async Task> GetFailedReceivedMessages() { var sql = $"SELECT * FROM `{_prefix}.received` WHERE `StatusName` = '{StatusName.Failed}';"; - using (var connection = new MySqlConnection(_options.ConnectionString)) + using (var connection = new MySqlConnection(Options.ConnectionString)) { return await connection.QueryAsync(sql); } @@ -123,10 +119,32 @@ VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; { } + public bool ChangePublishedState(int messageId, string state) + { + var sql = + $"UPDATE `{_prefix}.published` SET `Retries`=`Retries`+1,`StatusName` = '{state}' WHERE `Id`={messageId}"; + + using (var connection = new MySqlConnection(Options.ConnectionString)) + { + return connection.Execute(sql) > 0; + } + } + + public bool ChangeReceivedState(int messageId, string state) + { + var sql = + $"UPDATE `{_prefix}.received` SET `Retries`=`Retries`+1,`StatusName` = '{state}' WHERE `Id`={messageId}"; + + using (var connection = new MySqlConnection(Options.ConnectionString)) + { + return connection.Execute(sql) > 0; + } + } + private async Task FetchNextMessageCoreAsync(string sql, object args = null) { //here don't use `using` to dispose - var connection = new MySqlConnection(_options.ConnectionString); + var connection = new MySqlConnection(Options.ConnectionString); await connection.OpenAsync(); var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); FetchedMessage fetchedMessage; @@ -148,17 +166,8 @@ VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; return null; } - return new MySqlFetchedMessage(fetchedMessage.MessageId, fetchedMessage.MessageType, connection, transaction); - } - - public bool ChangePublishedState(int messageId, string state) - { - throw new NotImplementedException(); - } - - public bool ChangeReceivedState(int messageId, string state) - { - throw new NotImplementedException(); + return new MySqlFetchedMessage(fetchedMessage.MessageId, fetchedMessage.MessageType, connection, + transaction); } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.MySql/MySqlStorageTransaction.cs b/src/DotNetCore.CAP.MySql/MySqlStorageTransaction.cs index 682a04d..a65a4b3 100644 --- a/src/DotNetCore.CAP.MySql/MySqlStorageTransaction.cs +++ b/src/DotNetCore.CAP.MySql/MySqlStorageTransaction.cs @@ -9,10 +9,10 @@ namespace DotNetCore.CAP.MySql { public class MySqlStorageTransaction : IStorageTransaction { - private readonly string _prefix; + private readonly IDbConnection _dbConnection; private readonly IDbTransaction _dbTransaction; - private readonly IDbConnection _dbConnection; + private readonly string _prefix; public MySqlStorageTransaction(MySqlStorageConnection connection) { @@ -28,7 +28,8 @@ namespace DotNetCore.CAP.MySql { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $"UPDATE `{_prefix}.published` SET `Retries` = @Retries,`ExpiresAt` = @ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id;"; + var sql = + $"UPDATE `{_prefix}.published` SET `Retries` = @Retries,`ExpiresAt` = @ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -36,7 +37,8 @@ namespace DotNetCore.CAP.MySql { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $"UPDATE `{_prefix}.received` SET `Retries` = @Retries,`Content`= @Content,`ExpiresAt` = @ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id;"; + var sql = + $"UPDATE `{_prefix}.received` SET `Retries` = @Retries,`Content`= @Content,`ExpiresAt` = @ExpiresAt,`StatusName`=@StatusName WHERE `Id`=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -45,7 +47,8 @@ namespace DotNetCore.CAP.MySql if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $"INSERT INTO `{_prefix}.queue` values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Publish }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Publish}, + _dbTransaction); } public void EnqueueMessage(CapReceivedMessage message) @@ -53,7 +56,8 @@ namespace DotNetCore.CAP.MySql if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $"INSERT INTO `{_prefix}.queue` values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Subscribe }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Subscribe}, + _dbTransaction); } public Task CommitAsync() diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs index 12fc9bf..294ed6a 100644 --- a/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs +++ b/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs @@ -9,7 +9,7 @@ namespace DotNetCore.CAP /// /// Gets or sets the schema to use when creating database objects. - /// Default is . + /// Default is . /// public string Schema { get; set; } = DefaultSchema; diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.Options.Extensions.cs index 1505f02..9fde846 100644 --- a/src/DotNetCore.CAP.PostgreSql/CAP.Options.Extensions.cs +++ b/src/DotNetCore.CAP.PostgreSql/CAP.Options.Extensions.cs @@ -9,10 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection { public static CapOptions UsePostgreSql(this CapOptions options, string connectionString) { - return options.UsePostgreSql(opt => - { - opt.ConnectionString = connectionString; - }); + return options.UsePostgreSql(opt => { opt.ConnectionString = connectionString; }); } public static CapOptions UsePostgreSql(this CapOptions options, Action configure) @@ -27,10 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection public static CapOptions UseEntityFramework(this CapOptions options) where TContext : DbContext { - return options.UseEntityFramework(opt => - { - opt.DbContextType = typeof(TContext); - }); + return options.UseEntityFramework(opt => { opt.DbContextType = typeof(TContext); }); } public static CapOptions UseEntityFramework(this CapOptions options, Action configure) @@ -38,7 +32,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (configure == null) throw new ArgumentNullException(nameof(configure)); - var efOptions = new EFOptions { DbContextType = typeof(TContext) }; + var efOptions = new EFOptions {DbContextType = typeof(TContext)}; configure(efOptions); options.RegisterExtension(new PostgreSqlCapOptionsExtension(configure)); diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlCapOptionsExtension.cs b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlCapOptionsExtension.cs index 401401b..128cad9 100644 --- a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlCapOptionsExtension.cs +++ b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlCapOptionsExtension.cs @@ -29,22 +29,18 @@ namespace DotNetCore.CAP _configure(postgreSqlOptions); if (postgreSqlOptions.DbContextType != null) - { services.AddSingleton(x => { using (var scope = x.CreateScope()) { var provider = scope.ServiceProvider; - var dbContext = (DbContext)provider.GetService(postgreSqlOptions.DbContextType); + var dbContext = (DbContext) provider.GetService(postgreSqlOptions.DbContextType); postgreSqlOptions.ConnectionString = dbContext.Database.GetDbConnection().ConnectionString; return postgreSqlOptions; } }); - } else - { services.AddSingleton(postgreSqlOptions); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs index 9a95464..7368b94 100644 --- a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs +++ b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs @@ -1,4 +1,5 @@ // ReSharper disable once CheckNamespace + namespace DotNetCore.CAP { public class PostgreSqlOptions : EFOptions diff --git a/src/DotNetCore.CAP.PostgreSql/CapPublisher.cs b/src/DotNetCore.CAP.PostgreSql/CapPublisher.cs index 835e68a..bbe3672 100644 --- a/src/DotNetCore.CAP.PostgreSql/CapPublisher.cs +++ b/src/DotNetCore.CAP.PostgreSql/CapPublisher.cs @@ -13,9 +13,9 @@ namespace DotNetCore.CAP.PostgreSql { public class CapPublisher : CapPublisherBase, ICallbackPublisher { + private readonly DbContext _dbContext; private readonly ILogger _logger; private readonly PostgreSqlOptions _options; - private readonly DbContext _dbContext; public CapPublisher(IServiceProvider provider, ILogger logger, @@ -28,7 +28,15 @@ namespace DotNetCore.CAP.PostgreSql if (_options.DbContextType != null) { IsUsingEF = true; - _dbContext = (DbContext)ServiceProvider.GetService(_options.DbContextType); + _dbContext = (DbContext) ServiceProvider.GetService(_options.DbContextType); + } + } + + public async Task PublishAsync(CapPublishedMessage message) + { + using (var conn = new NpgsqlConnection(_options.ConnectionString)) + { + await conn.ExecuteAsync(PrepareSql(), message); } } @@ -45,36 +53,31 @@ namespace DotNetCore.CAP.PostgreSql dbContextTransaction = _dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted); dbTrans = dbContextTransaction.GetDbTransaction(); } - DbTranasaction = dbTrans; + DbTransaction = dbTrans; } - protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { dbConnection.Execute(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { await dbConnection.ExecuteAsync(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - public async Task PublishAsync(CapPublishedMessage message) - { - using (var conn = new NpgsqlConnection(_options.ConnectionString)) - { - await conn.ExecuteAsync(PrepareSql(), message); - } - } - #region private methods private string PrepareSql() { - return $"INSERT INTO \"{_options.Schema}\".\"published\" (\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; + return + $"INSERT INTO \"{_options.Schema}\".\"published\" (\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; } #endregion private methods diff --git a/src/DotNetCore.CAP.PostgreSql/IAdditionalProcessor.Default.cs b/src/DotNetCore.CAP.PostgreSql/IAdditionalProcessor.Default.cs index 1c79f60..256e14a 100644 --- a/src/DotNetCore.CAP.PostgreSql/IAdditionalProcessor.Default.cs +++ b/src/DotNetCore.CAP.PostgreSql/IAdditionalProcessor.Default.cs @@ -9,26 +9,22 @@ namespace DotNetCore.CAP.PostgreSql { internal class DefaultAdditionalProcessor : IAdditionalProcessor { - private readonly IServiceProvider _provider; - private readonly ILogger _logger; - private readonly PostgreSqlOptions _options; - private const int MaxBatch = 1000; - private readonly TimeSpan _delay = TimeSpan.FromSeconds(1); - private readonly TimeSpan _waitingInterval = TimeSpan.FromMinutes(5); private static readonly string[] Tables = { - "published","received" + "published", "received" }; - public DefaultAdditionalProcessor( - IServiceProvider provider, - ILogger logger, + private readonly TimeSpan _delay = TimeSpan.FromSeconds(1); + private readonly ILogger _logger; + private readonly PostgreSqlOptions _options; + private readonly TimeSpan _waitingInterval = TimeSpan.FromMinutes(5); + + public DefaultAdditionalProcessor(ILogger logger, PostgreSqlOptions sqlServerOptions) { _logger = logger; - _provider = provider; _options = sqlServerOptions; } @@ -43,8 +39,9 @@ namespace DotNetCore.CAP.PostgreSql { using (var connection = new NpgsqlConnection(_options.ConnectionString)) { - removedCount = await connection.ExecuteAsync($"DELETE FROM \"{_options.Schema}\".\"{table}\" WHERE \"ExpiresAt\" < @now AND \"Id\" IN (SELECT \"Id\" FROM \"{_options.Schema}\".\"{table}\" LIMIT @count);", - new { now = DateTime.Now, count = MaxBatch }); + removedCount = await connection.ExecuteAsync( + $"DELETE FROM \"{_options.Schema}\".\"{table}\" WHERE \"ExpiresAt\" < @now AND \"Id\" IN (SELECT \"Id\" FROM \"{_options.Schema}\".\"{table}\" LIMIT @count);", + new {now = DateTime.Now, count = MaxBatch}); } if (removedCount != 0) diff --git a/src/DotNetCore.CAP.PostgreSql/PostgreSqlFetchedMessage.cs b/src/DotNetCore.CAP.PostgreSql/PostgreSqlFetchedMessage.cs index 7189595..943db78 100644 --- a/src/DotNetCore.CAP.PostgreSql/PostgreSqlFetchedMessage.cs +++ b/src/DotNetCore.CAP.PostgreSql/PostgreSqlFetchedMessage.cs @@ -8,11 +8,11 @@ namespace DotNetCore.CAP.PostgreSql { public class PostgreSqlFetchedMessage : IFetchedMessage { - private readonly IDbConnection _connection; - private readonly IDbTransaction _transaction; - private readonly Timer _timer; private static readonly TimeSpan KeepAliveInterval = TimeSpan.FromMinutes(1); + private readonly IDbConnection _connection; private readonly object _lockObject = new object(); + private readonly Timer _timer; + private readonly IDbTransaction _transaction; public PostgreSqlFetchedMessage(int messageId, MessageType type, diff --git a/src/DotNetCore.CAP.PostgreSql/PostgreSqlMonitoringApi.cs b/src/DotNetCore.CAP.PostgreSql/PostgreSqlMonitoringApi.cs index e5a1718..3306bf3 100644 --- a/src/DotNetCore.CAP.PostgreSql/PostgreSqlMonitoringApi.cs +++ b/src/DotNetCore.CAP.PostgreSql/PostgreSqlMonitoringApi.cs @@ -10,10 +10,10 @@ using DotNetCore.CAP.Models; namespace DotNetCore.CAP.PostgreSql { - public class PostgreSqlMonitoringApi: IMonitoringApi + public class PostgreSqlMonitoringApi : IMonitoringApi { - private readonly PostgreSqlStorage _storage; private readonly PostgreSqlOptions _options; + private readonly PostgreSqlStorage _storage; public PostgreSqlMonitoringApi(IStorage storage, PostgreSqlOptions options) { @@ -23,7 +23,7 @@ namespace DotNetCore.CAP.PostgreSql public StatisticsDto GetStatistics() { - string sql = String.Format(@" + var sql = string.Format(@" select count(Id) from ""{0}"".""published"" where ""StatusName"" = N'Succeeded'; select count(Id) from ""{0}"".""received"" where ""StatusName"" = N'Succeeded'; select count(Id) from ""{0}"".""published"" where ""StatusName"" = N'Failed'; @@ -55,32 +55,22 @@ select count(Id) from ""{0}"".""received"" where ""StatusName"" in (N'Processin { var tableName = queryDto.MessageType == MessageType.Publish ? "published" : "received"; var where = string.Empty; - + if (!string.IsNullOrEmpty(queryDto.StatusName)) - { - if (string.Equals(queryDto.StatusName, StatusName.Processing, StringComparison.CurrentCultureIgnoreCase)) - { + if (string.Equals(queryDto.StatusName, StatusName.Processing, + StringComparison.CurrentCultureIgnoreCase)) where += " and \"StatusName\" in (N'Processing',N'Scheduled',N'Enqueued')"; - } else - { where += " and \"StatusName\" = @StatusName"; - } - } if (!string.IsNullOrEmpty(queryDto.Name)) - { where += " and \"Name\" = @Name"; - } if (!string.IsNullOrEmpty(queryDto.Group)) - { where += " and \"Group\" = @Group"; - } if (!string.IsNullOrEmpty(queryDto.Content)) - { where += " and \"Content\" like '%@Content%'"; - } - var sqlQuery = $"select * from \"{_options.Schema}\".\"{tableName}\" where 1=1 {where} order by \"Added\" desc offset @Offset limit @Limit"; + var sqlQuery = + $"select * from \"{_options.Schema}\".\"{tableName}\" where 1=1 {where} order by \"Added\" desc offset @Offset limit @Limit"; return UseConnection(conn => conn.Query(sqlQuery, new { @@ -89,7 +79,7 @@ select count(Id) from ""{0}"".""received"" where ""StatusName"" in (N'Processin queryDto.Name, queryDto.Content, Offset = queryDto.CurrentPage * queryDto.PageSize, - Limit = queryDto.PageSize, + Limit = queryDto.PageSize }).ToList()); } @@ -143,7 +133,7 @@ select count(Id) from ""{0}"".""received"" where ""StatusName"" in (N'Processin ? $"select count(Id) from \"{_options.Schema}\".\"{tableName}\" where \"StatusName\" in (N'Processing',N'Scheduled',N'Enqueued')" : $"select count(Id) from \"{_options.Schema}\".\"{tableName}\" where \"StatusName\" = @state"; - var count = connection.ExecuteScalar(sqlQuery, new { state = statusName }); + var count = connection.ExecuteScalar(sqlQuery, new {state = statusName}); return count; } @@ -152,7 +142,8 @@ select count(Id) from ""{0}"".""received"" where ""StatusName"" in (N'Processin return _storage.UseConnection(action); } - private Dictionary GetHourlyTimelineStats(IDbConnection connection, string tableName, string statusName) + private Dictionary GetHourlyTimelineStats(IDbConnection connection, string tableName, + string statusName) { var endDate = DateTime.Now; var dates = new List(); @@ -174,7 +165,7 @@ select count(Id) from ""{0}"".""received"" where ""StatusName"" in (N'Processin IDictionary keyMaps) { //SQL Server 2012+ - string sqlQuery = + var sqlQuery = $@" with aggr as ( select to_char(""Added"",'yyyy-MM-dd-HH') as ""Key"", @@ -187,13 +178,11 @@ select ""Key"",""Count"" from aggr where ""Key"" in @keys;"; var valuesMap = connection.Query( sqlQuery, - new { keys = keyMaps.Keys, statusName }) - .ToDictionary(x => (string)x.Key, x => (int)x.Count); + new {keys = keyMaps.Keys, statusName}) + .ToDictionary(x => (string) x.Key, x => (int) 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++) diff --git a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorage.cs b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorage.cs index 5790ab4..a07d358 100644 --- a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorage.cs +++ b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorage.cs @@ -11,9 +11,9 @@ namespace DotNetCore.CAP.PostgreSql { public class PostgreSqlStorage : IStorage { - private readonly PostgreSqlOptions _options; - private readonly ILogger _logger; private readonly IDbConnection _existingConnection = null; + private readonly ILogger _logger; + private readonly PostgreSqlOptions _options; public PostgreSqlStorage(ILogger logger, PostgreSqlOptions options) { @@ -64,9 +64,7 @@ namespace DotNetCore.CAP.PostgreSql var connection = _existingConnection ?? new NpgsqlConnection(_options.ConnectionString); if (connection.State == ConnectionState.Closed) - { connection.Open(); - } return connection; } @@ -79,9 +77,7 @@ namespace DotNetCore.CAP.PostgreSql internal void ReleaseConnection(IDbConnection connection) { if (connection != null && !IsExistingConnection(connection)) - { connection.Dispose(); - } } protected virtual string CreateDbTablesScript(string schema) diff --git a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageConnection.cs b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageConnection.cs index 6ddb1e0..bdf062f 100644 --- a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageConnection.cs +++ b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageConnection.cs @@ -63,8 +63,6 @@ namespace DotNetCore.CAP.PostgreSql } } - // CapReceviedMessage - public async Task StoreReceivedMessageAsync(CapReceivedMessage message) { if (message == null) throw new ArgumentNullException(nameof(message)); @@ -87,7 +85,7 @@ namespace DotNetCore.CAP.PostgreSql } } - public async Task GetNextReceviedMessageToBeEnqueuedAsync() + public async Task GetNextReceivedMessageToBeEnqueuedAsync() { var sql = $"SELECT * FROM \"{Options.Schema}\".\"received\" WHERE \"StatusName\" = '{StatusName.Scheduled}' FOR UPDATE SKIP LOCKED LIMIT 1;"; @@ -97,7 +95,7 @@ namespace DotNetCore.CAP.PostgreSql } } - public async Task> GetFailedReceviedMessages() + public async Task> GetFailedReceivedMessages() { var sql = $"SELECT * FROM \"{Options.Schema}\".\"received\" WHERE \"StatusName\"='{StatusName.Failed}' LIMIT 1000;"; @@ -125,7 +123,7 @@ namespace DotNetCore.CAP.PostgreSql public bool ChangeReceivedState(int messageId, string state) { var sql = - $"UPDATE \"{Options.Schema}\".\"received\" SET \"Retries\"=\"Retries\"+1,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; + $"UPDATE \"{Options.Schema}\".\"received\" SET \"Retries\"=\"Retries\"+1,\"StatusName\" = '{state}' WHERE \"Id\"={messageId}"; using (var connection = new NpgsqlConnection(Options.ConnectionString)) { diff --git a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageTransaction.cs b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageTransaction.cs index a1b6f35..df5e5c5 100644 --- a/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageTransaction.cs +++ b/src/DotNetCore.CAP.PostgreSql/PostgreSqlStorageTransaction.cs @@ -9,10 +9,10 @@ namespace DotNetCore.CAP.PostgreSql { public class PostgreSqlStorageTransaction : IStorageTransaction { - private readonly string _schema; + private readonly IDbConnection _dbConnection; private readonly IDbTransaction _dbTransaction; - private readonly IDbConnection _dbConnection; + private readonly string _schema; public PostgreSqlStorageTransaction(PostgreSqlStorageConnection connection) { @@ -28,7 +28,10 @@ namespace DotNetCore.CAP.PostgreSql { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $@"UPDATE ""{_schema}"".""published"" SET ""Retries""=@Retries,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; + var sql = + $@"UPDATE ""{ + _schema + }"".""published"" SET ""Retries""=@Retries,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -36,7 +39,10 @@ namespace DotNetCore.CAP.PostgreSql { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $@"UPDATE ""{_schema}"".""received"" SET ""Retries""=@Retries,""Content""= @Content,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; + var sql = + $@"UPDATE ""{ + _schema + }"".""received"" SET ""Retries""=@Retries,""Content""= @Content,""ExpiresAt""=@ExpiresAt,""StatusName""=@StatusName WHERE ""Id""=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -45,7 +51,8 @@ namespace DotNetCore.CAP.PostgreSql if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $@"INSERT INTO ""{_schema}"".""queue"" values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Publish }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Publish}, + _dbTransaction); } public void EnqueueMessage(CapReceivedMessage message) @@ -53,7 +60,8 @@ namespace DotNetCore.CAP.PostgreSql if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $@"INSERT INTO ""{_schema}"".""queue"" values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Subscribe }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Subscribe}, + _dbTransaction); } public Task CommitAsync() diff --git a/src/DotNetCore.CAP.RabbitMQ/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.RabbitMQ/CAP.Options.Extensions.cs index 4d59112..bdf0487 100644 --- a/src/DotNetCore.CAP.RabbitMQ/CAP.Options.Extensions.cs +++ b/src/DotNetCore.CAP.RabbitMQ/CAP.Options.Extensions.cs @@ -8,10 +8,7 @@ namespace Microsoft.Extensions.DependencyInjection { public static CapOptions UseRabbitMQ(this CapOptions options, string hostName) { - return options.UseRabbitMQ(opt => - { - opt.HostName = hostName; - }); + return options.UseRabbitMQ(opt => { opt.HostName = hostName; }); } public static CapOptions UseRabbitMQ(this CapOptions options, Action configure) diff --git a/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs b/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs index 6afc0ce..149c1f3 100644 --- a/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs +++ b/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs @@ -1,4 +1,5 @@ // ReSharper disable once CheckNamespace + namespace DotNetCore.CAP { public class RabbitMQOptions diff --git a/src/DotNetCore.CAP.RabbitMQ/ConnectionPool.cs b/src/DotNetCore.CAP.RabbitMQ/ConnectionPool.cs index 5db81e7..c6f1aa4 100644 --- a/src/DotNetCore.CAP.RabbitMQ/ConnectionPool.cs +++ b/src/DotNetCore.CAP.RabbitMQ/ConnectionPool.cs @@ -10,13 +10,13 @@ namespace DotNetCore.CAP.RabbitMQ { private const int DefaultPoolSize = 15; - private readonly ConcurrentQueue _pool = new ConcurrentQueue(); - private readonly Func _activator; - private int _maxSize; + private readonly ConcurrentQueue _pool = new ConcurrentQueue(); private int _count; + private int _maxSize; + public ConnectionPool(RabbitMQOptions options) { _maxSize = DefaultPoolSize; @@ -24,9 +24,28 @@ namespace DotNetCore.CAP.RabbitMQ _activator = CreateActivator(options); } + IConnection IConnectionPool.Rent() + { + return Rent(); + } + + bool IConnectionPool.Return(IConnection connection) + { + return Return(connection); + } + + public void Dispose() + { + _maxSize = 0; + + IConnection context; + while (_pool.TryDequeue(out context)) + context.Dispose(); + } + private static Func CreateActivator(RabbitMQOptions options) { - var factory = new ConnectionFactory() + var factory = new ConnectionFactory { HostName = options.HostName, UserName = options.UserName, @@ -43,7 +62,7 @@ namespace DotNetCore.CAP.RabbitMQ public virtual IConnection Rent() { - if (_pool.TryDequeue(out IConnection connection)) + if (_pool.TryDequeue(out var connection)) { Interlocked.Decrement(ref _count); @@ -72,20 +91,5 @@ namespace DotNetCore.CAP.RabbitMQ return false; } - - IConnection IConnectionPool.Rent() => Rent(); - - bool IConnectionPool.Return(IConnection connection) => Return(connection); - - public void Dispose() - { - _maxSize = 0; - - IConnection context; - while (_pool.TryDequeue(out context)) - { - context.Dispose(); - } - } } -} +} \ No newline at end of file diff --git a/src/DotNetCore.CAP.RabbitMQ/IConnectionPool.cs b/src/DotNetCore.CAP.RabbitMQ/IConnectionPool.cs index c916838..71d8ab8 100644 --- a/src/DotNetCore.CAP.RabbitMQ/IConnectionPool.cs +++ b/src/DotNetCore.CAP.RabbitMQ/IConnectionPool.cs @@ -8,4 +8,4 @@ namespace DotNetCore.CAP.RabbitMQ bool Return(IConnection context); } -} +} \ No newline at end of file diff --git a/src/DotNetCore.CAP.RabbitMQ/PublishQueueExecutor.cs b/src/DotNetCore.CAP.RabbitMQ/PublishQueueExecutor.cs index 0a47501..c3ec8d7 100644 --- a/src/DotNetCore.CAP.RabbitMQ/PublishQueueExecutor.cs +++ b/src/DotNetCore.CAP.RabbitMQ/PublishQueueExecutor.cs @@ -9,8 +9,8 @@ namespace DotNetCore.CAP.RabbitMQ { internal sealed class PublishQueueExecutor : BasePublishQueueExecutor { - private readonly ILogger _logger; private readonly ConnectionPool _connectionPool; + private readonly ILogger _logger; private readonly RabbitMQOptions _rabbitMQOptions; public PublishQueueExecutor( @@ -36,11 +36,11 @@ namespace DotNetCore.CAP.RabbitMQ { var body = Encoding.UTF8.GetBytes(content); - channel.ExchangeDeclare(_rabbitMQOptions.TopicExchangeName, RabbitMQOptions.ExchangeType, durable: true); - channel.BasicPublish(exchange: _rabbitMQOptions.TopicExchangeName, - routingKey: keyName, - basicProperties: null, - body: body); + channel.ExchangeDeclare(_rabbitMQOptions.TopicExchangeName, RabbitMQOptions.ExchangeType, true); + channel.BasicPublish(_rabbitMQOptions.TopicExchangeName, + keyName, + null, + body); _logger.LogDebug($"rabbitmq topic message [{keyName}] has been published."); } @@ -48,10 +48,11 @@ namespace DotNetCore.CAP.RabbitMQ } catch (Exception ex) { - _logger.LogError($"rabbitmq topic message [{keyName}] has benn raised an exception of sending. the exception is: {ex.Message}"); + _logger.LogError( + $"rabbitmq topic message [{keyName}] has benn raised an exception of sending. the exception is: {ex.Message}"); return Task.FromResult(OperateResult.Failed(ex, - new OperateError() + new OperateError { Code = ex.HResult.ToString(), Description = ex.Message diff --git a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs index 1465326..336d187 100644 --- a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs +++ b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs @@ -10,21 +10,17 @@ namespace DotNetCore.CAP.RabbitMQ { internal sealed class RabbitMQConsumerClient : IConsumerClient { + private readonly ConnectionPool _connectionPool; private readonly string _exchageName; private readonly string _queueName; private readonly RabbitMQOptions _rabbitMQOptions; - private readonly ConnectionPool _connectionPool; private IModel _channel; private ulong _deliveryTag; - public event EventHandler OnMessageReceieved; - - public event EventHandler OnError; - public RabbitMQConsumerClient(string queueName, - ConnectionPool connectionPool, - RabbitMQOptions options) + ConnectionPool connectionPool, + RabbitMQOptions options) { _queueName = queueName; _connectionPool = connectionPool; @@ -34,35 +30,16 @@ namespace DotNetCore.CAP.RabbitMQ InitClient(); } - private void InitClient() - { - var connection = _connectionPool.Rent(); - - _channel = connection.CreateModel(); - - _channel.ExchangeDeclare( - exchange: _exchageName, - type: RabbitMQOptions.ExchangeType, - durable: true); - - var arguments = new Dictionary { { "x-message-ttl", _rabbitMQOptions.QueueMessageExpires } }; - _channel.QueueDeclare(_queueName, - durable: true, - exclusive: false, - autoDelete: false, - arguments: arguments); + public event EventHandler OnMessageReceived; - _connectionPool.Return(connection); - } + public event EventHandler OnError; public void Subscribe(IEnumerable topics) { if (topics == null) throw new ArgumentNullException(nameof(topics)); foreach (var topic in topics) - { _channel.QueueBind(_queueName, _exchageName, topic); - } } public void Listening(TimeSpan timeout, CancellationToken cancellationToken) @@ -72,9 +49,7 @@ namespace DotNetCore.CAP.RabbitMQ consumer.Shutdown += OnConsumerShutdown; _channel.BasicConsume(_queueName, false, consumer); while (true) - { Task.Delay(timeout, cancellationToken).GetAwaiter().GetResult(); - } } public void Commit() @@ -87,6 +62,27 @@ namespace DotNetCore.CAP.RabbitMQ _channel.Dispose(); } + private void InitClient() + { + var connection = _connectionPool.Rent(); + + _channel = connection.CreateModel(); + + _channel.ExchangeDeclare( + _exchageName, + RabbitMQOptions.ExchangeType, + true); + + var arguments = new Dictionary {{"x-message-ttl", _rabbitMQOptions.QueueMessageExpires}}; + _channel.QueueDeclare(_queueName, + true, + false, + false, + arguments); + + _connectionPool.Return(connection); + } + private void OnConsumerReceived(object sender, BasicDeliverEventArgs e) { _deliveryTag = e.DeliveryTag; @@ -96,7 +92,7 @@ namespace DotNetCore.CAP.RabbitMQ Name = e.RoutingKey, Content = Encoding.UTF8.GetString(e.Body) }; - OnMessageReceieved?.Invoke(sender, message); + OnMessageReceived?.Invoke(sender, message); } private void OnConsumerShutdown(object sender, ShutdownEventArgs e) diff --git a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClientFactory.cs b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClientFactory.cs index cf2a1d0..110bb95 100644 --- a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClientFactory.cs +++ b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClientFactory.cs @@ -2,8 +2,8 @@ { internal sealed class RabbitMQConsumerClientFactory : IConsumerClientFactory { - private readonly RabbitMQOptions _rabbitMQOptions; private readonly ConnectionPool _connectionPool; + private readonly RabbitMQOptions _rabbitMQOptions; public RabbitMQConsumerClientFactory(RabbitMQOptions rabbitMQOptions, ConnectionPool pool) diff --git a/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs b/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs index b48dcd2..0c62833 100644 --- a/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs +++ b/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs @@ -9,7 +9,7 @@ namespace DotNetCore.CAP /// /// Gets or sets the schema to use when creating database objects. - /// Default is . + /// Default is . /// public string Schema { get; set; } = DefaultSchema; diff --git a/src/DotNetCore.CAP.SqlServer/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.SqlServer/CAP.Options.Extensions.cs index d87e260..c977921 100644 --- a/src/DotNetCore.CAP.SqlServer/CAP.Options.Extensions.cs +++ b/src/DotNetCore.CAP.SqlServer/CAP.Options.Extensions.cs @@ -9,10 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection { public static CapOptions UseSqlServer(this CapOptions options, string connectionString) { - return options.UseSqlServer(opt => - { - opt.ConnectionString = connectionString; - }); + return options.UseSqlServer(opt => { opt.ConnectionString = connectionString; }); } public static CapOptions UseSqlServer(this CapOptions options, Action configure) @@ -27,10 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection public static CapOptions UseEntityFramework(this CapOptions options) where TContext : DbContext { - return options.UseEntityFramework(opt => - { - opt.DbContextType = typeof(TContext); - }); + return options.UseEntityFramework(opt => { opt.DbContextType = typeof(TContext); }); } public static CapOptions UseEntityFramework(this CapOptions options, Action configure) @@ -38,7 +32,7 @@ namespace Microsoft.Extensions.DependencyInjection { if (configure == null) throw new ArgumentNullException(nameof(configure)); - var efOptions = new EFOptions { DbContextType = typeof(TContext) }; + var efOptions = new EFOptions {DbContextType = typeof(TContext)}; configure(efOptions); options.RegisterExtension(new SqlServerCapOptionsExtension(configure)); diff --git a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs index a83433d..333700d 100644 --- a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs +++ b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs @@ -34,22 +34,18 @@ namespace DotNetCore.CAP _configure(sqlServerOptions); if (sqlServerOptions.DbContextType != null) - { services.AddSingleton(x => { using (var scope = x.CreateScope()) { var provider = scope.ServiceProvider; - var dbContext = (DbContext)provider.GetService(sqlServerOptions.DbContextType); + var dbContext = (DbContext) provider.GetService(sqlServerOptions.DbContextType); sqlServerOptions.ConnectionString = dbContext.Database.GetDbConnection().ConnectionString; return sqlServerOptions; } }); - } else - { services.AddSingleton(sqlServerOptions); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs index a0f3fa2..f2d44a4 100644 --- a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs +++ b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs @@ -1,4 +1,5 @@ // ReSharper disable once CheckNamespace + namespace DotNetCore.CAP { public class SqlServerOptions : EFOptions diff --git a/src/DotNetCore.CAP.SqlServer/CapPublisher.cs b/src/DotNetCore.CAP.SqlServer/CapPublisher.cs index 21b2f00..fe8917c 100644 --- a/src/DotNetCore.CAP.SqlServer/CapPublisher.cs +++ b/src/DotNetCore.CAP.SqlServer/CapPublisher.cs @@ -13,9 +13,9 @@ namespace DotNetCore.CAP.SqlServer { public class CapPublisher : CapPublisherBase, ICallbackPublisher { + private readonly DbContext _dbContext; private readonly ILogger _logger; private readonly SqlServerOptions _options; - private readonly DbContext _dbContext; public CapPublisher(IServiceProvider provider, ILogger logger, @@ -28,7 +28,15 @@ namespace DotNetCore.CAP.SqlServer if (_options.DbContextType != null) { IsUsingEF = true; - _dbContext = (DbContext)ServiceProvider.GetService(_options.DbContextType); + _dbContext = (DbContext) ServiceProvider.GetService(_options.DbContextType); + } + } + + public async Task PublishAsync(CapPublishedMessage message) + { + using (var conn = new SqlConnection(_options.ConnectionString)) + { + await conn.ExecuteAsync(PrepareSql(), message); } } @@ -45,36 +53,31 @@ namespace DotNetCore.CAP.SqlServer dbContextTransaction = _dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted); dbTrans = dbContextTransaction.GetDbTransaction(); } - DbTranasaction = dbTrans; + DbTransaction = dbTrans; } - protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { dbConnection.Execute(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message) + protected override async Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message) { await dbConnection.ExecuteAsync(PrepareSql(), message, dbTransaction); _logger.LogInformation("Published Message has been persisted in the database. name:" + message); } - public async Task PublishAsync(CapPublishedMessage message) - { - using (var conn = new SqlConnection(_options.ConnectionString)) - { - await conn.ExecuteAsync(PrepareSql(), message); - } - } - #region private methods private string PrepareSql() { - return $"INSERT INTO {_options.Schema}.[Published] ([Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName])VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; + return + $"INSERT INTO {_options.Schema}.[Published] ([Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName])VALUES(@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName)"; } #endregion private methods diff --git a/src/DotNetCore.CAP.SqlServer/IAdditionalProcessor.Default.cs b/src/DotNetCore.CAP.SqlServer/IAdditionalProcessor.Default.cs index f5a1dac..e87f87a 100644 --- a/src/DotNetCore.CAP.SqlServer/IAdditionalProcessor.Default.cs +++ b/src/DotNetCore.CAP.SqlServer/IAdditionalProcessor.Default.cs @@ -9,18 +9,18 @@ namespace DotNetCore.CAP.SqlServer { public class DefaultAdditionalProcessor : IAdditionalProcessor { - private readonly ILogger _logger; - private readonly SqlServerOptions _options; - private const int MaxBatch = 1000; - private readonly TimeSpan _delay = TimeSpan.FromSeconds(1); - private readonly TimeSpan _waitingInterval = TimeSpan.FromMinutes(5); private static readonly string[] Tables = { - "Published","Received" + "Published", "Received" }; + private readonly TimeSpan _delay = TimeSpan.FromSeconds(1); + private readonly ILogger _logger; + private readonly SqlServerOptions _options; + private readonly TimeSpan _waitingInterval = TimeSpan.FromMinutes(5); + public DefaultAdditionalProcessor(ILogger logger, SqlServerOptions sqlServerOptions) { @@ -42,7 +42,7 @@ namespace DotNetCore.CAP.SqlServer removedCount = await connection.ExecuteAsync($@" DELETE TOP (@count) FROM [{_options.Schema}].[{table}] WITH (readpast) -WHERE ExpiresAt < @now;", new { now = DateTime.Now, count = MaxBatch }); +WHERE ExpiresAt < @now;", new {now = DateTime.Now, count = MaxBatch}); } if (removedCount != 0) diff --git a/src/DotNetCore.CAP.SqlServer/SqlServerFetchedMessage.cs b/src/DotNetCore.CAP.SqlServer/SqlServerFetchedMessage.cs index 06bc461..e423258 100644 --- a/src/DotNetCore.CAP.SqlServer/SqlServerFetchedMessage.cs +++ b/src/DotNetCore.CAP.SqlServer/SqlServerFetchedMessage.cs @@ -8,11 +8,11 @@ namespace DotNetCore.CAP.SqlServer { public class SqlServerFetchedMessage : IFetchedMessage { - private readonly IDbConnection _connection; - private readonly IDbTransaction _transaction; - private readonly Timer _timer; private static readonly TimeSpan KeepAliveInterval = TimeSpan.FromMinutes(1); + private readonly IDbConnection _connection; private readonly object _lockObject = new object(); + private readonly Timer _timer; + private readonly IDbTransaction _transaction; public SqlServerFetchedMessage(int messageId, MessageType type, diff --git a/src/DotNetCore.CAP.SqlServer/SqlServerMonitoringApi.cs b/src/DotNetCore.CAP.SqlServer/SqlServerMonitoringApi.cs index d0c649b..1d0d1c0 100644 --- a/src/DotNetCore.CAP.SqlServer/SqlServerMonitoringApi.cs +++ b/src/DotNetCore.CAP.SqlServer/SqlServerMonitoringApi.cs @@ -12,8 +12,8 @@ namespace DotNetCore.CAP.SqlServer { internal class SqlServerMonitoringApi : IMonitoringApi { - private readonly SqlServerStorage _storage; private readonly SqlServerOptions _options; + private readonly SqlServerStorage _storage; public SqlServerMonitoringApi(IStorage storage, SqlServerOptions options) { @@ -23,7 +23,7 @@ namespace DotNetCore.CAP.SqlServer public StatisticsDto GetStatistics() { - string sql = String.Format(@" + var sql = string.Format(@" set transaction isolation level read committed; select count(Id) from [{0}].Published with (nolock) where StatusName = N'Succeeded'; select count(Id) from [{0}].Received with (nolock) where StatusName = N'Succeeded'; @@ -31,7 +31,7 @@ select count(Id) from [{0}].Published with (nolock) where StatusName = N'Failed' select count(Id) from [{0}].Received with (nolock) where StatusName = N'Failed'; select count(Id) from [{0}].Published with (nolock) where StatusName in (N'Processing',N'Scheduled',N'Enqueued'); select count(Id) from [{0}].Received with (nolock) where StatusName in (N'Processing',N'Scheduled',N'Enqueued');", -_options.Schema); + _options.Schema); var statistics = UseConnection(connection => { @@ -63,7 +63,7 @@ _options.Schema); { var tableName = type == MessageType.Publish ? "Published" : "Received"; return UseConnection(connection => - GetHourlyTimelineStats(connection, tableName, StatusName.Succeeded)); + GetHourlyTimelineStats(connection, tableName, StatusName.Succeeded)); } public IList Messages(MessageQueryDto queryDto) @@ -71,30 +71,20 @@ _options.Schema); var tableName = queryDto.MessageType == MessageType.Publish ? "Published" : "Received"; var where = string.Empty; if (!string.IsNullOrEmpty(queryDto.StatusName)) - { - if (string.Equals(queryDto.StatusName, StatusName.Processing, StringComparison.CurrentCultureIgnoreCase)) - { + if (string.Equals(queryDto.StatusName, StatusName.Processing, + StringComparison.CurrentCultureIgnoreCase)) where += " and statusname in (N'Processing',N'Scheduled',N'Enqueued')"; - } else - { where += " and statusname=@StatusName"; - } - } if (!string.IsNullOrEmpty(queryDto.Name)) - { where += " and name=@Name"; - } if (!string.IsNullOrEmpty(queryDto.Group)) - { where += " and group=@Group"; - } if (!string.IsNullOrEmpty(queryDto.Content)) - { where += " and content like '%@Content%'"; - } - var sqlQuery = $"select * from [{_options.Schema}].{tableName} where 1=1 {where} order by Added desc offset @Offset rows fetch next @Limit rows only"; + var sqlQuery = + $"select * from [{_options.Schema}].{tableName} where 1=1 {where} order by Added desc offset @Offset rows fetch next @Limit rows only"; return UseConnection(conn => conn.Query(sqlQuery, new { @@ -103,7 +93,7 @@ _options.Schema); queryDto.Name, queryDto.Content, Offset = queryDto.CurrentPage * queryDto.PageSize, - Limit = queryDto.PageSize, + Limit = queryDto.PageSize }).ToList()); } @@ -143,7 +133,7 @@ _options.Schema); ? $"select count(Id) from [{_options.Schema}].{tableName} with (nolock) where StatusName in (N'Processing',N'Scheduled',N'Enqueued')" : $"select count(Id) from [{_options.Schema}].{tableName} with (nolock) where StatusName = @state"; - var count = connection.ExecuteScalar(sqlQuery, new { state = statusName }); + var count = connection.ExecuteScalar(sqlQuery, new {state = statusName}); return count; } @@ -152,7 +142,8 @@ _options.Schema); return _storage.UseConnection(action); } - private Dictionary GetHourlyTimelineStats(IDbConnection connection, string tableName, string statusName) + private Dictionary GetHourlyTimelineStats(IDbConnection connection, string tableName, + string statusName) { var endDate = DateTime.Now; var dates = new List(); @@ -168,14 +159,14 @@ _options.Schema); } private Dictionary GetTimelineStats( - IDbConnection connection, - string tableName, - string statusName, - IDictionary keyMaps) + IDbConnection connection, + string tableName, + string statusName, + IDictionary keyMaps) { //SQL Server 2012+ - string sqlQuery = -$@" + var sqlQuery = + $@" with aggr as ( select FORMAT(Added,'yyyy-MM-dd-HH') as [Key], count(id) [Count] @@ -186,14 +177,12 @@ with aggr as ( select [Key], [Count] from aggr with (nolock) where [Key] in @keys;"; var valuesMap = connection.Query( - sqlQuery, - new { keys = keyMaps.Keys, statusName }) - .ToDictionary(x => (string)x.Key, x => (int)x.Count); + sqlQuery, + new {keys = keyMaps.Keys, statusName}) + .ToDictionary(x => (string) x.Key, x => (int) 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++) diff --git a/src/DotNetCore.CAP.SqlServer/SqlServerStorage.cs b/src/DotNetCore.CAP.SqlServer/SqlServerStorage.cs index c0131b8..83d2a81 100644 --- a/src/DotNetCore.CAP.SqlServer/SqlServerStorage.cs +++ b/src/DotNetCore.CAP.SqlServer/SqlServerStorage.cs @@ -11,9 +11,9 @@ namespace DotNetCore.CAP.SqlServer { public class SqlServerStorage : IStorage { - private readonly SqlServerOptions _options; - private readonly ILogger _logger; private readonly IDbConnection _existingConnection = null; + private readonly ILogger _logger; + private readonly SqlServerOptions _options; public SqlServerStorage(ILogger logger, SqlServerOptions options) { @@ -47,7 +47,7 @@ namespace DotNetCore.CAP.SqlServer protected virtual string CreateDbTablesScript(string schema) { var batchSql = - $@" + $@" IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{schema}') BEGIN EXEC('CREATE SCHEMA {schema}') @@ -118,9 +118,7 @@ END;"; var connection = _existingConnection ?? new SqlConnection(_options.ConnectionString); if (connection.State == ConnectionState.Closed) - { connection.Open(); - } return connection; } @@ -133,10 +131,7 @@ END;"; internal void ReleaseConnection(IDbConnection connection) { if (connection != null && !IsExistingConnection(connection)) - { connection.Dispose(); - } } - } } \ No newline at end of file diff --git a/src/DotNetCore.CAP.SqlServer/SqlServerStorageConnection.cs b/src/DotNetCore.CAP.SqlServer/SqlServerStorageConnection.cs index 50ca30a..0f68e5d 100644 --- a/src/DotNetCore.CAP.SqlServer/SqlServerStorageConnection.cs +++ b/src/DotNetCore.CAP.SqlServer/SqlServerStorageConnection.cs @@ -101,7 +101,7 @@ VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; } } - public async Task GetNextReceviedMessageToBeEnqueuedAsync() + public async Task GetNextReceivedMessageToBeEnqueuedAsync() { var sql = $"SELECT TOP (1) * FROM [{Options.Schema}].[Received] WITH (readpast) WHERE StatusName = '{StatusName.Scheduled}'"; @@ -111,7 +111,7 @@ VALUES(@Name,@Group,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; } } - public async Task> GetFailedReceviedMessages() + public async Task> GetFailedReceivedMessages() { var sql = $"SELECT * FROM [{Options.Schema}].[Received] WITH (readpast) WHERE StatusName = '{StatusName.Failed}'"; diff --git a/src/DotNetCore.CAP.SqlServer/SqlServerStorageTransaction.cs b/src/DotNetCore.CAP.SqlServer/SqlServerStorageTransaction.cs index 521070a..396effe 100644 --- a/src/DotNetCore.CAP.SqlServer/SqlServerStorageTransaction.cs +++ b/src/DotNetCore.CAP.SqlServer/SqlServerStorageTransaction.cs @@ -9,10 +9,10 @@ namespace DotNetCore.CAP.SqlServer { public class SqlServerStorageTransaction : IStorageTransaction { - private readonly string _schema; + private readonly IDbConnection _dbConnection; private readonly IDbTransaction _dbTransaction; - private readonly IDbConnection _dbConnection; + private readonly string _schema; public SqlServerStorageTransaction(SqlServerStorageConnection connection) { @@ -28,7 +28,8 @@ namespace DotNetCore.CAP.SqlServer { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $"UPDATE [{_schema}].[Published] SET [Retries] = @Retries,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"; + var sql = + $"UPDATE [{_schema}].[Published] SET [Retries] = @Retries,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -36,7 +37,8 @@ namespace DotNetCore.CAP.SqlServer { if (message == null) throw new ArgumentNullException(nameof(message)); - var sql = $"UPDATE [{_schema}].[Received] SET [Retries] = @Retries,[Content] = @Content,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"; + var sql = + $"UPDATE [{_schema}].[Received] SET [Retries] = @Retries,[Content] = @Content,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"; _dbConnection.Execute(sql, message, _dbTransaction); } @@ -45,7 +47,8 @@ namespace DotNetCore.CAP.SqlServer if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $"INSERT INTO [{_schema}].[Queue] values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Publish }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Publish}, + _dbTransaction); } public void EnqueueMessage(CapReceivedMessage message) @@ -53,7 +56,8 @@ namespace DotNetCore.CAP.SqlServer if (message == null) throw new ArgumentNullException(nameof(message)); var sql = $"INSERT INTO [{_schema}].[Queue] values(@MessageId,@MessageType);"; - _dbConnection.Execute(sql, new CapQueue { MessageId = message.Id, MessageType = MessageType.Subscribe }, _dbTransaction); + _dbConnection.Execute(sql, new CapQueue {MessageId = message.Id, MessageType = MessageType.Subscribe}, + _dbTransaction); } public Task CommitAsync() diff --git a/src/DotNetCore.CAP/Abstractions/CapPublisherBase.cs b/src/DotNetCore.CAP/Abstractions/CapPublisherBase.cs index 2fd661a..77ef125 100644 --- a/src/DotNetCore.CAP/Abstractions/CapPublisherBase.cs +++ b/src/DotNetCore.CAP/Abstractions/CapPublisherBase.cs @@ -10,7 +10,7 @@ namespace DotNetCore.CAP.Abstractions public abstract class CapPublisherBase : ICapPublisher, IDisposable { protected IDbConnection DbConnection { get; set; } - protected IDbTransaction DbTranasaction { get; set; } + protected IDbTransaction DbTransaction { get; set; } protected bool IsCapOpenedTrans { get; set; } protected bool IsCapOpenedConn { get; set; } protected bool IsUsingEF { get; set; } @@ -60,13 +60,15 @@ namespace DotNetCore.CAP.Abstractions protected abstract void PrepareConnectionForEF(); - protected abstract void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message); + protected abstract void Execute(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message); - protected abstract Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, CapPublishedMessage message); + protected abstract Task ExecuteAsync(IDbConnection dbConnection, IDbTransaction dbTransaction, + CapPublishedMessage message); protected virtual string Serialize(T obj, string callbackName = null) { - var serializer = (IContentSerializer)ServiceProvider.GetService(typeof(IContentSerializer)); + var serializer = (IContentSerializer) ServiceProvider.GetService(typeof(IContentSerializer)); var message = new CapMessageDto(obj) { @@ -85,11 +87,11 @@ namespace DotNetCore.CAP.Abstractions IsCapOpenedConn = true; DbConnection.Open(); } - DbTranasaction = dbTransaction; - if (DbTranasaction == null) + DbTransaction = dbTransaction; + if (DbTransaction == null) { IsCapOpenedTrans = true; - DbTranasaction = dbConnection.BeginTransaction(IsolationLevel.ReadCommitted); + DbTransaction = dbConnection.BeginTransaction(IsolationLevel.ReadCommitted); } } @@ -97,15 +99,17 @@ namespace DotNetCore.CAP.Abstractions { if (name == null) throw new ArgumentNullException(nameof(name)); if (!IsUsingEF) - throw new InvalidOperationException("If you are using the EntityFramework, you need to configure the DbContextType first." + - " otherwise you need to use overloaded method with IDbConnection and IDbTransaction."); + throw new InvalidOperationException( + "If you are using the EntityFramework, you need to configure the DbContextType first." + + " otherwise you need to use overloaded method with IDbConnection and IDbTransaction."); } private void CheckIsAdoNet(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); if (IsUsingEF) - throw new InvalidOperationException("If you are using the EntityFramework, you do not need to use this overloaded."); + throw new InvalidOperationException( + "If you are using the EntityFramework, you do not need to use this overloaded."); } private async Task PublishWithTransAsync(string name, string content) @@ -117,7 +121,7 @@ namespace DotNetCore.CAP.Abstractions StatusName = StatusName.Scheduled }; - await ExecuteAsync(DbConnection, DbTranasaction, message); + await ExecuteAsync(DbConnection, DbTransaction, message); ClosedCap(); @@ -133,7 +137,7 @@ namespace DotNetCore.CAP.Abstractions StatusName = StatusName.Scheduled }; - Execute(DbConnection, DbTranasaction, message); + Execute(DbConnection, DbTransaction, message); ClosedCap(); @@ -144,18 +148,16 @@ namespace DotNetCore.CAP.Abstractions { if (IsCapOpenedTrans) { - DbTranasaction.Commit(); - DbTranasaction.Dispose(); + DbTransaction.Commit(); + DbTransaction.Dispose(); } if (IsCapOpenedConn) - { DbConnection.Dispose(); - } } public void Dispose() { - DbTranasaction?.Dispose(); + DbTransaction?.Dispose(); DbConnection?.Dispose(); } diff --git a/src/DotNetCore.CAP/Abstractions/ConsumerContext.cs b/src/DotNetCore.CAP/Abstractions/ConsumerContext.cs index bb0cbb4..e2fa4d5 100644 --- a/src/DotNetCore.CAP/Abstractions/ConsumerContext.cs +++ b/src/DotNetCore.CAP/Abstractions/ConsumerContext.cs @@ -3,15 +3,15 @@ namespace DotNetCore.CAP.Abstractions { /// - /// A context for consumers, it used to be provider wapper of method description and received message. + /// A context for consumers, it used to be provider wrapper of method description and received message. /// public class ConsumerContext { /// - /// create a new instance of . + /// create a new instance of . /// /// consumer method descriptor. - /// reveied message. + /// received message. public ConsumerContext(ConsumerExecutorDescriptor descriptor, MessageContext message) { ConsumerDescriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor)); @@ -24,7 +24,7 @@ namespace DotNetCore.CAP.Abstractions public ConsumerExecutorDescriptor ConsumerDescriptor { get; set; } /// - /// consumer reveived message. + /// consumer received message. /// public MessageContext DeliverMessage { get; set; } } diff --git a/src/DotNetCore.CAP/Abstractions/IConsumerServiceSelector.cs b/src/DotNetCore.CAP/Abstractions/IConsumerServiceSelector.cs index 4ddecc7..66e7d17 100644 --- a/src/DotNetCore.CAP/Abstractions/IConsumerServiceSelector.cs +++ b/src/DotNetCore.CAP/Abstractions/IConsumerServiceSelector.cs @@ -3,22 +3,22 @@ namespace DotNetCore.CAP.Abstractions { /// - /// Defines an interface for selecting an cosumer service method to invoke for the current message. + /// Defines an interface for selecting an consumer service method to invoke for the current message. /// public interface IConsumerServiceSelector { /// - /// Selects a set of candidates for the current message associated with - /// - /// A set of candidates or null. + /// Selects a set of candidates for the current message associated with + /// + /// A set of candidates or null. IReadOnlyList SelectCandidates(); /// - /// Selects the best candidate from for the + /// Selects the best candidate from for the /// current message associated. /// /// topic or exchange router key. - /// the set of candidates. + /// the set of candidates. /// ConsumerExecutorDescriptor SelectBestCandidate(string key, IReadOnlyList candidates); diff --git a/src/DotNetCore.CAP/Abstractions/IContentSerializer.cs b/src/DotNetCore.CAP/Abstractions/IContentSerializer.cs index 3e8e2b7..952e6bf 100644 --- a/src/DotNetCore.CAP/Abstractions/IContentSerializer.cs +++ b/src/DotNetCore.CAP/Abstractions/IContentSerializer.cs @@ -8,4 +8,4 @@ namespace DotNetCore.CAP.Abstractions T DeSerialize(string content) where T : CapMessageDto, new(); } -} +} \ No newline at end of file diff --git a/src/DotNetCore.CAP/Abstractions/ModelBinding/ModelBindingResult.cs b/src/DotNetCore.CAP/Abstractions/ModelBinding/ModelBindingResult.cs index b1ae8eb..c1796d9 100644 --- a/src/DotNetCore.CAP/Abstractions/ModelBinding/ModelBindingResult.cs +++ b/src/DotNetCore.CAP/Abstractions/ModelBinding/ModelBindingResult.cs @@ -8,22 +8,22 @@ namespace DotNetCore.CAP.Abstractions.ModelBinding public struct ModelBindingResult { /// - /// Creates a representing a failed model binding operation. + /// Creates a representing a failed model binding operation. /// - /// A representing a failed model binding operation. + /// A representing a failed model binding operation. public static ModelBindingResult Failed() { - return new ModelBindingResult(model: null, isSuccess: false); + return new ModelBindingResult(null, false); } /// - /// Creates a representing a successful model binding operation. + /// Creates a representing a successful model binding operation. /// /// The model value. May be null. - /// A representing a successful model bind. + /// A representing a successful model bind. public static ModelBindingResult Success(object model) { - return new ModelBindingResult(model, isSuccess: true); + return new ModelBindingResult(model, true); } private ModelBindingResult(object model, bool isSuccess) @@ -42,26 +42,16 @@ namespace DotNetCore.CAP.Abstractions.ModelBinding public override string ToString() { if (IsSuccess) - { return $"Success '{Model}'"; - } - else - { - return $"Failed"; - } + return $"Failed"; } public override bool Equals(object obj) { var other = obj as ModelBindingResult?; if (other == null) - { return false; - } - else - { - return Equals(other.Value); - } + return Equals(other.Value); } public override int GetHashCode() @@ -81,10 +71,10 @@ namespace DotNetCore.CAP.Abstractions.ModelBinding } /// - /// Compares objects for equality. + /// Compares objects for equality. /// - /// A . - /// A . + /// A . + /// A . /// true if the objects are equal, otherwise false. public static bool operator ==(ModelBindingResult x, ModelBindingResult y) { @@ -92,10 +82,10 @@ namespace DotNetCore.CAP.Abstractions.ModelBinding } /// - /// Compares objects for inequality. + /// Compares objects for inequality. /// - /// A . - /// A . + /// A . + /// A . /// true if the objects are not equal, otherwise false. public static bool operator !=(ModelBindingResult x, ModelBindingResult y) { diff --git a/src/DotNetCore.CAP/Abstractions/TopicAttribute.cs b/src/DotNetCore.CAP/Abstractions/TopicAttribute.cs index 3dc7308..9fcdd8b 100644 --- a/src/DotNetCore.CAP/Abstractions/TopicAttribute.cs +++ b/src/DotNetCore.CAP/Abstractions/TopicAttribute.cs @@ -4,7 +4,7 @@ namespace DotNetCore.CAP.Abstractions { /// /// - /// An abstract attribute that for kafka attribute or rabbitmq attribute + /// An abstract attribute that for kafka attribute or rabbit mq attribute /// [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)] public abstract class TopicAttribute : Attribute @@ -20,8 +20,8 @@ namespace DotNetCore.CAP.Abstractions public string Name { get; } /// - /// kafak --> groups.id - /// rabbitmq --> queue.name + /// kafka --> groups.id + /// rabbit MQ --> queue.name /// public string Group { get; set; } = "cap.default.group"; } diff --git a/src/DotNetCore.CAP/CAP.AppBuilderExtensions.cs b/src/DotNetCore.CAP/CAP.AppBuilderExtensions.cs index 1caf994..51ccbff 100644 --- a/src/DotNetCore.CAP/CAP.AppBuilderExtensions.cs +++ b/src/DotNetCore.CAP/CAP.AppBuilderExtensions.cs @@ -7,21 +7,19 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Builder { /// - /// app extensions for + /// app extensions for /// public static class AppBuilderExtensions { - /// + /// /// Enables cap for the current application /// - /// The instance this method extends. - /// The instance this method extends. + /// The instance this method extends. + /// The instance this method extends. public static IApplicationBuilder UseCap(this IApplicationBuilder app) { if (app == null) - { throw new ArgumentNullException(nameof(app)); - } CheckRequirement(app); @@ -33,9 +31,7 @@ namespace Microsoft.AspNetCore.Builder if (provider.GetService() != null) { if (provider.GetService() != null) - { app.UseMiddleware(); - } app.UseMiddleware(); } @@ -46,21 +42,18 @@ namespace Microsoft.AspNetCore.Builder { var marker = app.ApplicationServices.GetService(); if (marker == null) - { - throw new InvalidOperationException("AddCap() must be called on the service collection. eg: services.AddCap(...)"); - } + throw new InvalidOperationException( + "AddCap() must be called on the service collection. eg: services.AddCap(...)"); - var messageQueuemarker = app.ApplicationServices.GetService(); - if (messageQueuemarker == null) - { - throw new InvalidOperationException("You must be config used message queue provider at AddCap() options! eg: services.AddCap(options=>{ options.UseKafka(...) })"); - } + var messageQueueMarker = app.ApplicationServices.GetService(); + if (messageQueueMarker == null) + throw new InvalidOperationException( + "You must be config used message queue provider at AddCap() options! eg: services.AddCap(options=>{ options.UseKafka(...) })"); var databaseMarker = app.ApplicationServices.GetService(); if (databaseMarker == null) - { - throw new InvalidOperationException("You must be config used database provider at AddCap() options! eg: services.AddCap(options=>{ options.UseSqlServer(...) })"); - } + throw new InvalidOperationException( + "You must be config used database provider at AddCap() options! eg: services.AddCap(options=>{ options.UseSqlServer(...) })"); } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/CAP.Builder.cs b/src/DotNetCore.CAP/CAP.Builder.cs index 0ab5c54..dd495ca 100644 --- a/src/DotNetCore.CAP/CAP.Builder.cs +++ b/src/DotNetCore.CAP/CAP.Builder.cs @@ -15,7 +15,6 @@ namespace DotNetCore.CAP /// public class CapDatabaseStorageMarkerService { - } /// @@ -23,7 +22,6 @@ namespace DotNetCore.CAP /// public class CapMessageQueueMakerService { - } /// @@ -37,7 +35,7 @@ namespace DotNetCore.CAP } /// - /// Gets the where MVC services are configured. + /// Gets the where MVC services are configured. /// public IServiceCollection Services { get; } @@ -51,7 +49,7 @@ namespace DotNetCore.CAP } /// - /// Add an . + /// Add an . /// /// The type of the service. public virtual CapBuilder AddProducerService() diff --git a/src/DotNetCore.CAP/CAP.Options.cs b/src/DotNetCore.CAP/CAP.Options.cs index f2373cb..9273f78 100644 --- a/src/DotNetCore.CAP/CAP.Options.cs +++ b/src/DotNetCore.CAP/CAP.Options.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using DotNetCore.CAP.Models; namespace DotNetCore.CAP { @@ -8,8 +9,6 @@ namespace DotNetCore.CAP /// public class CapOptions { - internal IList Extensions { get; } - /// /// Default value for polling delay timeout, in seconds. /// @@ -21,7 +20,7 @@ namespace DotNetCore.CAP public const int DefaultQueueProcessorCount = 2; /// - /// Default succeeded message expriation timespan, in seconds. + /// Default succeeded message expiration time span, in seconds. /// public const int DefaultSucceedMessageExpirationAfter = 24 * 3600; @@ -39,8 +38,10 @@ namespace DotNetCore.CAP Extensions = new List(); } + internal IList Extensions { get; } + /// - /// Productor job polling delay time. + /// Producer job polling delay time. /// Default is 15 sec. /// public int PollingDelay { get; set; } @@ -52,8 +53,8 @@ namespace DotNetCore.CAP public int QueueProcessorCount { get; set; } /// - /// Sent or received succeed message after timespan of due, then the message will be deleted at due time. - /// Dafault is 24*3600 seconds. + /// Sent or received succeed message after timespan of due, then the message will be deleted at due time. + /// Default is 24*3600 seconds. /// public int SucceedMessageExpiredAfter { get; set; } @@ -66,7 +67,7 @@ namespace DotNetCore.CAP /// /// We’ll invoke this call-back with message type,name,content when requeue failed message. /// - public Action FailedCallback { get; set; } + public Action FailedCallback { get; set; } /// /// Registers an extension that will be executed when building services. diff --git a/src/DotNetCore.CAP/CAP.ServiceCollectionExtensions.cs b/src/DotNetCore.CAP/CAP.ServiceCollectionExtensions.cs index 4aed1da..024f07f 100644 --- a/src/DotNetCore.CAP/CAP.ServiceCollectionExtensions.cs +++ b/src/DotNetCore.CAP/CAP.ServiceCollectionExtensions.cs @@ -11,16 +11,16 @@ using Microsoft.Extensions.DependencyInjection.Extensions; namespace Microsoft.Extensions.DependencyInjection { /// - /// Contains extension methods to for configuring consistence services. + /// Contains extension methods to for configuring consistence services. /// public static class ServiceCollectionExtensions { /// - /// Adds and configures the consistence services for the consitence. + /// Adds and configures the consistence services for the consistency. /// /// The services available in the application. - /// An action to configure the . - /// An for application services. + /// An action to configure the . + /// An for application services. public static CapBuilder AddCap( this IServiceCollection services, Action setupAction) @@ -42,7 +42,7 @@ namespace Microsoft.Extensions.DependencyInjection services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - + //Processors services.AddTransient(); services.AddTransient(); @@ -51,15 +51,13 @@ namespace Microsoft.Extensions.DependencyInjection //Executors services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); //Options and extension service var options = new CapOptions(); setupAction(options); foreach (var serviceExtension in options.Extensions) - { serviceExtension.AddServices(services); - } services.AddSingleton(options); return new CapBuilder(services); @@ -69,19 +67,13 @@ namespace Microsoft.Extensions.DependencyInjection { var consumerListenerServices = new List>(); foreach (var rejectedServices in services) - { if (rejectedServices.ImplementationType != null && typeof(ICapSubscribe).IsAssignableFrom(rejectedServices.ImplementationType)) - { consumerListenerServices.Add(new KeyValuePair(typeof(ICapSubscribe), rejectedServices.ImplementationType)); - } - } foreach (var service in consumerListenerServices) - { services.AddTransient(service.Key, service.Value); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/CapCache.cs b/src/DotNetCore.CAP/CapCache.cs index 06fdf77..9483ce8 100644 --- a/src/DotNetCore.CAP/CapCache.cs +++ b/src/DotNetCore.CAP/CapCache.cs @@ -6,26 +6,26 @@ using System.Threading; namespace DotNetCore.CAP { #region Cache class + /// /// This is a generic cache subsystem based on key/value pairs, where key is generic, too. Key must be unique. /// Every cache entry has its own timeout. - /// Cache is thread safe and will delete expired entries on its own using System.Threading.Timers (which run on threads). + /// Cache is thread safe and will delete expired entries on its own using System.Threading.Timers (which run on + /// threads). /// public class Cache : IDisposable { #region Constructor and class members - /// - /// Initializes a new instance of the class. - /// - public Cache() { } - private Dictionary _cache = new Dictionary(); - private Dictionary _timers = new Dictionary(); - private ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(); + private readonly Dictionary _cache = new Dictionary(); + private readonly Dictionary _timers = new Dictionary(); + private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(); + #endregion #region IDisposable implementation & Clear - private bool disposed = false; + + private bool disposed; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. @@ -40,7 +40,8 @@ namespace DotNetCore.CAP /// Releases unmanaged and - optionally - managed resources. /// /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// protected virtual void Dispose(bool disposing) { if (!disposed) @@ -67,20 +68,26 @@ namespace DotNetCore.CAP { try { - foreach (Timer t in _timers.Values) + foreach (var t in _timers.Values) t.Dispose(); } catch - { } + { + } _timers.Clear(); _cache.Clear(); } - finally { _locker.ExitWriteLock(); } + finally + { + _locker.ExitWriteLock(); + } } + #endregion #region CheckTimer + // Checks whether a specific timer already exists and adds a new one, if not private void CheckTimer(K key, TimeSpan? cacheTimeout, bool restartTimerIfExists) { @@ -89,41 +96,48 @@ namespace DotNetCore.CAP if (_timers.TryGetValue(key, out timer)) { if (restartTimerIfExists) - { timer.Change( cacheTimeout ?? Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); - } } else + { _timers.Add( key, new Timer( - new TimerCallback(RemoveByTimer), + RemoveByTimer, key, cacheTimeout ?? Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan)); + } } private void RemoveByTimer(object state) { - Remove((K)state); + Remove((K) state); } + #endregion #region AddOrUpdate, Get, Remove, Exists, Clear + /// - /// Adds or updates the specified cache-key with the specified cacheObject and applies a specified timeout (in seconds) to this key. + /// Adds or updates the specified cache-key with the specified cacheObject and applies a specified timeout (in seconds) + /// to this key. /// /// The cache-key to add or update. /// The cache object to store. - /// The cache timeout (lifespan) of this object. Must be 1 or greater. - /// Specify Timeout.Infinite to keep the entry forever. - /// (Optional). If set to true, the timer for this cacheObject will be reset if the object already - /// exists in the cache. (Default = false). + /// + /// The cache timeout (lifespan) of this object. Must be 1 or greater. + /// Specify Timeout.Infinite to keep the entry forever. + /// + /// + /// (Optional). If set to true, the timer for this cacheObject will be reset if the object already + /// exists in the cache. (Default = false). + /// public void AddOrUpdate(K key, T cacheObject, TimeSpan? cacheTimeout, bool restartTimerIfExists = false) { - if (disposed) return; + if (disposed) return; _locker.EnterWriteLock(); try @@ -135,11 +149,15 @@ namespace DotNetCore.CAP else _cache[key] = cacheObject; } - finally { _locker.ExitWriteLock(); } + finally + { + _locker.ExitWriteLock(); + } } /// - /// Adds or updates the specified cache-key with the specified cacheObject and applies Timeout.Infinite to this key. + /// Adds or updates the specified cache-key with the specified cacheObject and applies Timeout.Infinite to this + /// key. /// /// The cache-key to add or update. /// The cache object to store. @@ -168,9 +186,12 @@ namespace DotNetCore.CAP try { T rv; - return (_cache.TryGetValue(key, out rv) ? rv : default(T)); + return _cache.TryGetValue(key, out rv) ? rv : default(T); + } + finally + { + _locker.ExitReadLock(); } - finally { _locker.ExitReadLock(); } } /// @@ -192,7 +213,10 @@ namespace DotNetCore.CAP { return _cache.TryGetValue(key, out value); } - finally { _locker.ExitReadLock(); } + finally + { + _locker.ExitReadLock(); + } } /// @@ -207,18 +231,26 @@ namespace DotNetCore.CAP try { var removers = (from k in _cache.Keys.Cast() - where keyPattern(k) - select k).ToList(); + where keyPattern(k) + select k).ToList(); - foreach (K workKey in removers) + foreach (var workKey in removers) { - try { _timers[workKey].Dispose(); } - catch { } + try + { + _timers[workKey].Dispose(); + } + catch + { + } _timers.Remove(workKey); _cache.Remove(workKey); } } - finally { _locker.ExitWriteLock(); } + finally + { + _locker.ExitWriteLock(); + } } /// @@ -235,13 +267,21 @@ namespace DotNetCore.CAP { if (_cache.ContainsKey(key)) { - try { _timers[key].Dispose(); } - catch { } + try + { + _timers[key].Dispose(); + } + catch + { + } _timers.Remove(key); _cache.Remove(key); } } - finally { _locker.ExitWriteLock(); } + finally + { + _locker.ExitWriteLock(); + } } /// @@ -258,33 +298,40 @@ namespace DotNetCore.CAP { return _cache.ContainsKey(key); } - finally { _locker.ExitReadLock(); } + finally + { + _locker.ExitReadLock(); + } } + #endregion } + #endregion #region Other Cache classes (derived) + /// /// This is a generic cache subsystem based on key/value pairs, where key is a string. - /// You can add any item to this cache as long as the key is unique, so treat keys as something like namespaces and build them with a + /// You can add any item to this cache as long as the key is unique, so treat keys as something like namespaces and + /// build them with a /// specific system/syntax in your application. /// Every cache entry has its own timeout. - /// Cache is thread safe and will delete expired entries on its own using System.Threading.Timers (which run on threads). + /// Cache is thread safe and will delete expired entries on its own using System.Threading.Timers (which run on + /// threads). /// - //public class Cache : Cache - //{ - //} - /// /// The non-generic Cache class instanciates a Cache{object} that can be used with any type of (mixed) contents. - /// It also publishes a static .Global member, so a cache can be used even without creating a dedicated instance. + /// It also publishes a static .Global member, so a cache can be used even without creating a dedicated + /// instance. /// The .Global member is lazy instanciated. /// public class CapCache : Cache { #region Static Global Cache instance - private static Lazy global = new Lazy(); + + private static readonly Lazy global = new Lazy(); + /// /// Gets the global shared cache instance valid for the entire process. /// @@ -292,8 +339,9 @@ namespace DotNetCore.CAP /// The global shared cache instance. /// public static CapCache Global => global.Value; + #endregion } - #endregion -} + #endregion +} \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/BatchCommandDispatcher.cs b/src/DotNetCore.CAP/Dashboard/BatchCommandDispatcher.cs index 6615140..ca707ee 100644 --- a/src/DotNetCore.CAP/Dashboard/BatchCommandDispatcher.cs +++ b/src/DotNetCore.CAP/Dashboard/BatchCommandDispatcher.cs @@ -28,7 +28,7 @@ namespace DotNetCore.CAP.Dashboard _command(context, id); } - context.Response.StatusCode = (int)HttpStatusCode.NoContent; + context.Response.StatusCode = (int) HttpStatusCode.NoContent; } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/CAP.DashboardMiddleware.cs b/src/DotNetCore.CAP/Dashboard/CAP.DashboardMiddleware.cs index 072d8ba..9997280 100644 --- a/src/DotNetCore.CAP/Dashboard/CAP.DashboardMiddleware.cs +++ b/src/DotNetCore.CAP/Dashboard/CAP.DashboardMiddleware.cs @@ -10,12 +10,13 @@ namespace DotNetCore.CAP { public class DashboardMiddleware { - private readonly DashboardOptions _options; private readonly RequestDelegate _next; - private readonly IStorage _storage; + private readonly DashboardOptions _options; private readonly RouteCollection _routes; + private readonly IStorage _storage; - public DashboardMiddleware(RequestDelegate next, DashboardOptions options, IStorage storage, RouteCollection routes) + public DashboardMiddleware(RequestDelegate next, DashboardOptions options, IStorage storage, + RouteCollection routes) { _next = next ?? throw new ArgumentNullException(nameof(next)); _options = options ?? throw new ArgumentNullException(nameof(options)); @@ -40,17 +41,15 @@ namespace DotNetCore.CAP var findResult = _routes.FindDispatcher(context.Request.Path.Value); if (findResult == null) - { return _next.Invoke(context); - } if (_options.Authorization.Any(filter => !filter.Authorize(dashboardContext))) { var isAuthenticated = context.User?.Identity?.IsAuthenticated; context.Response.StatusCode = isAuthenticated == true - ? (int)HttpStatusCode.Forbidden - : (int)HttpStatusCode.Unauthorized; + ? (int) HttpStatusCode.Forbidden + : (int) HttpStatusCode.Unauthorized; return Task.CompletedTask; } @@ -66,4 +65,4 @@ namespace DotNetCore.CAP } } } -} +} \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptions.cs b/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptions.cs index abd9bf9..b144996 100644 --- a/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptions.cs +++ b/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptions.cs @@ -10,7 +10,7 @@ namespace DotNetCore.CAP { AppPath = "/"; PathMatch = "/cap"; - Authorization = new[] { new LocalRequestsOnlyAuthorizationFilter() }; + Authorization = new[] {new LocalRequestsOnlyAuthorizationFilter()}; StatsPollingInterval = 2000; } @@ -28,5 +28,4 @@ namespace DotNetCore.CAP /// public int StatsPollingInterval { get; set; } } - -} +} \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptionsExtensions.cs b/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptionsExtensions.cs index b5c1c2f..c2ef243 100644 --- a/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptionsExtensions.cs +++ b/src/DotNetCore.CAP/Dashboard/CAP.DashboardOptionsExtensions.cs @@ -1,12 +1,12 @@ using System; +using DotNetCore.CAP; +using DotNetCore.CAP.Dashboard; +using DotNetCore.CAP.Dashboard.GatewayProxy; +using DotNetCore.CAP.Dashboard.GatewayProxy.Requester; +using Microsoft.Extensions.DependencyInjection; namespace DotNetCore.CAP { - using Dashboard; - using Dashboard.GatewayProxy; - using Dashboard.GatewayProxy.Requester; - using Microsoft.Extensions.DependencyInjection; - internal sealed class DashboardOptionsExtension : ICapOptionsExtension { private readonly Action _options; @@ -20,8 +20,8 @@ namespace DotNetCore.CAP { var dashboardOptions = new DashboardOptions(); _options?.Invoke(dashboardOptions); - services.AddSingleton(dashboardOptions); - services.AddSingleton(DashboardRoutes.Routes); + services.AddSingleton(dashboardOptions); + services.AddSingleton(DashboardRoutes.Routes); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -31,13 +31,11 @@ namespace DotNetCore.CAP namespace Microsoft.Extensions.DependencyInjection { - using DotNetCore.CAP; - public static class CapOptionsExtensions { public static CapOptions UseDashboard(this CapOptions capOptions) { - return capOptions.UseDashboard(opt => {}); + return capOptions.UseDashboard(opt => { }); } public static CapOptions UseDashboard(this CapOptions capOptions, Action options) diff --git a/src/DotNetCore.CAP/Dashboard/CombinedResourceDispatcher.cs b/src/DotNetCore.CAP/Dashboard/CombinedResourceDispatcher.cs index 3004b30..94c0d99 100644 --- a/src/DotNetCore.CAP/Dashboard/CombinedResourceDispatcher.cs +++ b/src/DotNetCore.CAP/Dashboard/CombinedResourceDispatcher.cs @@ -22,12 +22,10 @@ namespace DotNetCore.CAP.Dashboard protected override void WriteResponse(DashboardResponse response) { foreach (var resourceName in _resourceNames) - { WriteResource( response, _assembly, $"{_baseNamespace}.{resourceName}"); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/CommandDispatcher.cs b/src/DotNetCore.CAP/Dashboard/CommandDispatcher.cs index 85dd87a..75ac2b4 100644 --- a/src/DotNetCore.CAP/Dashboard/CommandDispatcher.cs +++ b/src/DotNetCore.CAP/Dashboard/CommandDispatcher.cs @@ -20,18 +20,14 @@ namespace DotNetCore.CAP.Dashboard if (!"POST".Equals(request.Method, StringComparison.OrdinalIgnoreCase)) { - response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; + response.StatusCode = (int) HttpStatusCode.MethodNotAllowed; return Task.FromResult(false); } if (_command(context)) - { - response.StatusCode = (int)HttpStatusCode.NoContent; - } + response.StatusCode = (int) HttpStatusCode.NoContent; else - { response.StatusCode = 422; - } return Task.FromResult(true); } diff --git a/src/DotNetCore.CAP/Dashboard/Content/css/cap.css b/src/DotNetCore.CAP/Dashboard/Content/css/cap.css index 321659a..dbcc0a5 100644 --- a/src/DotNetCore.CAP/Dashboard/Content/css/cap.css +++ b/src/DotNetCore.CAP/Dashboard/Content/css/cap.css @@ -12,34 +12,32 @@ body { } /* Wrapper for page content to push down footer */ + #wrap { - min-height: 100%; height: auto !important; height: 100%; /* Negative indent footer by its height */ margin: 0 auto -60px; + min-height: 100%; /* Pad bottom by footer height */ padding: 0 0 60px; } /* Set the fixed height of the footer here */ -#footer { - background-color: #f5f5f5; -} + +#footer { background-color: #f5f5f5; } /* Custom page CSS -------------------------------------------------- */ -.container .credit { - margin: 20px 0; -} +.container .credit { margin: 20px 0; } .page-header { margin-top: 0; overflow: hidden; - white-space: nowrap; text-overflow: ellipsis; + white-space: nowrap; } .btn-death { @@ -48,37 +46,33 @@ body { color: #fff; } - .btn-death:hover { - background-color: #666; - border-color: #555; - color: #fff; - } - -.list-group .list-group-item .glyphicon { - margin-right: 3px; +.btn-death:hover { + background-color: #666; + border-color: #555; + color: #fff; } +.list-group .list-group-item .glyphicon { margin-right: 3px; } + .breadcrumb { - margin-bottom: 10px; background-color: inherit; + margin-bottom: 10px; padding: 0; } .btn-toolbar-label { - padding: 7px 0; - vertical-align: middle; display: inline-block; margin-left: 5px; + padding: 7px 0; + vertical-align: middle; } -.btn-toolbar-label-sm { - padding: 5px 0; -} +.btn-toolbar-label-sm { padding: 5px 0; } .btn-toolbar-spacer { - width: 5px; display: inline-block; height: 1px; + width: 5px; } a:hover .label-hover { @@ -86,31 +80,23 @@ a:hover .label-hover { color: #fff !important; } -.expander { - cursor: pointer; -} +.expander { cursor: pointer; } -.expandable { - display: none; -} +.expandable { display: none; } .table-inner { - margin-bottom: 7px; font-size: 90%; + margin-bottom: 7px; } .min-width { - width: 1%; white-space: nowrap; + width: 1%; } -.align-right { - text-align: right; -} +.align-right { text-align: right; } -.table > tbody > tr.hover:hover > td, .table > tbody > tr.hover:hover > th { - background-color: #f9f9f9; -} +.table > tbody > tr.hover:hover > td, .table > tbody > tr.hover:hover > th { background-color: #f9f9f9; } .table > tbody > tr.highlight > td, .table > tbody > tr.highlight > th { background-color: #fcf8e3; @@ -122,246 +108,196 @@ a:hover .label-hover { border-color: #f5e8ce; } -.word-break { - word-break: break-all; -} +.word-break { word-break: break-all; } /* Statistics widget -------------------------------------------------- */ #stats .list-group-item { - border-color: #e7e7e7; background-color: #f8f8f8; + border-color: #e7e7e7; } -#stats a.list-group-item { - color: #777; -} +#stats a.list-group-item { color: #777; } - #stats a.list-group-item:hover, - #stats a.list-group-item:focus { - color: #333; - } +#stats a.list-group-item:hover, +#stats a.list-group-item:focus { color: #333; } #stats .list-group-item.active, #stats .list-group-item.active:hover, #stats .list-group-item.active:focus { - color: #555; background-color: #e7e7e7; border-color: #e7e7e7; + color: #555; } .table td.failed-job-details { - padding-top: 0; - padding-bottom: 0; - border-top: none; background-color: #f5f5f5; + border-top: none; + padding-bottom: 0; + padding-top: 0; } -.obsolete-data, .obsolete-data a, .obsolete-data pre, .obsolete-data .label { - color: #999; -} +.obsolete-data, .obsolete-data a, .obsolete-data pre, .obsolete-data .label { color: #999; } - .obsolete-data pre, .obsolete-data .label { - background-color: #f5f5f5; - } +.obsolete-data pre, .obsolete-data .label { background-color: #f5f5f5; } - .obsolete-data .glyphicon-question-sign { - font-size: 80%; - color: #999; - } +.obsolete-data .glyphicon-question-sign { + color: #999; + font-size: 80%; +} .stack-trace { - padding: 10px; border: none; + padding: 10px; } -.st-type { - font-weight: bold; -} +.st-type { font-weight: bold; } -.st-param-name { - color: #666; -} +.st-param-name { color: #666; } -.st-file { - color: #999; -} +.st-file { color: #999; } .st-method { color: #00008B; font-weight: bold; } -.st-line { - color: #8B008B; -} +.st-line { color: #8B008B; } -.width-200 { - width: 200px; -} +.width-200 { width: 200px; } -.btn-toolbar-top { - margin-bottom: 10px; -} +.btn-toolbar-top { margin-bottom: 10px; } -.paginator .btn { - color: #428bca; -} +.paginator .btn { color: #428bca; } - .paginator .btn.active { - color: #333; - } +.paginator .btn.active { color: #333; } /* Job Snippet styles */ .job-snippet { + -ms-border-radius: 4px; + background-color: #f5f5f5; + border-radius: 4px; + display: table; margin-bottom: 20px; padding: 15px; - display: table; width: 100%; - -ms-border-radius: 4px; - border-radius: 4px; - background-color: #f5f5f5; } - .job-snippet > * { - display: table-cell; - vertical-align: top; - } - -.job-snippet-code { +.job-snippet > * { + display: table-cell; vertical-align: top; } - .job-snippet-code pre { - border: none; - margin: 0; - background: inherit; - padding: 0; - -ms-border-radius: 0; - border-radius: 0; - font-size: 14px; - } +.job-snippet-code { vertical-align: top; } - .job-snippet-code code { - display: block; - color: black; - background-color: #f5f5f5; - } +.job-snippet-code pre { + -ms-border-radius: 0; + background: inherit; + border: none; + border-radius: 0; + font-size: 14px; + margin: 0; + padding: 0; +} - .job-snippet-code pre .comment { - color: rgb(0, 128, 0); - } +.job-snippet-code code { + background-color: #f5f5f5; + color: black; + display: block; +} - .job-snippet-code pre .keyword { - color: rgb(0, 0, 255); - } +.job-snippet-code pre .comment { color: rgb(0, 128, 0); } - .job-snippet-code pre .string { - color: rgb(163, 21, 21); - } +.job-snippet-code pre .keyword { color: rgb(0, 0, 255); } - .job-snippet-code pre .type { - color: rgb(43, 145, 175); - } +.job-snippet-code pre .string { color: rgb(163, 21, 21); } - .job-snippet-code pre .xmldoc { - color: rgb(128, 128, 128); - } +.job-snippet-code pre .type { color: rgb(43, 145, 175); } + +.job-snippet-code pre .xmldoc { color: rgb(128, 128, 128); } .job-snippet-properties { max-width: 200px; padding-left: 5px; } - .job-snippet-properties dl { - margin: 0; - } +.job-snippet-properties dl { margin: 0; } - .job-snippet-properties dl dt { - color: #999; - text-shadow: 0 1px white; - font-weight: normal; - } - - .job-snippet-properties dl dd { - margin-left: 0; - margin-bottom: 5px; - } - - .job-snippet-properties pre { - background-color: white; - -webkit-box-shadow: none; - -ms-box-shadow: none; - padding: 2px 4px; - border: none; - margin: 0; - } +.job-snippet-properties dl dt { + color: #999; + font-weight: normal; + text-shadow: 0 1px white; +} - .job-snippet-properties code { - color: black; - } +.job-snippet-properties dl dd { + margin-bottom: 5px; + margin-left: 0; +} + +.job-snippet-properties pre { + -ms-box-shadow: none; + -webkit-box-shadow: none; + background-color: white; + border: none; + margin: 0; + padding: 2px 4px; +} + +.job-snippet-properties code { color: black; } .state-card { - position: relative; - display: block; - margin-bottom: 7px; - padding: 12px; + -ms-border-radius: 3px; background-color: #fff; border: 1px solid #e5e5e5; - -ms-border-radius: 3px; border-radius: 3px; + display: block; + margin-bottom: 7px; + padding: 12px; + position: relative; } -.state-card-title { - margin-bottom: 0; -} +.state-card-title { margin-bottom: 0; } - .state-card-title .pull-right { - margin-top: 3px; - } +.state-card-title .pull-right { margin-top: 3px; } .state-card-text { - margin-top: 5px; margin-bottom: 0; + margin-top: 5px; } -.state-card h4 { - margin-top: 0; -} +.state-card h4 { margin-top: 0; } .state-card-body { - padding: 10px; - margin: 10px -12px -12px -12px; -ms-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; -ms-border-bottom-right-radius: 3px; - border-bottom-right-radius: 3px; background-color: #f5f5f5; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + margin: 10px -12px -12px -12px; + padding: 10px; } .state-card-body dl { - margin-top: 5px; - margin-bottom: 0; - } + margin-bottom: 0; + margin-top: 5px; +} - .state-card-body pre { - white-space: pre-wrap; /* CSS 3 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - background: transparent; - padding: 0; - } +.state-card-body pre { + background: transparent; + padding: 0; + white-space: pre-wrap; /* CSS 3 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} - .state-card-body .stack-trace { - background-color: transparent; - padding: 0 20px; - margin-bottom: 0; - } +.state-card-body .stack-trace { + background-color: transparent; + margin-bottom: 0; + padding: 0 20px; +} - .state-card-body .exception-type { - margin-top: 0; - } +.state-card-body .exception-type { margin-top: 0; } /* Job History styles */ @@ -370,17 +306,15 @@ a:hover .label-hover { opacity: 0.8; } - .job-history.job-history-current { - opacity: 1.0; - } +.job-history.job-history-current { opacity: 1.0; } .job-history-heading { - padding: 5px 10px; - color: #666; -ms-border-top-left-radius: 4px; - border-top-left-radius: 4px; -ms-border-top-right-radius: 4px; + border-top-left-radius: 4px; border-top-right-radius: 4px; + color: #666; + padding: 5px 10px; } .job-history-body { @@ -389,140 +323,118 @@ a:hover .label-hover { } .job-history-title { - margin-top: 0; margin-bottom: 2px; + margin-top: 0; } .job-history dl { - margin-top: 5px; margin-bottom: 5px; + margin-top: 5px; } .job-history .stack-trace { background-color: transparent; - padding: 0 20px; margin-bottom: 5px; + padding: 0 20px; } -.job-history .exception-type { - margin-top: 0; -} +.job-history .exception-type { margin-top: 0; } .job-history-current .job-history-heading, -.job-history-current small { - color: white; -} +.job-history-current small { color: white; } -a.job-method { - color: inherit; -} +a.job-method { color: inherit; } -.list-group .glyphicon { - top: 2px; -} +.list-group .glyphicon { top: 2px; } span.metric { + -moz-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; + -ms-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; + -o-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; + -webkit-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; + background-color: transparent; + border: solid 1px; + border-radius: 10px; display: inline-block; - min-width: 10px; - padding: 2px 6px; font-size: 12px; line-height: 1; + min-width: 10px; + padding: 2px 6px; text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: transparent; - border-radius: 10px; - border: solid 1px; - -webkit-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; - -moz-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; - -ms-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; - -o-transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; + vertical-align: baseline; + white-space: nowrap; } - span.metric.highlighted { - font-weight: bold; - color: #fff !important; - } +span.metric.highlighted { + color: #fff !important; + font-weight: bold; +} span.metric-default { - color: #777; border-color: #777; + color: #777; } - span.metric-default.highlighted { - background-color: #777; - } +span.metric-default.highlighted { background-color: #777; } div.metric { - border: solid 1px transparent; -ms-border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + border: solid 1px transparent; border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.05); - box-shadow: 0 1px 1px rgba(0,0,0,.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); margin-bottom: 20px; transition: color .1s ease-out, background .1s ease-out, border .1s ease-out; } div.metric .metric-body { - padding: 15px 15px 0; - font-size: 26px; - text-align: center; - } + font-size: 26px; + padding: 15px 15px 0; + text-align: center; +} - div.metric .metric-description { - padding: 0 15px 15px; - text-align: center; - } +div.metric .metric-description { + padding: 0 15px 15px; + text-align: center; +} - div.metric.metric-default { - border-color: #ddd; - } +div.metric.metric-default { border-color: #ddd; } div.metric-info, span.metric-info { - color: #5bc0de; border-color: #5bc0de; + color: #5bc0de; } - span.metric-info.highlighted { - background-color: #5bc0de; - } +span.metric-info.highlighted { background-color: #5bc0de; } div.metric-warning, span.metric-warning { - color: #f0ad4e; border-color: #f0ad4e; + color: #f0ad4e; } - span.metric-warning.highlighted { - background-color: #f0ad4e; - } +span.metric-warning.highlighted { background-color: #f0ad4e; } div.metric-success, span.metric-success { - color: #5cb85c; border-color: #5cb85c; + color: #5cb85c; } - span.metric-success.highlighted { - background-color: #5cb85c; - } +span.metric-success.highlighted { background-color: #5cb85c; } div.metric-danger, span.metric-danger { - color: #d9534f; border-color: #d9534f; + color: #d9534f; } - span.metric-danger.highlighted { - background-color: #d9534f; - } +span.metric-danger.highlighted { background-color: #d9534f; } span.metric-null, -div.metric-null { - display: none; -} +div.metric-null { display: none; } @media (min-width: 992px) { #stats { @@ -532,23 +444,17 @@ div.metric-null { } @media (min-width: 1200px) { - #stats { - width: 262.5px; - } + #stats { width: 262.5px; } } -.subscribe-table td { - vertical-align: middle !important; -} +.subscribe-table td { vertical-align: middle !important; } - .subscribe-table td[rowspan] { - font-weight: bold; - } +.subscribe-table td[rowspan] { font-weight: bold; } #legend { background: rgba(173, 169, 169, 0.13); + color: #000; position: absolute; - top: 110px; right: 20px; - color: #000; -} + top: 110px; +} \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/Content/js/cap.js b/src/DotNetCore.CAP/Dashboard/Content/js/cap.js index 2314bc7..be6a83d 100644 --- a/src/DotNetCore.CAP/Dashboard/Content/js/cap.js +++ b/src/DotNetCore.CAP/Dashboard/Content/js/cap.js @@ -1,16 +1,16 @@ -(function (cap) { +(function(cap) { cap.config = { pollInterval: $("#capConfig").data("pollinterval"), pollUrl: $("#capConfig").data("pollurl"), locale: document.documentElement.lang }; - cap.Metrics = (function () { + cap.Metrics = (function() { function Metrics() { this._metrics = {}; } - Metrics.prototype.addElement = function (name, element) { + Metrics.prototype.addElement = function(name, element) { if (!(name in this._metrics)) { this._metrics[name] = []; } @@ -18,7 +18,7 @@ this._metrics[name].push(element); }; - Metrics.prototype.getElements = function (name) { + Metrics.prototype.getElements = function(name) { if (!(name in this._metrics)) { return []; } @@ -26,11 +26,11 @@ return this._metrics[name]; }; - Metrics.prototype.getNames = function () { - var result = []; - var metrics = this._metrics; + Metrics.prototype.getNames = function() { + const result = []; + const metrics = this._metrics; - for (var name in metrics) { + for (let name in metrics) { if (metrics.hasOwnProperty(name)) { result.push(name); } @@ -42,14 +42,14 @@ return Metrics; })(); - var BaseGraph = function () { + var BaseGraph = function() { this.height = 200; }; - BaseGraph.prototype.update = function () { - var graph = this._graph; + BaseGraph.prototype.update = function() { + const graph = this._graph; - var width = $(graph.element).innerWidth(); + const width = $(graph.element).innerWidth(); if (width !== graph.width) { graph.configure({ width: width, @@ -60,48 +60,57 @@ graph.update(); }; - BaseGraph.prototype._initGraph = function (element, settings, xSettings, ySettings) { + BaseGraph.prototype._initGraph = function(element, settings, xSettings, ySettings) { - var graph = this._graph = new Rickshaw.Graph($.extend({ - element: element, - width: $(element).innerWidth(), - height: this.height, - interpolation: 'linear', - stroke: true - }, settings)); + const graph = this._graph = new Rickshaw.Graph($.extend({ + element: element, + width: $(element).innerWidth(), + height: this.height, + interpolation: "linear", + stroke: true + }, + settings)); this._hoverDetail = new Rickshaw.Graph.HoverDetail({ graph: graph, - yFormatter: function (y) { return Math.floor(y); }, - xFormatter: function (x) { return moment(new Date(x * 1000)).format("LLLL"); } + yFormatter: function(y) { return Math.floor(y); }, + xFormatter: function(x) { return moment(new Date(x * 1000)).format("LLLL"); } }); if (xSettings) { this._xAxis = new Rickshaw.Graph.Axis.Time($.extend({ - graph: graph, - timeFixture: new Rickshaw.Fixtures.Time.Local() - }, xSettings)); + graph: graph, + timeFixture: new Rickshaw.Fixtures.Time.Local() + }, + xSettings)); - var legend = new Rickshaw.Graph.Legend({ - element: document.querySelector('#legend'), + const legend = new Rickshaw.Graph.Legend({ + element: document.querySelector("#legend"), graph: graph }); } if (ySettings) { this._yAxis = new Rickshaw.Graph.Axis.Y($.extend({ - graph: graph, - tickFormat: Rickshaw.Fixtures.Number.formatKMBT - }, ySettings)); + graph: graph, + tickFormat: Rickshaw.Fixtures.Number.formatKMBT + }, + ySettings)); } graph.render(); - } + }; - cap.RealtimeGraph = (function () { + cap.RealtimeGraph = (function() { function RealtimeGraph(element, - pubSucceeded, pubFailed, pubSucceededStr, pubFailedStr, - recSucceeded, recFailed, recSucceededStr, recFailedStr + pubSucceeded, + pubFailed, + pubSucceededStr, + pubFailedStr, + recSucceeded, + recFailed, + recSucceededStr, + recFailedStr ) { this._pubSucceeded = pubSucceeded; this._pubSucceededStr = pubSucceededStr; @@ -115,48 +124,53 @@ this._recFailed = recFailed; this._recFailedStr = recFailedStr; - this._initGraph(element, { - renderer: 'bar', - series: new Rickshaw.Series.FixedDuration([ - { - name: pubSucceededStr, - color: '#33cc33' - },{ - name: recSucceededStr, - color: '#3333cc' - },{ - name: pubFailedStr, - color: '#ff3300' - },{ - name: recFailedStr, - color: '#ff3399' - } - ], - undefined, - { timeInterval: 2000, maxDataPoints: 100 } - ) - }, null, {}); + this._initGraph(element, + { + renderer: "bar", + series: new Rickshaw.Series.FixedDuration([ + { + name: pubSucceededStr, + color: "#33cc33" + }, { + name: recSucceededStr, + color: "#3333cc" + }, { + name: pubFailedStr, + color: "#ff3300" + }, { + name: recFailedStr, + color: "#ff3399" + } + ], + undefined, + { timeInterval: 2000, maxDataPoints: 100 } + ) + }, + null, + {}); } RealtimeGraph.prototype = Object.create(BaseGraph.prototype); - RealtimeGraph.prototype.appendHistory = function (statistics) { - var newPubSucceeded = parseInt(statistics["published_succeeded:count"].intValue); - var newPubFailed = parseInt(statistics["published_failed:count"].intValue); + RealtimeGraph.prototype.appendHistory = function(statistics) { + const newPubSucceeded = parseInt(statistics["published_succeeded:count"].intValue); + const newPubFailed = parseInt(statistics["published_failed:count"].intValue); - var newRecSucceeded = parseInt(statistics["received_succeeded:count"].intValue); - var newRecFailed = parseInt(statistics["received_failed:count"].intValue); + const newRecSucceeded = parseInt(statistics["received_succeeded:count"].intValue); + const newRecFailed = parseInt(statistics["received_failed:count"].intValue); - if (this._pubSucceeded !== null && this._pubFailed !== null && - this._recSucceeded !== null && this._recFailed !== null + if (this._pubSucceeded !== null && + this._pubFailed !== null && + this._recSucceeded !== null && + this._recFailed !== null ) { - var pubSucceeded = newPubSucceeded - this._pubSucceeded; - var pubFailed = newPubFailed - this._pubFailed; + const pubSucceeded = newPubSucceeded - this._pubSucceeded; + const pubFailed = newPubFailed - this._pubFailed; - var recSucceeded = newRecSucceeded - this._recSucceeded; - var recFailed = newRecFailed - this._recFailed; + const recSucceeded = newRecSucceeded - this._recSucceeded; + const recFailed = newRecFailed - this._recFailed; - var dataObj = {}; + const dataObj = {}; dataObj[this._pubFailedStr] = pubFailed; dataObj[this._pubSucceededStr] = pubSucceeded; dataObj[this._recFailedStr] = recFailed; @@ -176,31 +190,41 @@ return RealtimeGraph; })(); - cap.HistoryGraph = (function () { - function HistoryGraph(element, pubSucceeded, pubFailed, pubSucceededStr, pubFailedStr, - recSucceeded, recFailed, recSucceededStr, recFailedStr) { - this._initGraph(element, { - renderer: 'area', - series: [ - { - color: '#33cc33', - data: pubSucceeded, - name: pubSucceededStr - },{ - color: '#3333cc', - data: recSucceeded, - name: recSucceededStr - },{ - color: '#ff3300', - data: pubFailed, - name: pubFailedStr - }, { - color: '#ff3399', - data: recFailed, - name: recFailedStr - } - ] - }, {}, { ticksTreatment: 'glow' }); + cap.HistoryGraph = (function() { + function HistoryGraph(element, + pubSucceeded, + pubFailed, + pubSucceededStr, + pubFailedStr, + recSucceeded, + recFailed, + recSucceededStr, + recFailedStr) { + this._initGraph(element, + { + renderer: "area", + series: [ + { + color: "#33cc33", + data: pubSucceeded, + name: pubSucceededStr + }, { + color: "#3333cc", + data: recSucceeded, + name: recSucceededStr + }, { + color: "#ff3300", + data: pubFailed, + name: pubFailedStr + }, { + color: "#ff3399", + data: recFailed, + name: recFailedStr + } + ] + }, + {}, + { ticksTreatment: "glow" }); } HistoryGraph.prototype = Object.create(BaseGraph.prototype); @@ -208,7 +232,7 @@ return HistoryGraph; })(); - cap.StatisticsPoller = (function () { + cap.StatisticsPoller = (function() { function StatisticsPoller(metricsCallback, statisticsUrl, pollInterval) { this._metricsCallback = metricsCallback; this._listeners = []; @@ -217,14 +241,16 @@ this._intervalId = null; } - StatisticsPoller.prototype.start = function () { + StatisticsPoller.prototype.start = function() { var self = this; - var intervalFunc = function () { + const intervalFunc = function() { try { - $.post(self._statisticsUrl, { metrics: self._metricsCallback() }, function (data) { - self._notifyListeners(data); - }); + $.post(self._statisticsUrl, + { metrics: self._metricsCallback() }, + function(data) { + self._notifyListeners(data); + }); } catch (e) { console.log(e); } @@ -233,19 +259,19 @@ this._intervalId = setInterval(intervalFunc, this._pollInterval); }; - StatisticsPoller.prototype.stop = function () { + StatisticsPoller.prototype.stop = function() { if (this._intervalId !== null) { clearInterval(this._intervalId); this._intervalId = null; } }; - StatisticsPoller.prototype.addListener = function (listener) { + StatisticsPoller.prototype.addListener = function(listener) { this._listeners.push(listener); }; - StatisticsPoller.prototype._notifyListeners = function (statistics) { - var length = this._listeners.length; + StatisticsPoller.prototype._notifyListeners = function(statistics) { + const length = this._listeners.length; var i; for (i = 0; i < length; i++) { @@ -256,36 +282,36 @@ return StatisticsPoller; })(); - cap.Page = (function () { + cap.Page = (function() { function Page(config) { this._metrics = new cap.Metrics(); var self = this; this._poller = new cap.StatisticsPoller( - function () { return self._metrics.getNames(); }, + function() { return self._metrics.getNames(); }, config.pollUrl, config.pollInterval); this._initialize(config.locale); - this.realtimeGraph = this._createRealtimeGraph('realtimeGraph'); - this.historyGraph = this._createHistoryGraph('historyGraph'); + this.realtimeGraph = this._createRealtimeGraph("realtimeGraph"); + this.historyGraph = this._createHistoryGraph("historyGraph"); this._poller.start(); }; - Page.prototype._createRealtimeGraph = function (elementId) { - var realtimeElement = document.getElementById(elementId); + Page.prototype._createRealtimeGraph = function(elementId) { + const realtimeElement = document.getElementById(elementId); if (realtimeElement) { - var pubSucceeded = parseInt($(realtimeElement).data('published-succeeded')); - var pubFailed = parseInt($(realtimeElement).data('published-failed')); - var pubSucceededStr = $(realtimeElement).data('published-succeeded-string'); - var pubFailedStr = $(realtimeElement).data('published-failed-string'); + const pubSucceeded = parseInt($(realtimeElement).data("published-succeeded")); + const pubFailed = parseInt($(realtimeElement).data("published-failed")); + const pubSucceededStr = $(realtimeElement).data("published-succeeded-string"); + const pubFailedStr = $(realtimeElement).data("published-failed-string"); - var recSucceeded = parseInt($(realtimeElement).data('received-succeeded')); - var recFailed = parseInt($(realtimeElement).data('received-failed')); - var recSucceededStr = $(realtimeElement).data('received-succeeded-string'); - var recFailedStr = $(realtimeElement).data('received-failed-string'); + const recSucceeded = parseInt($(realtimeElement).data("received-succeeded")); + const recFailed = parseInt($(realtimeElement).data("received-failed")); + const recSucceededStr = $(realtimeElement).data("received-succeeded-string"); + const recFailedStr = $(realtimeElement).data("received-failed-string"); var realtimeGraph = new Cap.RealtimeGraph(realtimeElement, pubSucceeded, @@ -298,11 +324,11 @@ recFailedStr ); - this._poller.addListener(function (data) { + this._poller.addListener(function(data) { realtimeGraph.appendHistory(data); }); - $(window).resize(function () { + $(window).resize(function() { realtimeGraph.update(); }); @@ -312,30 +338,30 @@ return null; }; - Page.prototype._createHistoryGraph = function (elementId) { - var historyElement = document.getElementById(elementId); + Page.prototype._createHistoryGraph = function(elementId) { + const historyElement = document.getElementById(elementId); if (historyElement) { - var createSeries = function (obj) { - var series = []; - for (var date in obj) { + const createSeries = function(obj) { + const series = []; + for (let date in obj) { if (obj.hasOwnProperty(date)) { - var value = obj[date]; - var point = { x: Date.parse(date) / 1000, y: value }; + const value = obj[date]; + const point = { x: Date.parse(date) / 1000, y: value }; series.unshift(point); } } return series; }; - var publishedSucceeded = createSeries($(historyElement).data("published-succeeded")); - var publishedFailed = createSeries($(historyElement).data("published-failed")); - var publishedSucceededStr = $(historyElement).data('published-succeeded-string'); - var publishedFailedStr = $(historyElement).data('published-failed-string'); + const publishedSucceeded = createSeries($(historyElement).data("published-succeeded")); + const publishedFailed = createSeries($(historyElement).data("published-failed")); + const publishedSucceededStr = $(historyElement).data("published-succeeded-string"); + const publishedFailedStr = $(historyElement).data("published-failed-string"); - var receivedSucceeded = createSeries($(historyElement).data("received-succeeded")); - var receivedFailed = createSeries($(historyElement).data("received-failed")); - var receivedSucceededStr = $(historyElement).data('received-succeeded-string'); - var receivedFailedStr = $(historyElement).data('received-failed-string'); + const receivedSucceeded = createSeries($(historyElement).data("received-succeeded")); + const receivedFailed = createSeries($(historyElement).data("received-failed")); + const receivedSucceededStr = $(historyElement).data("received-succeeded-string"); + const receivedFailedStr = $(historyElement).data("received-failed-string"); var historyGraph = new Cap.HistoryGraph(historyElement, publishedSucceeded, @@ -348,7 +374,7 @@ receivedFailedStr, ); - $(window).resize(function () { + $(window).resize(function() { historyGraph.update(); }); @@ -358,39 +384,39 @@ return null; }; - Page.prototype._initialize = function (locale) { + Page.prototype._initialize = function(locale) { moment.locale(locale); - var updateRelativeDates = function () { - $('*[data-moment]').each(function () { - var $this = $(this); - var timestamp = $this.data('moment'); + const updateRelativeDates = function() { + $("*[data-moment]").each(function() { + const $this = $(this); + const timestamp = $this.data("moment"); if (timestamp) { - var time = moment(timestamp, 'X'); + const time = moment(timestamp, "X"); $this.html(time.fromNow()) - .attr('title', time.format('llll')) - .attr('data-container', 'body'); + .attr("title", time.format("llll")) + .attr("data-container", "body"); } }); - $('*[data-moment-title]').each(function () { - var $this = $(this); - var timestamp = $this.data('moment-title'); + $("*[data-moment-title]").each(function() { + const $this = $(this); + const timestamp = $this.data("moment-title"); if (timestamp) { - var time = moment(timestamp, 'X'); - $this.prop('title', time.format('llll')) - .attr('data-container', 'body'); + const time = moment(timestamp, "X"); + $this.prop("title", time.format("llll")) + .attr("data-container", "body"); } }); - $('*[data-moment-local]').each(function () { - var $this = $(this); - var timestamp = $this.data('moment-local'); + $("*[data-moment-local]").each(function() { + const $this = $(this); + const timestamp = $this.data("moment-local"); if (timestamp) { - var time = moment(timestamp, 'X'); - $this.html(time.format('l LTS')); + const time = moment(timestamp, "X"); + $this.html(time.format("l LTS")); } }); }; @@ -401,163 +427,180 @@ $("*[title]").tooltip(); var self = this; - $("*[data-metric]").each(function () { - var name = $(this).data('metric'); + $("*[data-metric]").each(function() { + const name = $(this).data("metric"); self._metrics.addElement(name, this); }); - this._poller.addListener(function (metrics) { - for (var name in metrics) { - var elements = self._metrics.getElements(name); - for (var i = 0; i < elements.length; i++) { - var metric = metrics[name]; - var metricClass = metric ? "metric-" + metric.style : "metric-null"; - var highlighted = metric && metric.highlighted ? "highlighted" : null; - var value = metric ? metric.value : null; + this._poller.addListener(function(metrics) { + for (let name in metrics) { + const elements = self._metrics.getElements(name); + for (let i = 0; i < elements.length; i++) { + const metric = metrics[name]; + const metricClass = metric ? `metric-${metric.style}` : "metric-null"; + const highlighted = metric && metric.highlighted ? "highlighted" : null; + const value = metric ? metric.value : null; $(elements[i]) .text(value) - .closest('.metric') + .closest(".metric") .removeClass() - .addClass(["metric", metricClass, highlighted].join(' ')); + .addClass(["metric", metricClass, highlighted].join(" ")); } } }); - $(document).on('click', '*[data-ajax]', function (e) { - var $this = $(this); - var confirmText = $this.data('confirm'); - - if (!confirmText || confirm(confirmText)) { - $this.prop('disabled'); - var loadingDelay = setTimeout(function () { - $this.button('loading'); - }, 100); + $(document).on("click", + "*[data-ajax]", + function(e) { + var $this = $(this); + const confirmText = $this.data("confirm"); - $.post($this.data('ajax'), function () { - clearTimeout(loadingDelay); - window.location.reload(); - }); - } + if (!confirmText || confirm(confirmText)) { + $this.prop("disabled"); + var loadingDelay = setTimeout(function() { + $this.button("loading"); + }, + 100); + + $.post($this.data("ajax"), + function() { + clearTimeout(loadingDelay); + window.location.reload(); + }); + } - e.preventDefault(); - }); + e.preventDefault(); + }); - $(document).on('click', '.expander', function (e) { - var $expander = $(this), - $expandable = $expander.closest('tr').next().find('.expandable'); + $(document).on("click", + ".expander", + function(e) { + var $expander = $(this), + $expandable = $expander.closest("tr").next().find(".expandable"); - if (!$expandable.is(':visible')) { - $expander.text('Less details...'); - } + if (!$expandable.is(":visible")) { + $expander.text("Less details..."); + } - $expandable.slideToggle( - 150, - function () { - if (!$expandable.is(':visible')) { - $expander.text('More details...'); - } - }); - e.preventDefault(); - }); + $expandable.slideToggle( + 150, + function() { + if (!$expandable.is(":visible")) { + $expander.text("More details..."); + } + }); + e.preventDefault(); + }); - $('.js-jobs-list').each(function () { + $(".js-jobs-list").each(function() { var container = this; - var selectRow = function (row, isSelected) { - var $checkbox = $('.js-jobs-list-checkbox', row); + var selectRow = function(row, isSelected) { + const $checkbox = $(".js-jobs-list-checkbox", row); if ($checkbox.length > 0) { - $checkbox.prop('checked', isSelected); - $(row).toggleClass('highlight', isSelected); + $checkbox.prop("checked", isSelected); + $(row).toggleClass("highlight", isSelected); } }; - var toggleRowSelection = function (row) { - var $checkbox = $('.js-jobs-list-checkbox', row); + var toggleRowSelection = function(row) { + const $checkbox = $(".js-jobs-list-checkbox", row); if ($checkbox.length > 0) { - var isSelected = $checkbox.is(':checked'); + const isSelected = $checkbox.is(":checked"); selectRow(row, !isSelected); } }; - var setListState = function (state) { - $('.js-jobs-list-select-all', container) - .prop('checked', state === 'all-selected') - .prop('indeterminate', state === 'some-selected'); + var setListState = function(state) { + $(".js-jobs-list-select-all", container) + .prop("checked", state === "all-selected") + .prop("indeterminate", state === "some-selected"); - $('.js-jobs-list-command', container) - .prop('disabled', state === 'none-selected'); + $(".js-jobs-list-command", container) + .prop("disabled", state === "none-selected"); }; - var updateListState = function () { - var selectedRows = $('.js-jobs-list-checkbox', container).map(function () { - return $(this).prop('checked'); + var updateListState = function() { + const selectedRows = $(".js-jobs-list-checkbox", container).map(function() { + return $(this).prop("checked"); }).get(); - var state = 'none-selected'; + var state = "none-selected"; if (selectedRows.length > 0) { - state = 'some-selected'; + state = "some-selected"; if ($.inArray(false, selectedRows) === -1) { - state = 'all-selected'; + state = "all-selected"; } else if ($.inArray(true, selectedRows) === -1) { - state = 'none-selected'; + state = "none-selected"; } } setListState(state); }; - $(this).on('click', '.js-jobs-list-checkbox', function (e) { - selectRow( - $(this).closest('.js-jobs-list-row').first(), - $(this).is(':checked')); - - updateListState(); + $(this).on("click", + ".js-jobs-list-checkbox", + function(e) { + selectRow( + $(this).closest(".js-jobs-list-row").first(), + $(this).is(":checked")); - e.stopPropagation(); - }); + updateListState(); - $(this).on('click', '.js-jobs-list-row', function (e) { - if ($(e.target).is('a')) return; - - toggleRowSelection(this); - updateListState(); - }); + e.stopPropagation(); + }); - $(this).on('click', '.js-jobs-list-select-all', function () { - var selectRows = $(this).is(':checked'); + $(this).on("click", + ".js-jobs-list-row", + function(e) { + if ($(e.target).is("a")) return; - $('.js-jobs-list-row', container).each(function () { - selectRow(this, selectRows); + toggleRowSelection(this); + updateListState(); }); - updateListState(); - }); + $(this).on("click", + ".js-jobs-list-select-all", + function() { + var selectRows = $(this).is(":checked"); - $(this).on('click', '.js-jobs-list-command', function (e) { - var $this = $(this); - var confirmText = $this.data('confirm'); + $(".js-jobs-list-row", container).each(function() { + selectRow(this, selectRows); + }); - var jobs = $("input[name='messages[]']:checked", container).map(function () { - return $(this).val(); - }).get(); + updateListState(); + }); - if (!confirmText || confirm(confirmText)) { - $this.prop('disabled'); - var loadingDelay = setTimeout(function () { - $this.button('loading'); - }, 100); - - $.post($this.data('url'), { 'messages[]': jobs }, function () { - clearTimeout(loadingDelay); - window.location.reload(); - }); - } + $(this).on("click", + ".js-jobs-list-command", + function(e) { + var $this = $(this); + const confirmText = $this.data("confirm"); + + const jobs = $("input[name='messages[]']:checked", container).map(function() { + return $(this).val(); + }).get(); + + if (!confirmText || confirm(confirmText)) { + $this.prop("disabled"); + var loadingDelay = setTimeout(function() { + $this.button("loading"); + }, + 100); + + $.post($this.data("url"), + { 'messages[]': jobs }, + function() { + clearTimeout(loadingDelay); + window.location.reload(); + }); + } - e.preventDefault(); - }); + e.preventDefault(); + }); updateListState(); }); @@ -567,20 +610,20 @@ })(); })(window.Cap = window.Cap || {}); -$(function () { +$(function() { Cap.page = new Cap.Page(Cap.config); }); -(function () { +(function() { var json = null; - $(".openModal").click(function () { - var url = $(this).data("url"); + $(".openModal").click(function() { + const url = $(this).data("url"); $.ajax({ url: url, dataType: "json", - success: function (data) { + success: function(data) { json = data; $("#formatBtn").click(); $(".modal").modal("show"); @@ -588,25 +631,25 @@ $(function () { }); }); - $("#formatBtn").click(function () { - $('#jsonContent').JSONView(json); + $("#formatBtn").click(function() { + $("#jsonContent").JSONView(json); }); - $("#rawBtn").click(function () { - $('#jsonContent').text(JSON.stringify(json)); + $("#rawBtn").click(function() { + $("#jsonContent").text(JSON.stringify(json)); }); - $("#expandBtn").click(function () { - $('#jsonContent').JSONView('expand'); + $("#expandBtn").click(function() { + $("#jsonContent").JSONView("expand"); }); - $("#collapseBtn").click(function () { - $('#jsonContent').JSONView('collapse'); + $("#collapseBtn").click(function() { + $("#jsonContent").JSONView("collapse"); }); })(); function nodeSwitch(id) { - console.log("id:" + id); - document.cookie = "cap.node=" + escape(id) + ";"; + console.log(`id:${id}`); + document.cookie = `cap.node=${escape(id)};`; } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/DashboardMetrics.cs b/src/DotNetCore.CAP/Dashboard/DashboardMetrics.cs index cf54595..c6c4ba9 100644 --- a/src/DotNetCore.CAP/Dashboard/DashboardMetrics.cs +++ b/src/DotNetCore.CAP/Dashboard/DashboardMetrics.cs @@ -11,42 +11,6 @@ namespace DotNetCore.CAP.Dashboard { private static readonly Dictionary Metrics = new Dictionary(); - static DashboardMetrics() - { - AddMetric(ServerCount); - AddMetric(SubscriberCount); - - AddMetric(PublishedFailedCountOrNull); - AddMetric(ReceivedFailedCountOrNull); - - AddMetric(PublishedProcessingCount); - AddMetric(ReceivedProcessingCount); - - AddMetric(PublishedSucceededCount); - AddMetric(ReceivedSucceededCount); - - AddMetric(PublishedFailedCount); - AddMetric(ReceivedFailedCount); - } - - public static void AddMetric(DashboardMetric metric) - { - if (metric == null) throw new ArgumentNullException(nameof(metric)); - - lock (Metrics) - { - Metrics[metric.Name] = metric; - } - } - - public static IEnumerable GetMetrics() - { - lock (Metrics) - { - return Metrics.Values.ToList(); - } - } - public static readonly DashboardMetric ServerCount = new DashboardMetric( "servers:count", "Metrics_Servers", @@ -61,7 +25,7 @@ namespace DotNetCore.CAP.Dashboard public static readonly DashboardMetric SubscriberCount = new DashboardMetric( "retries:count", - "Metrics_Retries", + "Metrics_Retries", page => { long retryCount; @@ -91,14 +55,14 @@ namespace DotNetCore.CAP.Dashboard public static readonly DashboardMetric ReceivedFailedCountOrNull = new DashboardMetric( "received_failed:count-or-null", "Metrics_FailedJobs", - page => page.Statistics.ReceivedFailed > 0 - ? new Metric(page.Statistics.ReceivedFailed.ToString("N0")) - { - Style = MetricStyle.Danger, - Highlighted = true, - Title = string.Format(Strings.Metrics_FailedCountOrNull, page.Statistics.ReceivedFailed) - } - : null); + page => page.Statistics.ReceivedFailed > 0 + ? new Metric(page.Statistics.ReceivedFailed.ToString("N0")) + { + Style = MetricStyle.Danger, + Highlighted = true, + Title = string.Format(Strings.Metrics_FailedCountOrNull, page.Statistics.ReceivedFailed) + } + : null); //---------------------------------------------------- @@ -111,12 +75,12 @@ namespace DotNetCore.CAP.Dashboard }); public static readonly DashboardMetric ReceivedProcessingCount = new DashboardMetric( - "received_processing:count", - "Metrics_ProcessingJobs", - page => new Metric(page.Statistics.ReceivedProcessing.ToString("N0")) - { - Style = page.Statistics.ReceivedProcessing > 0 ? MetricStyle.Warning : MetricStyle.Default - }); + "received_processing:count", + "Metrics_ProcessingJobs", + page => new Metric(page.Statistics.ReceivedProcessing.ToString("N0")) + { + Style = page.Statistics.ReceivedProcessing > 0 ? MetricStyle.Warning : MetricStyle.Default + }); //---------------------------------------------------- public static readonly DashboardMetric PublishedSucceededCount = new DashboardMetric( @@ -128,12 +92,12 @@ namespace DotNetCore.CAP.Dashboard }); public static readonly DashboardMetric ReceivedSucceededCount = new DashboardMetric( - "received_succeeded:count", - "Metrics_SucceededJobs", - page => new Metric(page.Statistics.ReceivedSucceeded.ToString("N0")) - { - IntValue = page.Statistics.ReceivedSucceeded - }); + "received_succeeded:count", + "Metrics_SucceededJobs", + page => new Metric(page.Statistics.ReceivedSucceeded.ToString("N0")) + { + IntValue = page.Statistics.ReceivedSucceeded + }); //---------------------------------------------------- @@ -148,13 +112,49 @@ namespace DotNetCore.CAP.Dashboard }); public static readonly DashboardMetric ReceivedFailedCount = new DashboardMetric( - "received_failed:count", - "Metrics_FailedJobs", - page => new Metric(page.Statistics.ReceivedFailed.ToString("N0")) - { - IntValue = page.Statistics.ReceivedFailed, - Style = page.Statistics.ReceivedFailed > 0 ? MetricStyle.Danger : MetricStyle.Default, - Highlighted = page.Statistics.ReceivedFailed > 0 - }); + "received_failed:count", + "Metrics_FailedJobs", + page => new Metric(page.Statistics.ReceivedFailed.ToString("N0")) + { + IntValue = page.Statistics.ReceivedFailed, + Style = page.Statistics.ReceivedFailed > 0 ? MetricStyle.Danger : MetricStyle.Default, + Highlighted = page.Statistics.ReceivedFailed > 0 + }); + + static DashboardMetrics() + { + AddMetric(ServerCount); + AddMetric(SubscriberCount); + + AddMetric(PublishedFailedCountOrNull); + AddMetric(ReceivedFailedCountOrNull); + + AddMetric(PublishedProcessingCount); + AddMetric(ReceivedProcessingCount); + + AddMetric(PublishedSucceededCount); + AddMetric(ReceivedSucceededCount); + + AddMetric(PublishedFailedCount); + AddMetric(ReceivedFailedCount); + } + + public static void AddMetric(DashboardMetric metric) + { + if (metric == null) throw new ArgumentNullException(nameof(metric)); + + lock (Metrics) + { + Metrics[metric.Name] = metric; + } + } + + public static IEnumerable GetMetrics() + { + lock (Metrics) + { + return Metrics.Values.ToList(); + } + } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/DashboardRequest.cs b/src/DotNetCore.CAP/Dashboard/DashboardRequest.cs index 264ecdb..2499206 100644 --- a/src/DotNetCore.CAP/Dashboard/DashboardRequest.cs +++ b/src/DotNetCore.CAP/Dashboard/DashboardRequest.cs @@ -34,8 +34,11 @@ namespace DotNetCore.CAP.Dashboard public override string PathBase => _context.Request.PathBase.Value; public override string LocalIpAddress => _context.Connection.LocalIpAddress.ToString(); public override string RemoteIpAddress => _context.Connection.RemoteIpAddress.ToString(); - - public override string GetQuery(string key) => _context.Request.Query[key]; + + public override string GetQuery(string key) + { + return _context.Request.Query[key]; + } public override async Task> GetFormValuesAsync(string key) { diff --git a/src/DotNetCore.CAP/Dashboard/EmbeddedResourceDispatcher.cs b/src/DotNetCore.CAP/Dashboard/EmbeddedResourceDispatcher.cs index ea9f677..ce19de3 100644 --- a/src/DotNetCore.CAP/Dashboard/EmbeddedResourceDispatcher.cs +++ b/src/DotNetCore.CAP/Dashboard/EmbeddedResourceDispatcher.cs @@ -7,12 +7,12 @@ namespace DotNetCore.CAP.Dashboard internal class EmbeddedResourceDispatcher : IDashboardDispatcher { private readonly Assembly _assembly; - private readonly string _resourceName; private readonly string _contentType; + private readonly string _resourceName; public EmbeddedResourceDispatcher( - string contentType, - Assembly assembly, + string contentType, + Assembly assembly, string resourceName) { if (assembly != null) @@ -47,9 +47,8 @@ namespace DotNetCore.CAP.Dashboard using (var inputStream = assembly.GetManifestResourceStream(resourceName)) { if (inputStream == null) - { - throw new ArgumentException($@"Resource with name {resourceName} not found in assembly {assembly}."); - } + throw new ArgumentException( + $@"Resource with name {resourceName} not found in assembly {assembly}."); inputStream.CopyTo(response.Body); } diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/GatewayProxyMiddleware.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/GatewayProxyMiddleware.cs index 645b713..b166acd 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/GatewayProxyMiddleware.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/GatewayProxyMiddleware.cs @@ -16,20 +16,18 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy public class GatewayProxyMiddleware { public const string NodeCookieName = "cap.node"; + private readonly ILogger _logger; private readonly RequestDelegate _next; - private readonly ILogger _logger; - private readonly IRequestMapper _requestMapper; private readonly IHttpRequester _requester; + private readonly IRequestMapper _requestMapper; private INodeDiscoveryProvider _discoveryProvider; - protected HttpRequestMessage DownstreamRequest { get; set; } - public GatewayProxyMiddleware(RequestDelegate next, - ILoggerFactory loggerFactory, - IRequestMapper requestMapper, - IHttpRequester requester) + ILoggerFactory loggerFactory, + IRequestMapper requestMapper, + IHttpRequester requester) { _next = next; _logger = loggerFactory.CreateLogger(); @@ -37,6 +35,8 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy _requester = requester; } + protected HttpRequestMessage DownstreamRequest { get; set; } + public async Task Invoke(HttpContext context, DiscoveryOptions discoveryOptions, INodeDiscoveryProvider discoveryProvider) @@ -53,7 +53,7 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy else { //For performance reasons, we need to put this functionality in the else - var isSwitchNode = request.Cookies.TryGetValue(NodeCookieName, out string requestNodeId); + var isSwitchNode = request.Cookies.TryGetValue(NodeCookieName, out var requestNodeId); var isCurrentNode = discoveryOptions.NodeId.ToString() == requestNodeId; var isNodesPage = request.Path.StartsWithSegments(new PathString(pathMatch + "/nodes")); @@ -65,7 +65,7 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy { _logger.LogDebug("started calling gateway proxy middleware"); - if (TryGetRemoteNode(requestNodeId, out Node node)) + if (TryGetRemoteNode(requestNodeId, out var node)) { try { @@ -94,31 +94,26 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy public async Task SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response) { foreach (var httpResponseHeader in response.Content.Headers) - { AddHeaderIfDoesntExist(context, httpResponseHeader); - } var content = await response.Content.ReadAsByteArrayAsync(); AddHeaderIfDoesntExist(context, - new KeyValuePair>("Content-Length", new[] { content.Length.ToString() })); + new KeyValuePair>("Content-Length", new[] {content.Length.ToString()})); context.Response.OnStarting(state => { - var httpContext = (HttpContext)state; + var httpContext = (HttpContext) state; - httpContext.Response.StatusCode = (int)response.StatusCode; + httpContext.Response.StatusCode = (int) response.StatusCode; return Task.CompletedTask; - }, context); using (Stream stream = new MemoryStream(content)) { if (response.StatusCode != HttpStatusCode.NotModified) - { await stream.CopyToAsync(context.Response.Body); - } } } @@ -139,10 +134,8 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy KeyValuePair> httpResponseHeader) { if (!context.Response.Headers.ContainsKey(httpResponseHeader.Key)) - { context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Value.ToArray())); - } } } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.Default.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.Default.cs index 823b03b..90d80a9 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.Default.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.Default.cs @@ -12,14 +12,14 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy { public class RequestMapper : IRequestMapper { - private readonly string[] _unsupportedHeaders = { "host", "cookie" }; private const string SchemeDelimiter = "://"; + private readonly string[] _unsupportedHeaders = {"host", "cookie"}; public async Task Map(HttpRequest request) { try { - var requestMessage = new HttpRequestMessage() + var requestMessage = new HttpRequestMessage { Content = await MapContent(request), Method = MapMethod(request), @@ -45,11 +45,9 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy FragmentString fragment = new FragmentString()) { if (scheme == null) - { throw new ArgumentNullException(nameof(scheme)); - } - var combinedPath = (pathBase.HasValue || path.HasValue) ? (pathBase + path).ToString() : "/"; + var combinedPath = pathBase.HasValue || path.HasValue ? (pathBase + path).ToString() : "/"; var encodedHost = host.ToString(); var encodedQuery = query.ToString(); @@ -57,7 +55,7 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy // PERF: Calculate string length to allocate correct buffer size for StringBuilder. var length = scheme.Length + SchemeDelimiter.Length + encodedHost.Length - + combinedPath.Length + encodedQuery.Length + encodedFragment.Length; + + combinedPath.Length + encodedQuery.Length + encodedFragment.Length; return new StringBuilder(length) .Append(scheme) @@ -77,13 +75,11 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy private async Task MapContent(HttpRequest request) { if (request.Body == null) - { return null; - } var content = new ByteArrayContent(await ToByteArray(request.Body)); - content.Headers.TryAddWithoutValidation("Content-Type", new[] { request.ContentType }); + content.Headers.TryAddWithoutValidation("Content-Type", new[] {request.ContentType}); return content; } @@ -101,12 +97,8 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy private void MapHeaders(HttpRequest request, HttpRequestMessage requestMessage) { foreach (var header in request.Headers) - { if (IsSupportedHeader(header)) - { requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); - } - } } private async Task ToByteArray(Stream stream) diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.cs index 88752a0..ee1f994 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/IRequestMapper.cs @@ -1,9 +1,9 @@ -namespace DotNetCore.CAP.Dashboard.GatewayProxy -{ - using System.Net.Http; - using System.Threading.Tasks; - using Microsoft.AspNetCore.Http; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +namespace DotNetCore.CAP.Dashboard.GatewayProxy +{ public interface IRequestMapper { Task Map(HttpRequest request); diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientBuilder.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientBuilder.cs index e5088d8..df913b6 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientBuilder.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientBuilder.cs @@ -8,7 +8,8 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester { internal class HttpClientBuilder : IHttpClientBuilder { - private readonly Dictionary> _handlers = new Dictionary>(); + private readonly Dictionary> _handlers = + new Dictionary>(); public IHttpClient Create() { @@ -41,13 +42,13 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester /// internal class HttpClientWrapper : IHttpClient { - public HttpClient Client { get; } - public HttpClientWrapper(HttpClient client) { Client = client; } + public HttpClient Client { get; } + public Task SendAsync(HttpRequestMessage request) { return Client.SendAsync(request); diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientHttpRequester.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientHttpRequester.cs index d64cfe9..807e452 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientHttpRequester.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/HttpClientHttpRequester.cs @@ -44,15 +44,13 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester var httpClient = _cacheHandlers.Get(cacheKey); if (httpClient == null) - { httpClient = builder.Create(); - } return httpClient; } private string GetCacheKey(HttpRequestMessage request, IHttpClientBuilder builder) { - string baseUrl = $"{request.RequestUri.Scheme}://{request.RequestUri.Authority}"; + var baseUrl = $"{request.RequestUri.Scheme}://{request.RequestUri.Authority}"; return baseUrl; } diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/IHttpClientBuilder.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/IHttpClientBuilder.cs index 4f28220..3c24f6e 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/IHttpClientBuilder.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/IHttpClientBuilder.cs @@ -5,7 +5,7 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester public interface IHttpClientBuilder { /// - /// Creates the + /// Creates the /// IHttpClient Create(); } diff --git a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/MemoryHttpClientCache.cs b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/MemoryHttpClientCache.cs index 02512bc..20498ec 100644 --- a/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/MemoryHttpClientCache.cs +++ b/src/DotNetCore.CAP/Dashboard/GatewayProxy/Requester/MemoryHttpClientCache.cs @@ -5,7 +5,8 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester { public class MemoryHttpClientCache : IHttpClientCache { - private readonly ConcurrentDictionary> _httpClientsCache = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _httpClientsCache = + new ConcurrentDictionary>(); public void Set(string id, IHttpClient client, TimeSpan expirationTime) { @@ -30,9 +31,7 @@ namespace DotNetCore.CAP.Dashboard.GatewayProxy.Requester { IHttpClient client = null; if (_httpClientsCache.TryGetValue(id, out var connectionQueue)) - { connectionQueue.TryDequeue(out client); - } return client; } diff --git a/src/DotNetCore.CAP/Dashboard/HtmlHelper.cs b/src/DotNetCore.CAP/Dashboard/HtmlHelper.cs index 91bbcde..c38f1ff 100644 --- a/src/DotNetCore.CAP/Dashboard/HtmlHelper.cs +++ b/src/DotNetCore.CAP/Dashboard/HtmlHelper.cs @@ -31,9 +31,7 @@ namespace DotNetCore.CAP.Dashboard public NonEscapedString MessagesSidebar(MessageType type) { if (type == MessageType.Publish) - { return SidebarMenu(MessagesSidebarMenu.PublishedItems); - } return SidebarMenu(MessagesSidebarMenu.ReceivedItems); } @@ -80,12 +78,11 @@ namespace DotNetCore.CAP.Dashboard public NonEscapedString StateLabel(string stateName) { - if (String.IsNullOrWhiteSpace(stateName)) - { + if (string.IsNullOrWhiteSpace(stateName)) return Raw($"{Strings.Common_NoState}"); - } - return Raw($"{stateName}"); + return Raw( + $"{stateName}"); } public NonEscapedString RelativeTime(DateTime value) @@ -109,52 +106,36 @@ namespace DotNetCore.CAP.Dashboard var builder = new StringBuilder(); if (displaySign) - { builder.Append(duration.Value.TotalMilliseconds < 0 ? "-" : "+"); - } duration = duration.Value.Duration(); if (duration.Value.Days > 0) - { builder.Append($"{duration.Value.Days}d "); - } if (duration.Value.Hours > 0) - { builder.Append($"{duration.Value.Hours}h "); - } if (duration.Value.Minutes > 0) - { builder.Append($"{duration.Value.Minutes}m "); - } if (duration.Value.TotalHours < 1) - { if (duration.Value.Seconds > 0) { builder.Append(duration.Value.Seconds); if (duration.Value.Milliseconds > 0) - { builder.Append($".{duration.Value.Milliseconds.ToString().PadLeft(3, '0')}"); - } builder.Append("s "); } else { if (duration.Value.Milliseconds > 0) - { builder.Append($"{duration.Value.Milliseconds}ms "); - } } - } if (builder.Length <= 1) - { builder.Append(" <1ms "); - } builder.Remove(builder.Length - 1, 1); @@ -163,7 +144,7 @@ namespace DotNetCore.CAP.Dashboard public string FormatProperties(IDictionary properties) { - return String.Join(", ", properties.Select(x => $"{x.Key}: \"{x.Value}\"")); + return string.Join(", ", properties.Select(x => $"{x.Key}: \"{x.Value}\"")); } public NonEscapedString QueueLabel(string queue) @@ -179,7 +160,7 @@ namespace DotNetCore.CAP.Dashboard { var parts = serverId.Split(':'); var shortenedId = parts.Length > 1 - ? String.Join(":", parts.Take(parts.Length - 1)) + ? string.Join(":", parts.Take(parts.Length - 1)) : serverId; return new NonEscapedString( @@ -188,20 +169,40 @@ namespace DotNetCore.CAP.Dashboard public NonEscapedString NodeSwitchLink(string id) { - return Raw($"{Strings.NodePage_Switch}"); + return Raw( + $"{Strings.NodePage_Switch}"); + } + + public NonEscapedString StackTrace(string stackTrace) + { + try + { + //return new NonEscapedString(StackTraceFormatter.FormatHtml(stackTrace, StackTraceHtmlFragments)); + return new NonEscapedString(stackTrace); + } + catch (RegexMatchTimeoutException) + { + return new NonEscapedString(HtmlEncode(stackTrace)); + } + } + + public string HtmlEncode(string text) + { + return WebUtility.HtmlEncode(text); } #region MethodEscaped + public NonEscapedString MethodEscaped(MethodInfo method) { var @public = WrapKeyword("public"); - var @async = string.Empty; + var async = string.Empty; string @return; var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(method.ReturnType, out var coercedAwaitableInfo); if (isAwaitable) { - @async = WrapKeyword("async"); + async = WrapKeyword("async"); var asyncResultType = coercedAwaitableInfo.AwaitableInfo.ResultType; @return = WrapType("Task") + WrapIdentifier("<") + WrapType(asyncResultType) + WrapIdentifier(">"); @@ -211,7 +212,7 @@ namespace DotNetCore.CAP.Dashboard @return = WrapType(method.ReturnType); } - var @name = method.Name; + var name = method.Name; string paramType = null; string paramName = null; @@ -227,7 +228,8 @@ namespace DotNetCore.CAP.Dashboard var paramString = paramType == null ? "();" : $"({paramType} {paramName});"; - var outputString = @public + " " + (string.IsNullOrEmpty(@async) ? "" : @async + " ") + @return + " " + @name + paramString; + var outputString = @public + " " + (string.IsNullOrEmpty(async) ? "" : async + " ") + @return + " " + name + + paramString; return new NonEscapedString(outputString); } @@ -235,26 +237,15 @@ namespace DotNetCore.CAP.Dashboard private string WrapType(Type type) { if (type == null) - { return string.Empty; - } if (type.Name == "Void") - { return WrapKeyword(type.Name.ToLower()); - } if (Helper.IsComplexType(type)) - { return WrapType(type.Name); - } if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal)) - { return WrapKeyword(type.Name.ToLower()); - } - else - { - return WrapType(type.Name); - } + return WrapType(type.Name); } private string WrapIdentifier(string value) @@ -275,25 +266,8 @@ namespace DotNetCore.CAP.Dashboard private string Span(string @class, string value) { return $"{value}"; - } - #endregion - - public NonEscapedString StackTrace(string stackTrace) - { - try - { - //return new NonEscapedString(StackTraceFormatter.FormatHtml(stackTrace, StackTraceHtmlFragments)); - return new NonEscapedString(stackTrace); - } - catch (RegexMatchTimeoutException) - { - return new NonEscapedString(HtmlEncode(stackTrace)); - } } - public string HtmlEncode(string text) - { - return WebUtility.HtmlEncode(text); - } + #endregion } } \ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/JsonDispatcher.cs b/src/DotNetCore.CAP/Dashboard/JsonDispatcher.cs index 621ab19..c50109f 100644 --- a/src/DotNetCore.CAP/Dashboard/JsonDispatcher.cs +++ b/src/DotNetCore.CAP/Dashboard/JsonDispatcher.cs @@ -26,20 +26,18 @@ namespace DotNetCore.CAP.Dashboard string serialized = null; if (_command != null) { - object result = _command(context); + var result = _command(context); var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), - Converters = new JsonConverter[] { new StringEnumConverter { CamelCaseText = true } } + Converters = new JsonConverter[] {new StringEnumConverter {CamelCaseText = true}} }; serialized = JsonConvert.SerializeObject(result, settings); } if (_jsonCommand != null) - { serialized = _jsonCommand(context); - } context.Response.ContentType = "application/json"; await context.Response.WriteAsync(serialized ?? string.Empty); diff --git a/src/DotNetCore.CAP/Dashboard/JsonStats.cs b/src/DotNetCore.CAP/Dashboard/JsonStats.cs index 47b4deb..78ad871 100644 --- a/src/DotNetCore.CAP/Dashboard/JsonStats.cs +++ b/src/DotNetCore.CAP/Dashboard/JsonStats.cs @@ -27,7 +27,7 @@ namespace DotNetCore.CAP.Dashboard var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), - Converters = new JsonConverter[] { new StringEnumConverter { CamelCaseText = true } } + Converters = new JsonConverter[] {new StringEnumConverter {CamelCaseText = true}} }; var serialized = JsonConvert.SerializeObject(result, settings); diff --git a/src/DotNetCore.CAP/Dashboard/LocalRequestsOnlyAuthorizationFilter.cs b/src/DotNetCore.CAP/Dashboard/LocalRequestsOnlyAuthorizationFilter.cs index 0580a4f..4884ed2 100644 --- a/src/DotNetCore.CAP/Dashboard/LocalRequestsOnlyAuthorizationFilter.cs +++ b/src/DotNetCore.CAP/Dashboard/LocalRequestsOnlyAuthorizationFilter.cs @@ -1,13 +1,11 @@ -using System; - -namespace DotNetCore.CAP.Dashboard +namespace DotNetCore.CAP.Dashboard { public class LocalRequestsOnlyAuthorizationFilter : IDashboardAuthorizationFilter { public bool Authorize(DashboardContext context) { // if unknown, assume not local - if (String.IsNullOrEmpty(context.Request.RemoteIpAddress)) + if (string.IsNullOrEmpty(context.Request.RemoteIpAddress)) return false; // check if localhost diff --git a/src/DotNetCore.CAP/Dashboard/MenuItem.cs b/src/DotNetCore.CAP/Dashboard/MenuItem.cs index b06d5c4..3f0ea1c 100644 --- a/src/DotNetCore.CAP/Dashboard/MenuItem.cs +++ b/src/DotNetCore.CAP/Dashboard/MenuItem.cs @@ -20,12 +20,10 @@ namespace DotNetCore.CAP.Dashboard public IEnumerable GetAllMetrics() { - var metrics = new List { Metric }; + var metrics = new List {Metric}; if (Metrics != null) - { metrics.AddRange(Metrics); - } return metrics.Where(x => x != null).ToList(); } diff --git a/src/DotNetCore.CAP/Dashboard/MessageHistoryRenderer.cs b/src/DotNetCore.CAP/Dashboard/MessageHistoryRenderer.cs index 28a4ca4..990aee7 100644 --- a/src/DotNetCore.CAP/Dashboard/MessageHistoryRenderer.cs +++ b/src/DotNetCore.CAP/Dashboard/MessageHistoryRenderer.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Net; using System.Text; using DotNetCore.CAP.Infrastructure; @@ -16,7 +18,7 @@ namespace DotNetCore.CAP.Dashboard private static readonly IDictionary ForegroundStateColors = new Dictionary(); - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] + [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")] static MessageHistoryRenderer() { Register(StatusName.Succeeded, SucceededRenderer); @@ -44,9 +46,7 @@ namespace DotNetCore.CAP.Dashboard public static string GetBackgroundStateColor(string stateName) { if (stateName == null || !BackgroundStateColors.ContainsKey(stateName)) - { return "inherit"; - } return BackgroundStateColors[stateName]; } @@ -59,23 +59,18 @@ namespace DotNetCore.CAP.Dashboard public static string GetForegroundStateColor(string stateName) { if (stateName == null || !ForegroundStateColors.ContainsKey(stateName)) - { return "inherit"; - } return ForegroundStateColors[stateName]; } - public static void Register(string state, Func, NonEscapedString> renderer) + public static void Register(string state, + Func, NonEscapedString> renderer) { if (!Renderers.ContainsKey(state)) - { Renderers.Add(state, renderer); - } else - { Renderers[state] = renderer; - } } public static bool Exists(string state) @@ -141,10 +136,10 @@ namespace DotNetCore.CAP.Dashboard itemsAdded = true; } - if (stateData.ContainsKey("Result") && !String.IsNullOrWhiteSpace(stateData["Result"])) + if (stateData.ContainsKey("Result") && !string.IsNullOrWhiteSpace(stateData["Result"])) { var result = stateData["Result"]; - builder.Append($"
Result:
{System.Net.WebUtility.HtmlEncode(result)}
"); + builder.Append($"
Result:
{WebUtility.HtmlEncode(result)}
"); itemsAdded = true; } @@ -171,13 +166,9 @@ namespace DotNetCore.CAP.Dashboard string serverId = null; if (stateData.ContainsKey("ServerId")) - { serverId = stateData["ServerId"]; - } else if (stateData.ContainsKey("ServerName")) - { serverId = stateData["ServerName"]; - } if (serverId != null) { diff --git a/src/DotNetCore.CAP/Dashboard/MessagesSidebarMenu.cs b/src/DotNetCore.CAP/Dashboard/MessagesSidebarMenu.cs index 0157241..0d68f5d 100644 --- a/src/DotNetCore.CAP/Dashboard/MessagesSidebarMenu.cs +++ b/src/DotNetCore.CAP/Dashboard/MessagesSidebarMenu.cs @@ -20,11 +20,12 @@ namespace DotNetCore.CAP.Dashboard Metric = DashboardMetrics.PublishedSucceededCount }); - PublishedItems.Add(page => new MenuItem(Strings.SidebarMenu_Processing, page.Url.To("/published/processing")) - { - Active = page.RequestPath.StartsWith("/published/processing"), - Metric = DashboardMetrics.PublishedProcessingCount - }); + PublishedItems.Add(page => + new MenuItem(Strings.SidebarMenu_Processing, page.Url.To("/published/processing")) + { + Active = page.RequestPath.StartsWith("/published/processing"), + Metric = DashboardMetrics.PublishedProcessingCount + }); PublishedItems.Add(page => new MenuItem(Strings.SidebarMenu_Failed, page.Url.To("/published/failed")) { diff --git a/src/DotNetCore.CAP/Dashboard/Metric.cs b/src/DotNetCore.CAP/Dashboard/Metric.cs index d8108fa..fafa537 100644 --- a/src/DotNetCore.CAP/Dashboard/Metric.cs +++ b/src/DotNetCore.CAP/Dashboard/Metric.cs @@ -20,7 +20,7 @@ Info, Success, Warning, - Danger, + Danger } internal static class MetricStyleExtensions diff --git a/src/DotNetCore.CAP/Dashboard/Pager.cs b/src/DotNetCore.CAP/Dashboard/Pager.cs index 7476f36..8962ff0 100644 --- a/src/DotNetCore.CAP/Dashboard/Pager.cs +++ b/src/DotNetCore.CAP/Dashboard/Pager.cs @@ -7,9 +7,9 @@ namespace DotNetCore.CAP.Dashboard { private const int PageItemsCount = 7; private const int DefaultRecordsPerPage = 10; + private int _endPageIndex = 1; private int _startPageIndex = 1; - private int _endPageIndex = 1; public Pager(int from, int perPage, long total) { @@ -17,7 +17,7 @@ namespace DotNetCore.CAP.Dashboard RecordsPerPage = perPage > 0 ? perPage : DefaultRecordsPerPage; TotalRecordCount = total; CurrentPage = FromRecord / RecordsPerPage + 1; - TotalPageCount = (int)Math.Ceiling((double)TotalRecordCount / RecordsPerPage); + TotalPageCount = (int) Math.Ceiling((double) TotalRecordCount / RecordsPerPage); PagerItems = GenerateItems(); } @@ -110,7 +110,7 @@ namespace DotNetCore.CAP.Dashboard if (_endPageIndex < TotalPageCount - 1) { var index = _startPageIndex + PageItemsCount; - if (index > TotalPageCount) { index = TotalPageCount; } + if (index > TotalPageCount) index = TotalPageCount; var item = new Item(index, false, ItemType.MorePage); results.Add(item); } diff --git a/src/DotNetCore.CAP/Dashboard/Pages/HomePage.cshtml b/src/DotNetCore.CAP/Dashboard/Pages/HomePage.cshtml index bb77537..a416980 100644 --- a/src/DotNetCore.CAP/Dashboard/Pages/HomePage.cshtml +++ b/src/DotNetCore.CAP/Dashboard/Pages/HomePage.cshtml @@ -1,21 +1,18 @@ @* Generator: Template TypeVisibility: Internal GeneratePrettyNames: True *@ -@using System -@using System.Collections.Generic -@using DotNetCore.CAP.Models; -@using DotNetCore.CAP.Dashboard @using DotNetCore.CAP.Dashboard.Pages @using DotNetCore.CAP.Dashboard.Resources +@using DotNetCore.CAP.Models @using Newtonsoft.Json -@inherits RazorPage +@inherits DotNetCore.CAP.Dashboard.RazorPage @{ Layout = new LayoutPage(Strings.HomePage_Title); var monitor = Storage.GetMonitoringApi(); - IDictionary publishedSucceeded = monitor.HourlySucceededJobs(MessageType.Publish); - IDictionary publishedFailed = monitor.HourlyFailedJobs(MessageType.Publish); + var publishedSucceeded = monitor.HourlySucceededJobs(MessageType.Publish); + var publishedFailed = monitor.HourlyFailedJobs(MessageType.Publish); - IDictionary receivedSucceeded = monitor.HourlySucceededJobs(MessageType.Subscribe); - IDictionary receivedFailed = monitor.HourlyFailedJobs(MessageType.Subscribe); + var receivedSucceeded = monitor.HourlySucceededJobs(MessageType.Subscribe); + var receivedFailed = monitor.HourlyFailedJobs(MessageType.Subscribe); }
@@ -41,7 +38,8 @@ data-received-succeeded="@Statistics.ReceivedSucceeded" data-received-failed="@Statistics.ReceivedFailed" data-received-succeeded-string="@Strings.HomePage_GraphHover_RSucceeded" - data-received-failed-string="@Strings.HomePage_GraphHover_RFailed">
+ data-received-failed-string="@Strings.HomePage_GraphHover_RFailed"> +
@@ -61,7 +59,7 @@ data-received-succeeded="@JsonConvert.SerializeObject(receivedSucceeded)" data-received-failed="@JsonConvert.SerializeObject(receivedFailed)" data-received-succeeded-string="@Strings.HomePage_GraphHover_RSucceeded" - data-received-failed-string="@Strings.HomePage_GraphHover_RFailed"> + data-received-failed-string="@Strings.HomePage_GraphHover_RFailed">
\ No newline at end of file diff --git a/src/DotNetCore.CAP/Dashboard/Pages/LayoutPage.cshtml b/src/DotNetCore.CAP/Dashboard/Pages/LayoutPage.cshtml index 2c2961c..ed8044b 100644 --- a/src/DotNetCore.CAP/Dashboard/Pages/LayoutPage.cshtml +++ b/src/DotNetCore.CAP/Dashboard/Pages/LayoutPage.cshtml @@ -2,10 +2,9 @@ @using System @using System.Globalization @using System.Reflection -@using DotNetCore.CAP.Dashboard @using DotNetCore.CAP.Dashboard.Pages @using DotNetCore.CAP.Dashboard.Resources -@inherits RazorPage +@inherits DotNetCore.CAP.Dashboard.RazorPage @@ -16,63 +15,65 @@ @{ var version = GetType().GetTypeInfo().Assembly.GetName().Version; } - - -
+ + +
- -