Unverified Commit fb6943e8 authored by Savorboard's avatar Savorboard Committed by GitHub

release 2.4.2 (#272)

* update version to 2.4.0

* Add version options to config file.

* update resource

* add  message version support  for dashboard

* add  message version support  for dashboard

* Support using version to isolate messages. #220

* update mongo unit tests

* update unit tests

* update unit tests

* Set default versions for consumer groups

* solve the problem of issue#181 (#237)

* Issue#235 (#238)

* solve the problem of issue#181

* solve the problem of issue#235

* refactor

* Fix the message persistence bug. #240

* using new CamelCaseNamingStrategy

* update packages to .net core 2.2

* update test framework to netcoreapp2.2

* Update .travis.yml

* update TargetFramework

* Exclude build samples project

* update version to 2.4.1

* add samples project to sln for build

* update version to 2.4.2

* Fixed PostgreSql version isolation feature bug. (#256)

* Fixed spelling errors

* modify cap publish Message to rabbitmq slow (#261)

* Startup the CAP with the BackgroundService.  #265

* update samples

* Fixed SQL query bug. #266

* update travis ci config

* update travis ci config

* adjust dashboard table column width

* adjust the consumer execution time to milliseconds
parent 94e54c21
language: csharp language: csharp
sudo: required sudo: required
dist: trusty dist: xenial
solution: CAP.sln solution: CAP.sln
dotnet: 2.2.100 dotnet: 2.2
mono: none mono: none
matrix: #matrix:
include: # include:
- os: linux # - dotnet: 2.2
dist: trusty # Ubuntu 14.04 # - os: linux
sudo: required # dist: trusty # Ubuntu 14.04
- os: osx # sudo: required
osx_image: xcode8.3 # macOS 10.12 # - os: osx
# osx_image: xcode8.3 # macOS 10.12
# Run the build script # Run the build script
script: script:
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<VersionMajor>2</VersionMajor> <VersionMajor>2</VersionMajor>
<VersionMinor>4</VersionMinor> <VersionMinor>4</VersionMinor>
<VersionPatch>1</VersionPatch> <VersionPatch>2</VersionPatch>
<VersionQuality></VersionQuality> <VersionQuality></VersionQuality>
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix> <VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
</PropertyGroup> </PropertyGroup>
......
...@@ -22,7 +22,7 @@ namespace Sample.RabbitMQ.MongoDB.Controllers ...@@ -22,7 +22,7 @@ namespace Sample.RabbitMQ.MongoDB.Controllers
[Route("~/without/transaction")] [Route("~/without/transaction")]
public IActionResult WithoutTransaction() public IActionResult WithoutTransaction()
{ {
_capBus.Publish("sample.rabbitmq.mongodb", DateTime.Now); _capBus.PublishAsync("sample.rabbitmq.mongodb", DateTime.Now);
return Ok(); return Ok();
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.App" />
......
using Microsoft.AspNetCore.Builder; using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
...@@ -18,14 +19,14 @@ namespace Sample.RabbitMQ.MongoDB ...@@ -18,14 +19,14 @@ namespace Sample.RabbitMQ.MongoDB
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddSingleton<IMongoClient>(new MongoClient("mongodb://192.168.10.110:27017,192.168.10.110:27018,192.168.10.110:27019/?replicaSet=rs0")); services.AddSingleton<IMongoClient>(new MongoClient(Configuration.GetConnectionString("MongoDB")));
services.AddCap(x => services.AddCap(x =>
{ {
x.UseMongoDB("mongodb://192.168.10.110:27017,192.168.10.110:27018,192.168.10.110:27019/?replicaSet=rs0"); x.UseMongoDB(Configuration.GetConnectionString("MongoDB"));
x.UseRabbitMQ("localhost"); x.UseRabbitMQ("192.168.2.120");
x.UseDashboard(); x.UseDashboard();
}); });
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
} }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) public void Configure(IApplicationBuilder app, IHostingEnvironment env)
......
{ {
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Warning" "Default": "Debug"
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"MongoDB": "mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=rs0" "MongoDB": "mongodb://192.168.2.120:27017,192.168.2.120:27018,192.168.2.120:27019/?replicaSet=rs0"
}, },
"RabbitMQ": { "RabbitMQ": {
"HostName": "localhost", "HostName": "localhost",
......
...@@ -80,7 +80,7 @@ select count(Id) from `{0}.received` where StatusName = N'Failed';", _prefix); ...@@ -80,7 +80,7 @@ select count(Id) from `{0}.received` where StatusName = N'Failed';", _prefix);
if (!string.IsNullOrEmpty(queryDto.Group)) if (!string.IsNullOrEmpty(queryDto.Group))
{ {
where += " and Group=@Group"; where += " and `Group`=@Group";
} }
if (!string.IsNullOrEmpty(queryDto.Content)) if (!string.IsNullOrEmpty(queryDto.Content))
......
...@@ -55,7 +55,7 @@ namespace DotNetCore.CAP.PostgreSql ...@@ -55,7 +55,7 @@ namespace DotNetCore.CAP.PostgreSql
private string PrepareSql() private string PrepareSql()
{ {
return return
$"INSERT INTO \"{_options.Schema}\".\"published\" (\"Id\",\"Version\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Id,@Version,@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);"; $"INSERT INTO \"{_options.Schema}\".\"published\" (\"Id\",\"Version\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")VALUES(@Id,'{_options.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";
} }
private IDbConnection InitDbConnection() private IDbConnection InitDbConnection()
......
...@@ -81,7 +81,7 @@ select count(Id) from [{0}].Received with (nolock) where StatusName = N'Failed'; ...@@ -81,7 +81,7 @@ select count(Id) from [{0}].Received with (nolock) where StatusName = N'Failed';
if (!string.IsNullOrEmpty(queryDto.Group)) if (!string.IsNullOrEmpty(queryDto.Group))
{ {
where += " and group=@Group"; where += " and [group]=@Group";
} }
if (!string.IsNullOrEmpty(queryDto.Content)) if (!string.IsNullOrEmpty(queryDto.Content))
......
...@@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Builder ...@@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Builder
/// </summary> /// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> instance this method extends.</param> /// <param name="app">The <see cref="IApplicationBuilder" /> instance this method extends.</param>
/// <returns>The <see cref="IApplicationBuilder" /> instance this method extends.</returns> /// <returns>The <see cref="IApplicationBuilder" /> instance this method extends.</returns>
public static IApplicationBuilder UseCap(this IApplicationBuilder app) public static IApplicationBuilder UseCapDashboard(this IApplicationBuilder app)
{ {
if (app == null) if (app == null)
{ {
...@@ -31,9 +31,6 @@ namespace Microsoft.AspNetCore.Builder ...@@ -31,9 +31,6 @@ namespace Microsoft.AspNetCore.Builder
var provider = app.ApplicationServices; var provider = app.ApplicationServices;
var bootstrapper = provider.GetRequiredService<IBootstrapper>();
bootstrapper.BootstrapAsync();
if (provider.GetService<DashboardOptions>() != null) if (provider.GetService<DashboardOptions>() != null)
{ {
if (provider.GetService<DiscoveryOptions>() != null) if (provider.GetService<DiscoveryOptions>() != null)
...@@ -78,7 +75,7 @@ namespace Microsoft.AspNetCore.Builder ...@@ -78,7 +75,7 @@ namespace Microsoft.AspNetCore.Builder
{ {
return app => return app =>
{ {
app.UseCap(); app.UseCapDashboard();
next(app); next(app);
}; };
......
...@@ -11,6 +11,7 @@ using DotNetCore.CAP.Processor.States; ...@@ -11,6 +11,7 @@ using DotNetCore.CAP.Processor.States;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
...@@ -48,10 +49,9 @@ namespace Microsoft.Extensions.DependencyInjection ...@@ -48,10 +49,9 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddSingleton<IConsumerInvokerFactory, ConsumerInvokerFactory>(); services.TryAddSingleton<IConsumerInvokerFactory, ConsumerInvokerFactory>();
services.TryAddSingleton<MethodMatcherCache>(); services.TryAddSingleton<MethodMatcherCache>();
//Bootstrapper and Processors //Processors
services.TryAddEnumerable(ServiceDescriptor.Singleton<IProcessingServer, ConsumerHandler>()); services.TryAddEnumerable(ServiceDescriptor.Singleton<IProcessingServer, ConsumerHandler>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IProcessingServer, CapProcessingServer>()); services.TryAddEnumerable(ServiceDescriptor.Singleton<IProcessingServer, CapProcessingServer>());
services.TryAddSingleton<IBootstrapper, DefaultBootstrapper>();
services.TryAddSingleton<IStateChanger, StateChanger>(); services.TryAddSingleton<IStateChanger, StateChanger>();
//Queue's message processor //Queue's message processor
...@@ -72,6 +72,7 @@ namespace Microsoft.Extensions.DependencyInjection ...@@ -72,6 +72,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton(options); services.AddSingleton(options);
//Startup and Middleware //Startup and Middleware
services.AddTransient<IHostedService, DefaultBootstrapper>();
services.AddTransient<IStartupFilter, CapStartupFilter>(); services.AddTransient<IStartupFilter, CapStartupFilter>();
return new CapBuilder(services); return new CapBuilder(services);
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th style="width: 60px;"> <th style="width: 30px;">
<input type="checkbox" class="js-jobs-list-select-all"/> <input type="checkbox" class="js-jobs-list-select-all"/>
</th> </th>
<th>@Strings.Common_Id</th> <th>@Strings.Common_Id</th>
......
...@@ -264,7 +264,7 @@ namespace DotNetCore.CAP.Dashboard.Pages ...@@ -264,7 +264,7 @@ namespace DotNetCore.CAP.Dashboard.Pages
<table class=""table""> <table class=""table"">
<thead> <thead>
<tr> <tr>
<th style=""width:60px;""> <th style=""width:30px;"">
<input type=""checkbox"" class=""js-jobs-list-select-all"" /> <input type=""checkbox"" class=""js-jobs-list-select-all"" />
</th> </th>
<th style=""width:22%;"">"); <th style=""width:22%;"">");
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th style="width: 60px;"> <th style="width: 30px;">
<input type="checkbox" class="js-jobs-list-select-all"/> <input type="checkbox" class="js-jobs-list-select-all"/>
</th> </th>
<th>@Strings.Common_Id</th> <th>@Strings.Common_Id</th>
......
...@@ -289,7 +289,7 @@ namespace DotNetCore.CAP.Dashboard.Pages ...@@ -289,7 +289,7 @@ namespace DotNetCore.CAP.Dashboard.Pages
<table class=""table""> <table class=""table"">
<thead> <thead>
<tr> <tr>
<th style=""width:60px;""> <th style=""width:30px;"">
<input type=""checkbox"" class=""js-jobs-list-select-all"" /> <input type=""checkbox"" class=""js-jobs-list-select-all"" />
</th> </th>
<th>"); <th>");
......
...@@ -5,87 +5,57 @@ using System; ...@@ -5,87 +5,57 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace DotNetCore.CAP namespace DotNetCore.CAP
{ {
/// <inheritdoc />
/// <summary> /// <summary>
/// Default implement of <see cref="T:DotNetCore.CAP.IBootstrapper" />. /// Default implement of <see cref="T:DotNetCore.CAP.IBootstrapper" />.
/// </summary> /// </summary>
internal class DefaultBootstrapper : IBootstrapper internal class DefaultBootstrapper : BackgroundService, IBootstrapper
{ {
private readonly IApplicationLifetime _appLifetime;
private readonly CancellationTokenSource _cts;
private readonly CancellationTokenRegistration _ctsRegistration;
private readonly ILogger<DefaultBootstrapper> _logger; private readonly ILogger<DefaultBootstrapper> _logger;
private Task _bootstrappingTask;
public DefaultBootstrapper( public DefaultBootstrapper(
ILogger<DefaultBootstrapper> logger, ILogger<DefaultBootstrapper> logger,
IStorage storage, IStorage storage,
IApplicationLifetime appLifetime,
IEnumerable<IProcessingServer> processors) IEnumerable<IProcessingServer> processors)
{ {
_logger = logger; _logger = logger;
_appLifetime = appLifetime;
Storage = storage; Storage = storage;
Processors = processors; Processors = processors;
_cts = new CancellationTokenSource();
_ctsRegistration = appLifetime.ApplicationStopping.Register(() =>
{
_cts.Cancel();
try
{
_bootstrappingTask?.GetAwaiter().GetResult();
}
catch (OperationCanceledException ex)
{
_logger.ExpectedOperationCanceledException(ex);
}
});
} }
private IStorage Storage { get; } private IStorage Storage { get; }
private IEnumerable<IProcessingServer> Processors { get; } private IEnumerable<IProcessingServer> Processors { get; }
public Task BootstrapAsync() public async Task BootstrapAsync(CancellationToken stoppingToken)
{ {
return _bootstrappingTask = BootstrapTaskAsync(); _logger.LogDebug("### CAP background task is starting.");
}
private async Task BootstrapTaskAsync() await Storage.InitializeAsync(stoppingToken);
{
_logger.LogInformation("### CAP starting...");
await Storage.InitializeAsync(_cts.Token);
if (_cts.IsCancellationRequested) stoppingToken.Register(() =>
{ {
return; _logger.LogDebug("### CAP background task is stopping.");
}
_appLifetime.ApplicationStopping.Register(() =>
{
foreach (var item in Processors) foreach (var item in Processors)
{
try
{ {
item.Dispose(); item.Dispose();
} }
}); catch (OperationCanceledException ex)
if (_cts.IsCancellationRequested)
{ {
return; _logger.ExpectedOperationCanceledException(ex);
} }
}
});
await BootstrapCoreAsync(); await BootstrapCoreAsync();
_ctsRegistration.Dispose();
_cts.Dispose();
_logger.LogInformation("### CAP started!"); _logger.LogInformation("### CAP started!");
} }
...@@ -105,5 +75,10 @@ namespace DotNetCore.CAP ...@@ -105,5 +75,10 @@ namespace DotNetCore.CAP
return Task.CompletedTask; return Task.CompletedTask;
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await BootstrapAsync(stoppingToken);
}
} }
} }
\ No newline at end of file
// Copyright (c) .NET Core Community. All rights reserved. // Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information. // Licensed under the MIT License. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace DotNetCore.CAP namespace DotNetCore.CAP
...@@ -10,6 +11,6 @@ namespace DotNetCore.CAP ...@@ -10,6 +11,6 @@ namespace DotNetCore.CAP
/// </summary> /// </summary>
public interface IBootstrapper public interface IBootstrapper
{ {
Task BootstrapAsync(); Task BootstrapAsync(CancellationToken stoppingToken);
} }
} }
\ No newline at end of file
...@@ -43,6 +43,8 @@ namespace DotNetCore.CAP ...@@ -43,6 +43,8 @@ namespace DotNetCore.CAP
public abstract Task<OperateResult> PublishAsync(string keyName, string content); public abstract Task<OperateResult> PublishAsync(string keyName, string content);
public async Task<OperateResult> SendAsync(CapPublishedMessage message) public async Task<OperateResult> SendAsync(CapPublishedMessage message)
{
return await Task.Run(async () =>
{ {
bool retry; bool retry;
OperateResult result; OperateResult result;
...@@ -58,6 +60,7 @@ namespace DotNetCore.CAP ...@@ -58,6 +60,7 @@ namespace DotNetCore.CAP
} while (retry); } while (retry);
return result; return result;
});
} }
private async Task<(bool, OperateResult)> SendWithoutRetryAsync(CapPublishedMessage message) private async Task<(bool, OperateResult)> SendWithoutRetryAsync(CapPublishedMessage message)
......
...@@ -89,7 +89,7 @@ namespace DotNetCore.CAP ...@@ -89,7 +89,7 @@ namespace DotNetCore.CAP
await SetSuccessfulState(message); await SetSuccessfulState(message);
_logger.ConsumerExecuted(sp.Elapsed.TotalSeconds); _logger.ConsumerExecuted(sp.Elapsed.TotalMilliseconds);
return (false, OperateResult.Success); return (false, OperateResult.Success);
} }
...@@ -161,7 +161,7 @@ namespace DotNetCore.CAP ...@@ -161,7 +161,7 @@ namespace DotNetCore.CAP
private async Task InvokeConsumerMethodAsync(CapReceivedMessage receivedMessage) private async Task InvokeConsumerMethodAsync(CapReceivedMessage receivedMessage)
{ {
if (!_selector.TryGetTopicExector(receivedMessage.Name, receivedMessage.Group, if (!_selector.TryGetTopicExecutor(receivedMessage.Name, receivedMessage.Group,
out var executor)) out var executor))
{ {
var error = $"Message can not be found subscriber. {receivedMessage} \r\n see: https://github.com/dotnetcore/CAP/issues/63"; var error = $"Message can not be found subscriber. {receivedMessage} \r\n see: https://github.com/dotnetcore/CAP/issues/63";
......
...@@ -45,9 +45,9 @@ namespace DotNetCore.CAP ...@@ -45,9 +45,9 @@ namespace DotNetCore.CAP
logger.LogError(ex, $"An exception occured while publishing a message, reason:{reason}. message id:{messageId}"); logger.LogError(ex, $"An exception occured while publishing a message, reason:{reason}. message id:{messageId}");
} }
public static void ConsumerExecuted(this ILogger logger, double seconds) public static void ConsumerExecuted(this ILogger logger, double milliseconds)
{ {
logger.LogDebug($"Consumer executed. Took: {seconds} secs."); logger.LogDebug($"Consumer executed. Took: {milliseconds} ms.");
} }
public static void ServerStarting(this ILogger logger) public static void ServerStarting(this ILogger logger)
......
...@@ -44,14 +44,14 @@ namespace DotNetCore.CAP.Internal ...@@ -44,14 +44,14 @@ namespace DotNetCore.CAP.Internal
} }
/// <summary> /// <summary>
/// Attempts to get the topic exector associated with the specified topic name and group name from the /// Attempts to get the topic executor associated with the specified topic name and group name from the
/// <see cref="Entries" />. /// <see cref="Entries" />.
/// </summary> /// </summary>
/// <param name="topicName">The topic name of the value to get.</param> /// <param name="topicName">The topic name of the value to get.</param>
/// <param name="groupName">The group name of the value to get.</param> /// <param name="groupName">The group name of the value to get.</param>
/// <param name="matchTopic">topic exector of the value.</param> /// <param name="matchTopic">topic executor of the value.</param>
/// <returns>true if the key was found, otherwise false. </returns> /// <returns>true if the key was found, otherwise false. </returns>
public bool TryGetTopicExector(string topicName, string groupName, public bool TryGetTopicExecutor(string topicName, string groupName,
out ConsumerExecutorDescriptor matchTopic) out ConsumerExecutorDescriptor matchTopic)
{ {
if (Entries == null) if (Entries == null)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment