Browse Source

dispose response of HttpClient #6534

pull/6693/head
Alper Ebicoglu 6 years ago
parent
commit
0a47340528
  1. 1
      docs/en/CLI.md
  2. 28
      docs/en/UI/AspNetCore/Data-Tables.md
  3. 1
      docs/zh-Hans/CLI.md
  4. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  5. 4
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
  6. 2
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs
  7. 25
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs
  8. 6
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs
  9. 2
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
  10. 22
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
  11. 94
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs
  12. 12
      framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs
  13. 51
      framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs
  14. 127
      framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs
  15. 2
      framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs
  16. 4
      framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs
  17. 987
      modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.Designer.cs
  18. 24
      modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.cs
  19. 5
      modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs
  20. 2
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs
  21. 4
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs
  22. 5
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs
  23. 13
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/DocumentAuthor.cs
  24. 31
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs
  25. 2
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  26. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs

1
docs/en/CLI.md

@ -129,6 +129,7 @@ abp update [options]
* `--solution-path` or `-sp`: Specify the solution path. Use the current directory by default * `--solution-path` or `-sp`: Specify the solution path. Use the current directory by default
* `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default. * `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default.
* `--check-all`: Check the new version of each package separately. Default is `false`. * `--check-all`: Check the new version of each package separately. Default is `false`.
* `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used.
### add-package ### add-package

28
docs/en/UI/AspNetCore/Data-Tables.md

@ -105,6 +105,32 @@ The `abp.libs.datatables.createAjax` method (used in the example above) adapts r
This works automatically, so most of the times you don't need to know how it works. See the [DTO document](../../Data-Transfer-Objects.md) if you want to learn more about `IPagedAndSortedResultRequest`, `IPagedResult` and other standard interfaces and base DTO classes those are used in client to server communication. This works automatically, so most of the times you don't need to know how it works. See the [DTO document](../../Data-Transfer-Objects.md) if you want to learn more about `IPagedAndSortedResultRequest`, `IPagedResult` and other standard interfaces and base DTO classes those are used in client to server communication.
The `createAjax` also supports you to customize request parameters and handle the responses.
**Example:**
````csharp
var inputAction = function () {
return {
id: $('#Id').val(),
name: $('#Name').val(),
};
};
var responseCallback = function(result) {
// your custom code.
return {
recordsTotal: result.totalCount,
recordsFiltered: result.totalCount,
data: result.items
};
};
ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList, inputAction, responseCallback)
````
### Row Actions ### Row Actions
`rowAction` is an option defined by the ABP Framework to the column definitions to show a drop down button to take actions for a row in the table. `rowAction` is an option defined by the ABP Framework to the column definitions to show a drop down button to take actions for a row in the table.
@ -260,4 +286,4 @@ Assuming that the possible values for a column data is `f` and `m`, the `gender`
## Other Data Grids ## Other Data Grids
You can use any library you like. For example, [see this article](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) to learn how to use DevExtreme Data Grid in your applications. You can use any library you like. For example, [see this article](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) to learn how to use DevExtreme Data Grid in your applications.

1
docs/zh-Hans/CLI.md

@ -126,6 +126,7 @@ abp update [options]
* `--solution-path` 或 `-sp`: 指定解决方案路径/目录. 默认使用当前目录 * `--solution-path` 或 `-sp`: 指定解决方案路径/目录. 默认使用当前目录
* `--solution-name` 或 `-sn`: 指定解决方案名称. 默认在目录中搜索`*.sln`文件. * `--solution-name` 或 `-sn`: 指定解决方案名称. 默认在目录中搜索`*.sln`文件.
* `--check-all`: 分别检查每个包的新版本. 默认是 `false`. * `--check-all`: 分别检查每个包的新版本. 默认是 `false`.
* `--version` or `-v`: 指定用于升级的版本. 如果没有指定,则使用最新版本.
### add-package ### add-package

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -325,7 +325,14 @@
* AJAX extension for datatables * * AJAX extension for datatables *
*************************************************************************/ *************************************************************************/
(function () { (function () {
datatables.createAjax = function (serverMethod, inputAction) { datatables.createAjax = function (serverMethod, inputAction, responseCallback) {
responseCallback = responseCallback || function(result) {
return {
recordsTotal: result.totalCount,
recordsFiltered: result.totalCount,
data: result.items
};
}
return function (requestData, callback, settings) { return function (requestData, callback, settings) {
var input = inputAction ? inputAction(requestData, settings) : {}; var input = inputAction ? inputAction(requestData, settings) : {};
@ -359,11 +366,7 @@
if (callback) { if (callback) {
serverMethod(input).then(function (result) { serverMethod(input).then(function (result) {
callback({ callback(responseCallback(result));
recordsTotal: result.totalCount,
recordsFiltered: result.totalCount,
data: result.items
});
}); });
} }
}; };

4
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.BackgroundJobs
protected AbpBackgroundJobWorkerOptions WorkerOptions { get; } protected AbpBackgroundJobWorkerOptions WorkerOptions { get; }
public BackgroundJobWorker( public BackgroundJobWorker(
AbpTimer timer, AbpAsyncTimer timer,
IOptions<AbpBackgroundJobOptions> jobOptions, IOptions<AbpBackgroundJobOptions> jobOptions,
IOptions<AbpBackgroundJobWorkerOptions> workerOptions, IOptions<AbpBackgroundJobWorkerOptions> workerOptions,
IServiceScopeFactory serviceScopeFactory) IServiceScopeFactory serviceScopeFactory)
@ -113,4 +113,4 @@ namespace Volo.Abp.BackgroundJobs
return nextTryDate; return nextTryDate;
} }
} }
} }

2
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs

@ -34,7 +34,7 @@ namespace Volo.Abp.BackgroundWorkers.Quartz
throw new ArgumentException($"{nameof(worker)} type is different from the generic type"); throw new ArgumentException($"{nameof(worker)} type is different from the generic type");
} }
var timer = (AbpTimer) worker.GetType().GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker); var timer = (AbpAsyncTimer) worker.GetType().GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);
period = timer?.Period; period = timer?.Period;
} }
else else

25
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AsyncPeriodicBackgroundWorkerBase.cs

@ -11,15 +11,15 @@ namespace Volo.Abp.BackgroundWorkers
public abstract class AsyncPeriodicBackgroundWorkerBase : BackgroundWorkerBase public abstract class AsyncPeriodicBackgroundWorkerBase : BackgroundWorkerBase
{ {
protected IServiceScopeFactory ServiceScopeFactory { get; } protected IServiceScopeFactory ServiceScopeFactory { get; }
protected AbpTimer Timer { get; } protected AbpAsyncTimer Timer { get; }
protected AsyncPeriodicBackgroundWorkerBase( protected AsyncPeriodicBackgroundWorkerBase(
AbpTimer timer, AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory) IServiceScopeFactory serviceScopeFactory)
{ {
ServiceScopeFactory = serviceScopeFactory; ServiceScopeFactory = serviceScopeFactory;
Timer = timer; Timer = timer;
Timer.Elapsed += Timer_Elapsed; Timer.Elapsed = Timer_Elapsed;
} }
public async override Task StartAsync(CancellationToken cancellationToken = default) public async override Task StartAsync(CancellationToken cancellationToken = default)
@ -34,23 +34,24 @@ namespace Volo.Abp.BackgroundWorkers
await base.StopAsync(cancellationToken); await base.StopAsync(cancellationToken);
} }
private void Timer_Elapsed(object sender, System.EventArgs e) private async Task Timer_Elapsed(AbpAsyncTimer timer)
{
await DoWorkAsync();
}
private async Task DoWorkAsync()
{ {
using (var scope = ServiceScopeFactory.CreateScope()) using (var scope = ServiceScopeFactory.CreateScope())
{ {
try try
{ {
AsyncHelper.RunSync( await DoWorkAsync(new PeriodicBackgroundWorkerContext(scope.ServiceProvider));
() => DoWorkAsync(new PeriodicBackgroundWorkerContext(scope.ServiceProvider))
);
} }
catch (Exception ex) catch (Exception ex)
{ {
AsyncHelper.RunSync( await scope.ServiceProvider
() => scope.ServiceProvider .GetRequiredService<IExceptionNotifier>()
.GetRequiredService<IExceptionNotifier>() .NotifyAsync(new ExceptionNotificationContext(ex));
.NotifyAsync(new ExceptionNotificationContext(ex))
);
Logger.LogException(ex); Logger.LogException(ex);
} }

6
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/PeriodicBackgroundWorkerBase.cs

@ -43,14 +43,12 @@ namespace Volo.Abp.BackgroundWorkers
{ {
try try
{ {
DoWork(new PeriodicBackgroundWorkerContext(scope.ServiceProvider)); DoWork(new PeriodicBackgroundWorkerContext(scope.ServiceProvider));
} }
catch (Exception ex) catch (Exception ex)
{ {
scope.ServiceProvider var exceptionNotifier = scope.ServiceProvider.GetRequiredService<IExceptionNotifier>();
.GetRequiredService<IExceptionNotifier>() AsyncHelper.RunSync(() => exceptionNotifier.NotifyAsync(new ExceptionNotificationContext(ex)));
.NotifyAsync(new ExceptionNotificationContext(ex));
Logger.LogException(ex); Logger.LogException(ex);
} }

2
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs

@ -1029,7 +1029,7 @@ namespace Volo.Abp.Caching
protected virtual void HandleException(Exception ex) protected virtual void HandleException(Exception ex)
{ {
AsyncHelper.RunSync(() => HandleExceptionAsync(ex)); _ = HandleExceptionAsync(ex);
} }
protected virtual async Task HandleExceptionAsync(Exception ex) protected virtual async Task HandleExceptionAsync(Exception ex)

22
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs

@ -34,24 +34,25 @@ namespace Volo.Abp.Cli.Commands
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ?? var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ??
Directory.GetCurrentDirectory(); Directory.GetCurrentDirectory();
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
if (updateNuget || !updateNpm) if (updateNuget || !updateNpm)
{ {
await UpdateNugetPackages(commandLineArgs, directory); await UpdateNugetPackages(commandLineArgs, directory, version);
} }
if (updateNpm || !updateNuget) if (updateNpm || !updateNuget)
{ {
await UpdateNpmPackages(directory); await UpdateNpmPackages(directory, version);
} }
} }
private async Task UpdateNpmPackages(string directory) private async Task UpdateNpmPackages(string directory, string version)
{ {
await _npmPackagesUpdater.Update(directory); await _npmPackagesUpdater.Update(directory, version: version);
} }
private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory) private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version)
{ {
var solution = commandLineArgs.Options.GetOrNull(Options.SolutionName.Short, Options.SolutionName.Long); var solution = commandLineArgs.Options.GetOrNull(Options.SolutionName.Short, Options.SolutionName.Long);
@ -66,7 +67,7 @@ namespace Volo.Abp.Cli.Commands
{ {
var solutionName = Path.GetFileName(solution).RemovePostFix(".sln"); var solutionName = Path.GetFileName(solution).RemovePostFix(".sln");
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll); await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version);
Logger.LogInformation($"Volo packages are updated in {solutionName} solution."); Logger.LogInformation($"Volo packages are updated in {solutionName} solution.");
return; return;
@ -78,7 +79,7 @@ namespace Volo.Abp.Cli.Commands
{ {
var projectName = Path.GetFileName(project).RemovePostFix(".csproj"); var projectName = Path.GetFileName(project).RemovePostFix(".csproj");
await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll); await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version);
Logger.LogInformation($"Volo packages are updated in {projectName} project."); Logger.LogInformation($"Volo packages are updated in {projectName} project.");
return; return;
@ -107,6 +108,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine("-sp|--solution-path (Specify the solution path)"); sb.AppendLine("-sp|--solution-path (Specify the solution path)");
sb.AppendLine("-sn|--solution-name (Specify the solution name)"); sb.AppendLine("-sn|--solution-name (Specify the solution name)");
sb.AppendLine("--check-all (Check the new version of each package separately)"); sb.AppendLine("--check-all (Check the new version of each package separately)");
sb.AppendLine("-v|--version <version> (default: latest version)");
sb.AppendLine(""); sb.AppendLine("");
sb.AppendLine("Some examples:"); sb.AppendLine("Some examples:");
sb.AppendLine(""); sb.AppendLine("");
@ -148,6 +150,12 @@ namespace Volo.Abp.Cli.Commands
{ {
public const string Long = "check-all"; public const string Long = "check-all";
} }
public static class Version
{
public const string Short = "v";
public const string Long = "version";
}
} }
} }
} }

94
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs

@ -25,11 +25,11 @@ namespace Volo.Abp.Cli.ProjectModification
Logger = NullLogger<VoloNugetPackagesVersionUpdater>.Instance; Logger = NullLogger<VoloNugetPackagesVersionUpdater>.Instance;
} }
public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false) public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null)
{ {
var projectPaths = ProjectFinder.GetProjectFiles(solutionPath); var projectPaths = ProjectFinder.GetProjectFiles(solutionPath);
if (checkAll) if (checkAll && version.IsNullOrWhiteSpace())
{ {
Task.WaitAll(projectPaths.Select(projectPath => UpdateInternalAsync(projectPath, includePreviews, includeReleaseCandidates, switchToStable)).ToArray()); Task.WaitAll(projectPaths.Select(projectPath => UpdateInternalAsync(projectPath, includePreviews, includeReleaseCandidates, switchToStable)).ToArray());
} }
@ -48,7 +48,8 @@ namespace Volo.Abp.Cli.ProjectModification
switchToStable, switchToStable,
latestVersionFromNuget, latestVersionFromNuget,
latestReleaseCandidateVersionFromNuget, latestReleaseCandidateVersionFromNuget,
latestVersionFromMyGet); latestVersionFromMyGet,
version);
File.WriteAllText(filePath, updatedContent); File.WriteAllText(filePath, updatedContent);
} }
@ -57,9 +58,9 @@ namespace Volo.Abp.Cli.ProjectModification
} }
} }
public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false) public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null)
{ {
if (checkAll) if (checkAll && version.IsNullOrWhiteSpace())
{ {
await UpdateInternalAsync(projectPath, includeNightlyPreviews, includeReleaseCandidates, switchToStable); await UpdateInternalAsync(projectPath, includeNightlyPreviews, includeReleaseCandidates, switchToStable);
} }
@ -77,7 +78,8 @@ namespace Volo.Abp.Cli.ProjectModification
switchToStable, switchToStable,
latestVersionFromNuget, latestVersionFromNuget,
latestReleaseCandidateVersionFromNuget, latestReleaseCandidateVersionFromNuget,
latestVersionFromMyGet); latestVersionFromMyGet,
version);
File.WriteAllText(projectPath, updatedContent); File.WriteAllText(projectPath, updatedContent);
} }
@ -91,13 +93,26 @@ namespace Volo.Abp.Cli.ProjectModification
File.WriteAllText(projectPath, updatedContent); File.WriteAllText(projectPath, updatedContent);
} }
protected virtual async Task<bool> SpecifiedVersionExists(string version, string packageId)
{
var versionList = await _nuGetService.GetPackageVersionListAsync(packageId);
if (versionList.All(v => !v.Equals(version, StringComparison.OrdinalIgnoreCase)))
{
versionList = await _nuGetService.GetPackageVersionListAsync(packageId, true);
}
return versionList.Any(v => v.Equals(version, StringComparison.OrdinalIgnoreCase));
}
private async Task<string> UpdateVoloPackagesAsync(string content, private async Task<string> UpdateVoloPackagesAsync(string content,
bool includeNightlyPreviews = false, bool includeNightlyPreviews = false,
bool includeReleaseCandidates = false, bool includeReleaseCandidates = false,
bool switchToStable = false, bool switchToStable = false,
SemanticVersion latestNugetVersion = null, SemanticVersion latestNugetVersion = null,
SemanticVersion latestNugetReleaseCandidateVersion = null, SemanticVersion latestNugetReleaseCandidateVersion = null,
string latestMyGetVersion = null) string latestMyGetVersion = null,
string specifiedVersion = null)
{ {
string packageId = null; string packageId = null;
@ -129,40 +144,63 @@ namespace Volo.Abp.Cli.ProjectModification
Logger.LogDebug("Checking package: \"{0}\" - Current version: {1}", packageId, currentSemanticVersion); Logger.LogDebug("Checking package: \"{0}\" - Current version: {1}", packageId, currentSemanticVersion);
if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates) if (!specifiedVersion.IsNullOrWhiteSpace())
{ {
var latestVersion = latestMyGetVersion ?? await GetLatestVersionFromMyGet(packageId); if (await SpecifiedVersionExists(specifiedVersion, packageId))
if (currentVersion != latestVersion)
{ {
Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, latestVersion); var specifiedSemanticVersion = SemanticVersion.Parse(specifiedVersion);
versionAttribute.Value = latestVersion; if (specifiedSemanticVersion > currentSemanticVersion)
{
Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, specifiedVersion);
versionAttribute.Value = specifiedVersion;
}
else
{
Logger.LogWarning("Unable to update package \"{0}\" version v{1} to v{2}.", packageId, currentVersion, specifiedVersion);
}
} }
else else
{ {
Logger.LogDebug("Package: \"{0}-v{1}\" is up to date.", packageId, currentVersion); Logger.LogWarning("Package \"{0}\" specified version v{1} does not exist.", packageId, specifiedVersion);
} }
} }
else else
{ {
SemanticVersion latestVersion; if ((includeNightlyPreviews || (currentVersion.Contains("-preview") && !switchToStable)) && !includeReleaseCandidates)
if (currentSemanticVersion.IsPrerelease && !switchToStable)
{
latestVersion = latestNugetReleaseCandidateVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true);
}
else
{
latestVersion = latestNugetVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates);
}
if (latestVersion != null && (currentSemanticVersion < latestVersion || (currentSemanticVersion.IsPrerelease && switchToStable)))
{ {
Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentSemanticVersion.ToString(), latestVersion.ToString()); var latestVersion = latestMyGetVersion ?? await GetLatestVersionFromMyGet(packageId);
versionAttribute.Value = latestVersion.ToString();
if (currentVersion != latestVersion)
{
Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentVersion, latestVersion);
versionAttribute.Value = latestVersion;
}
else
{
Logger.LogDebug("Package: \"{0}-v{1}\" is up to date.", packageId, currentVersion);
}
} }
else else
{ {
Logger.LogInformation("Package: \"{0}-v{1}\" is up to date.", packageId, currentSemanticVersion); SemanticVersion latestVersion;
if (currentSemanticVersion.IsPrerelease && !switchToStable)
{
latestVersion = latestNugetReleaseCandidateVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: true);
}
else
{
latestVersion = latestNugetVersion ?? await _nuGetService.GetLatestVersionOrNullAsync(packageId, includeReleaseCandidates: includeReleaseCandidates);
}
if (latestVersion != null && (currentSemanticVersion < latestVersion || (currentSemanticVersion.IsPrerelease && switchToStable)))
{
Logger.LogInformation("Updating package \"{0}\" from v{1} to v{2}.", packageId, currentSemanticVersion.ToString(), latestVersion.ToString());
versionAttribute.Value = latestVersion.ToString();
}
else
{
Logger.LogInformation("Package: \"{0}-v{1}\" is up to date.", packageId, currentSemanticVersion);
}
} }
} }
} }

12
framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs

@ -3,13 +3,13 @@ using Microsoft.Extensions.DependencyInjection;
using Serilog; using Serilog;
using Serilog.Events; using Serilog.Events;
using System.IO; using System.IO;
using Volo.Abp.Threading; using System.Threading.Tasks;
namespace Volo.Abp.Cli namespace Volo.Abp.Cli
{ {
public class Program public class Program
{ {
private static void Main(string[] args) private static async Task Main(string[] args)
{ {
Console.OutputEncoding = System.Text.Encoding.UTF8; Console.OutputEncoding = System.Text.Encoding.UTF8;
@ -37,11 +37,9 @@ namespace Volo.Abp.Cli
{ {
application.Initialize(); application.Initialize();
AsyncHelper.RunSync( await application.ServiceProvider
() => application.ServiceProvider .GetRequiredService<CliService>()
.GetRequiredService<CliService>() .RunAsync(args);
.RunAsync(args)
);
application.Shutdown(); application.Shutdown();
} }

51
framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.RabbitMQ
protected IExceptionNotifier ExceptionNotifier { get; } protected IExceptionNotifier ExceptionNotifier { get; }
protected AbpTimer Timer { get; } protected AbpAsyncTimer Timer { get; }
protected ExchangeDeclareConfiguration Exchange { get; private set; } protected ExchangeDeclareConfiguration Exchange { get; private set; }
@ -38,7 +38,7 @@ namespace Volo.Abp.RabbitMQ
public RabbitMqMessageConsumer( public RabbitMqMessageConsumer(
IConnectionPool connectionPool, IConnectionPool connectionPool,
AbpTimer timer, AbpAsyncTimer timer,
IExceptionNotifier exceptionNotifier) IExceptionNotifier exceptionNotifier)
{ {
ConnectionPool = connectionPool; ConnectionPool = connectionPool;
@ -50,7 +50,7 @@ namespace Volo.Abp.RabbitMQ
Callbacks = new ConcurrentBag<Func<IModel, BasicDeliverEventArgs, Task>>(); Callbacks = new ConcurrentBag<Func<IModel, BasicDeliverEventArgs, Task>>();
Timer.Period = 5000; //5 sec. Timer.Period = 5000; //5 sec.
Timer.Elapsed += Timer_Elapsed; Timer.Elapsed = Timer_Elapsed;
Timer.RunOnStart = true; Timer.RunOnStart = true;
} }
@ -77,7 +77,7 @@ namespace Volo.Abp.RabbitMQ
await TrySendQueueBindCommandsAsync(); await TrySendQueueBindCommandsAsync();
} }
protected virtual void TrySendQueueBindCommands() protected virtual async Task TrySendQueueBindCommandsAsync()
{ {
try try
{ {
@ -119,40 +119,33 @@ namespace Volo.Abp.RabbitMQ
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
AsyncHelper.RunSync(() => ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning)); await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning);
} }
} }
protected virtual Task TrySendQueueBindCommandsAsync()
{
TrySendQueueBindCommands();
return Task.CompletedTask;
}
public virtual void OnMessageReceived(Func<IModel, BasicDeliverEventArgs, Task> callback) public virtual void OnMessageReceived(Func<IModel, BasicDeliverEventArgs, Task> callback)
{ {
Callbacks.Add(callback); Callbacks.Add(callback);
} }
protected virtual void Timer_Elapsed(object sender, EventArgs e) protected virtual async Task Timer_Elapsed(AbpAsyncTimer timer)
{ {
if (Channel == null || Channel.IsOpen == false) if (Channel == null || Channel.IsOpen == false)
{ {
TryCreateChannel(); await TryCreateChannelAsync();
TrySendQueueBindCommands(); await TrySendQueueBindCommandsAsync();
} }
} }
protected virtual void TryCreateChannel() protected virtual async Task TryCreateChannelAsync()
{ {
DisposeChannel(); await DisposeChannelAsync();
try try
{ {
var channel = ConnectionPool var channel = ConnectionPool
.Get(ConnectionName) .Get(ConnectionName)
.CreateModel(); .CreateModel();
channel.ExchangeDeclare( channel.ExchangeDeclare(
exchange: Exchange.ExchangeName, exchange: Exchange.ExchangeName,
type: Exchange.Type, type: Exchange.Type,
@ -172,7 +165,7 @@ namespace Volo.Abp.RabbitMQ
var consumer = new EventingBasicConsumer(channel); var consumer = new EventingBasicConsumer(channel);
consumer.Received += async (model, basicDeliverEventArgs) => consumer.Received += async (model, basicDeliverEventArgs) =>
{ {
await HandleIncomingMessage(channel, basicDeliverEventArgs); await HandleIncomingMessageAsync(channel, basicDeliverEventArgs);
}; };
channel.BasicConsume( channel.BasicConsume(
@ -186,11 +179,11 @@ namespace Volo.Abp.RabbitMQ
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
AsyncHelper.RunSync(() => ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning)); await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning);
} }
} }
protected virtual async Task HandleIncomingMessage(IModel channel, BasicDeliverEventArgs basicDeliverEventArgs) protected virtual async Task HandleIncomingMessageAsync(IModel channel, BasicDeliverEventArgs basicDeliverEventArgs)
{ {
try try
{ {
@ -208,6 +201,24 @@ namespace Volo.Abp.RabbitMQ
} }
} }
protected virtual async Task DisposeChannelAsync()
{
if (Channel == null)
{
return;
}
try
{
Channel.Dispose();
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
await ExceptionNotifier.NotifyAsync(ex, logLevel: LogLevel.Warning);
}
}
protected virtual void DisposeChannel() protected virtual void DisposeChannel()
{ {
if (Channel == null) if (Channel == null)

127
framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpAsyncTimer.cs

@ -0,0 +1,127 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling;
namespace Volo.Abp.Threading
{
/// <summary>
/// A robust timer implementation that ensures no overlapping occurs. It waits exactly specified <see cref="Period"/> between ticks.
/// </summary>
public class AbpAsyncTimer : ITransientDependency
{
/// <summary>
/// This func is raised periodically according to Period of Timer.
/// </summary>
public Func<AbpAsyncTimer, Task> Elapsed = _ => Task.CompletedTask;
/// <summary>
/// Task period of timer (as milliseconds).
/// </summary>
public int Period { get; set; }
/// <summary>
/// Indicates whether timer raises Elapsed event on Start method of Timer for once.
/// Default: False.
/// </summary>
public bool RunOnStart { get; set; }
public ILogger<AbpAsyncTimer> Logger { get; set; }
public IExceptionNotifier ExceptionNotifier { get; set; }
private readonly Timer _taskTimer;
private volatile bool _performingTasks;
private volatile bool _isRunning;
public AbpAsyncTimer()
{
ExceptionNotifier = NullExceptionNotifier.Instance;
Logger = NullLogger<AbpAsyncTimer>.Instance;
_taskTimer = new Timer(
TimerCallBack,
null,
Timeout.Infinite,
Timeout.Infinite
);
}
public void Start(CancellationToken cancellationToken = default)
{
if (Period <= 0)
{
throw new AbpException("Period should be set before starting the timer!");
}
lock (_taskTimer)
{
_taskTimer.Change(RunOnStart ? 0 : Period, Timeout.Infinite);
_isRunning = true;
}
}
public void Stop(CancellationToken cancellationToken = default)
{
lock (_taskTimer)
{
_taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
while (_performingTasks)
{
Monitor.Wait(_taskTimer);
}
_isRunning = false;
}
}
/// <summary>
/// This method is called by _taskTimer.
/// </summary>
/// <param name="state">Not used argument</param>
private void TimerCallBack(object state)
{
lock (_taskTimer)
{
if (!_isRunning || _performingTasks)
{
return;
}
_taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
_performingTasks = true;
}
_ = Timer_Elapsed();
}
private async Task Timer_Elapsed()
{
try
{
await Elapsed(this);
}
catch(Exception ex)
{
Logger.LogException(ex);
await ExceptionNotifier.NotifyAsync(ex);
}
finally
{
lock (_taskTimer)
{
_performingTasks = false;
if (_isRunning)
{
_taskTimer.Change(Period, Timeout.Infinite);
}
Monitor.Pulse(_taskTimer);
}
}
}
}
}

2
framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AbpTimer.cs

@ -118,4 +118,4 @@ namespace Volo.Abp.Threading
} }
} }
} }
} }

4
framework/test/Volo.Abp.BlobStoring.Aws.Tests/Volo/Abp/BlobStoring/Aws/AbpBlobStoringAwsTestModule.cs

@ -69,7 +69,7 @@ namespace Volo.Abp.BlobStoring.Aws
private async Task DeleteBucketAsync(ApplicationShutdownContext context) private async Task DeleteBucketAsync(ApplicationShutdownContext context)
{ {
var amazonS3Client = await context.ServiceProvider.GetService<IAmazonS3ClientFactory>() var amazonS3Client = await context.ServiceProvider.GetRequiredService<IAmazonS3ClientFactory>()
.GetAmazonS3Client(_configuration); .GetAmazonS3Client(_configuration);
if (await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, _randomContainerName)) if (await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, _randomContainerName))
@ -89,4 +89,4 @@ namespace Volo.Abp.BlobStoring.Aws
} }
} }
} }
} }

987
modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.Designer.cs

@ -0,0 +1,987 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
using VoloDocs.EntityFrameworkCore;
namespace VoloDocs.EntityFrameworkCore.Migrations
{
[DbContext(typeof(VoloDocsDbContext))]
[Migration("20201208084431_Added_CommitCount")]
partial class Added_CommitCount
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseIdentityColumns()
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.0");
modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Description")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsStatic")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Regex")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("RegexDescription")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<bool>("Required")
.HasColumnType("bit");
b.Property<int>("ValueType")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("AbpClaimTypes");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("SourceTenantId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("SourceUserId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TargetTenantId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("TargetUserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId")
.IsUnique()
.HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL");
b.ToTable("AbpLinkUsers");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDefault")
.HasColumnType("bit")
.HasColumnName("IsDefault");
b.Property<bool>("IsPublic")
.HasColumnType("bit")
.HasColumnName("IsPublic");
b.Property<bool>("IsStatic")
.HasColumnType("bit")
.HasColumnName("IsStatic");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("NormalizedName");
b.ToTable("AbpRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ClaimValue")
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AbpRoleClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.HasMaxLength(96)
.HasColumnType("nvarchar(96)");
b.Property<string>("ApplicationName")
.HasMaxLength(96)
.HasColumnType("nvarchar(96)");
b.Property<string>("BrowserInfo")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ClientIpAddress")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("CorrelationId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("Identity")
.HasMaxLength(96)
.HasColumnType("nvarchar(96)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("TenantName")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("TenantId", "Action");
b.HasIndex("TenantId", "ApplicationName");
b.HasIndex("TenantId", "Identity");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSecurityLogs");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("AccessFailedCount")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValue(0)
.HasColumnName("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("Email");
b.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("EmailConfirmed");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<bool>("IsExternal")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsExternal");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<bool>("LockoutEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Name");
b.Property<string>("NormalizedEmail")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("NormalizedEmail");
b.Property<string>("NormalizedUserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("NormalizedUserName");
b.Property<string>("PasswordHash")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("PasswordHash");
b.Property<string>("PhoneNumber")
.HasMaxLength(16)
.HasColumnType("nvarchar(16)")
.HasColumnName("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("SecurityStamp");
b.Property<string>("Surname")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)")
.HasColumnName("Surname");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("TwoFactorEnabled");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)")
.HasColumnName("UserName");
b.HasKey("Id");
b.HasIndex("Email");
b.HasIndex("NormalizedEmail");
b.HasIndex("NormalizedUserName");
b.HasIndex("UserName");
b.ToTable("AbpUsers");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("ClaimType")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ClaimValue")
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AbpUserClaims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LoginProvider")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ProviderDisplayName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(196)
.HasColumnType("nvarchar(196)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("UserId", "LoginProvider");
b.HasIndex("LoginProvider", "ProviderKey");
b.ToTable("AbpUserLogins");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b =>
{
b.Property<Guid>("OrganizationUnitId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("OrganizationUnitId", "UserId");
b.HasIndex("UserId", "OrganizationUnitId");
b.ToTable("AbpUserOrganizationUnits");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId", "UserId");
b.ToTable("AbpUserRoles");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LoginProvider")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Name")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AbpUserTokens");
});
modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(95)
.HasColumnType("nvarchar(95)")
.HasColumnName("Code");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)")
.HasColumnName("DisplayName");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<Guid?>("ParentId")
.HasColumnType("uniqueidentifier");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("Code");
b.HasIndex("ParentId");
b.ToTable("AbpOrganizationUnits");
});
modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b =>
{
b.Property<Guid>("OrganizationUnitId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("OrganizationUnitId", "RoleId");
b.HasIndex("RoleId", "OrganizationUnitId");
b.ToTable("AbpOrganizationUnitRoles");
});
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ProviderName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpPermissionGrants");
});
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ProviderKey")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("ProviderName")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.HasKey("Id");
b.HasIndex("Name", "ProviderName", "ProviderKey");
b.ToTable("AbpSettings");
});
modelBuilder.Entity("Volo.Docs.Documents.Document", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("EditLink")
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Format")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("LanguageCode")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("LastCachedTime")
.HasColumnType("datetime2");
b.Property<DateTime?>("LastSignificantUpdateTime")
.HasColumnType("datetime2");
b.Property<DateTime>("LastUpdatedTime")
.HasColumnType("datetime2");
b.Property<string>("LocalDirectory")
.HasMaxLength(512)
.HasColumnType("nvarchar(512)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<Guid>("ProjectId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RawRootUrl")
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("RootUrl")
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Version")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.ToTable("DocsDocuments");
});
modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b =>
{
b.Property<Guid>("DocumentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Username")
.HasColumnType("nvarchar(450)");
b.Property<string>("AvatarUrl")
.HasColumnType("nvarchar(max)");
b.Property<int>("CommitCount")
.HasColumnType("int");
b.Property<string>("UserProfileUrl")
.HasColumnType("nvarchar(max)");
b.HasKey("DocumentId", "Username");
b.ToTable("DocsDocumentContributors");
});
modelBuilder.Entity("Volo.Docs.Projects.Project", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("DefaultDocumentName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("DocumentStoreType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ExtraProperties")
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<string>("Format")
.HasColumnType("nvarchar(max)");
b.Property<string>("LatestVersionBranchName")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("MainWebsiteUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("MinimumVersion")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("NavigationDocumentName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ParametersDocumentName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("ShortName")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.ToTable("DocsProjects");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole", null)
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser", null)
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser", null)
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b =>
{
b.HasOne("Volo.Abp.Identity.OrganizationUnit", null)
.WithMany()
.HasForeignKey("OrganizationUnitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Volo.Abp.Identity.IdentityUser", null)
.WithMany("OrganizationUnits")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Volo.Abp.Identity.IdentityUser", null)
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
{
b.HasOne("Volo.Abp.Identity.IdentityUser", null)
.WithMany("Tokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b =>
{
b.HasOne("Volo.Abp.Identity.OrganizationUnit", null)
.WithMany()
.HasForeignKey("ParentId");
});
modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b =>
{
b.HasOne("Volo.Abp.Identity.OrganizationUnit", null)
.WithMany("Roles")
.HasForeignKey("OrganizationUnitId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Volo.Abp.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b =>
{
b.HasOne("Volo.Docs.Documents.Document", null)
.WithMany("Contributors")
.HasForeignKey("DocumentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
{
b.Navigation("Claims");
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{
b.Navigation("Claims");
b.Navigation("Logins");
b.Navigation("OrganizationUnits");
b.Navigation("Roles");
b.Navigation("Tokens");
});
modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b =>
{
b.Navigation("Roles");
});
modelBuilder.Entity("Volo.Docs.Documents.Document", b =>
{
b.Navigation("Contributors");
});
#pragma warning restore 612, 618
}
}
}

24
modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20201208084431_Added_CommitCount.cs

@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace VoloDocs.EntityFrameworkCore.Migrations
{
public partial class Added_CommitCount : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "CommitCount",
table: "DocsDocumentContributors",
type: "int",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CommitCount",
table: "DocsDocumentContributors");
}
}
}

5
modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs

@ -19,7 +19,7 @@ namespace VoloDocs.EntityFrameworkCore.Migrations
.UseIdentityColumns() .UseIdentityColumns()
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.0-rc.2.20475.6"); .HasAnnotation("ProductVersion", "5.0.0");
modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
{ {
@ -782,6 +782,9 @@ namespace VoloDocs.EntityFrameworkCore.Migrations
b.Property<string>("AvatarUrl") b.Property<string>("AvatarUrl")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<int>("CommitCount")
.HasColumnType("int");
b.Property<string>("UserProfileUrl") b.Property<string>("UserProfileUrl")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");

2
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentContributorDto.cs

@ -10,5 +10,7 @@ namespace Volo.Docs.Documents
public string UserProfileUrl { get; set; } public string UserProfileUrl { get; set; }
public string AvatarUrl { get; set; } public string AvatarUrl { get; set; }
public int CommitCount { get; set; }
} }
} }

4
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/Document.cs

@ -87,9 +87,9 @@ namespace Volo.Docs.Documents
Contributors = new List<DocumentContributor>(); Contributors = new List<DocumentContributor>();
} }
public virtual void AddContributor(string username, string userProfileUrl, string avatarUrl) public virtual void AddContributor(string username, string userProfileUrl, string avatarUrl, int commitCount = 1)
{ {
Contributors.AddIfNotContains(new DocumentContributor(Id, username, userProfileUrl, avatarUrl)); Contributors.AddIfNotContains(new DocumentContributor(Id, username, userProfileUrl, avatarUrl, commitCount));
} }
public virtual void RemoveAllContributors() public virtual void RemoveAllContributors()

5
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentContributor.cs

@ -9,6 +9,8 @@ namespace Volo.Docs.Documents
public string Username { get; set; } public string Username { get; set; }
public int CommitCount { get; set; }
public string UserProfileUrl { get; set; } public string UserProfileUrl { get; set; }
public string AvatarUrl { get; set; } public string AvatarUrl { get; set; }
@ -23,12 +25,13 @@ namespace Volo.Docs.Documents
return DocumentId == documentId && Username == username; return DocumentId == documentId && Username == username;
} }
public DocumentContributor(Guid documentId, string username, string userProfileUrl, string avatarUrl) public DocumentContributor(Guid documentId, string username, string userProfileUrl, string avatarUrl, int commitCount = 1)
{ {
DocumentId = documentId; DocumentId = documentId;
Username = username; Username = username;
UserProfileUrl = userProfileUrl; UserProfileUrl = userProfileUrl;
AvatarUrl = avatarUrl; AvatarUrl = avatarUrl;
CommitCount = commitCount;
} }
public override object[] GetKeys() public override object[] GetKeys()

13
modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/DocumentAuthor.cs

@ -0,0 +1,13 @@
namespace Volo.Docs.GitHub.Documents
{
public class DocumentAuthor
{
public string Login { get; set; }
public string HtmlUrl { get; set; }
public string AvatarUrl { get; set; }
public int CommitCount { get; set; }
}
}

31
modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs

@ -84,9 +84,11 @@ namespace Volo.Docs.GitHub.Documents
} }
var authors = GetAuthors(commits); var authors = GetAuthors(commits);
document.RemoveAllContributors();
foreach (var author in authors) foreach (var author in authors)
{ {
document.AddContributor(author.Login, author.HtmlUrl, author.AvatarUrl); document.AddContributor(author.Login, author.HtmlUrl, author.AvatarUrl, author.CommitCount);
} }
return document; return document;
@ -114,20 +116,35 @@ namespace Volo.Docs.GitHub.Documents
: null; : null;
} }
private static List<Author> GetAuthors(IReadOnlyList<GitHubCommit> commits) private static List<DocumentAuthor> GetAuthors(IReadOnlyList<GitHubCommit> commits)
{ {
if (commits == null || !commits.Any()) if (commits == null || !commits.Any())
{ {
return new List<Author>(); return new List<DocumentAuthor>();
} }
return commits var authorsOrderedAndGrouped = commits
.Where(x => x.Author != null) .Where(x => x.Author != null)
.Select(x => x.Author) .Select(x => x.Author)
.GroupBy(x => x.Id) .GroupBy(x => x.Id)
.OrderByDescending(x => x.Count()) .OrderByDescending(x => x.Count());
.Select(x => x.FirstOrDefault())
.ToList(); var documentAuthors = new List<DocumentAuthor>();
foreach (var authorGroup in authorsOrderedAndGrouped)
{
var author = authorGroup.FirstOrDefault();
var documentAuthor = new DocumentAuthor
{
CommitCount = authorGroup.Count(),
AvatarUrl = author.AvatarUrl,
HtmlUrl = author.HtmlUrl,
Login = author.Login
};
documentAuthors.Add(documentAuthor);
}
return documentAuthors;
} }
private static DateTime GetLastCommitDate(IReadOnlyList<GitHubCommit> commits) private static DateTime GetLastCommitDate(IReadOnlyList<GitHubCommit> commits)

2
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -217,7 +217,7 @@
<span class="for-desktop mr-3"> <span class="for-desktop mr-3">
@(L["Contributors"].Value) @(L["Contributors"].Value)
</span> </span>
@foreach (var contributor in Model.Document.Contributors) @foreach (var contributor in Model.Document.Contributors.OrderByDescending(c=> c.CommitCount).ToList())
{ {
<a href="@contributor.UserProfileUrl" target="_blank" class="cont-avatar"> <a href="@contributor.UserProfileUrl" target="_blank" class="cont-avatar">
<img src="@contributor.AvatarUrl" <img src="@contributor.AvatarUrl"

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Tokens/TokenCleanupBackgroundWorker.cs

@ -11,11 +11,11 @@ namespace Volo.Abp.IdentityServer.Tokens
protected TokenCleanupOptions Options { get; } protected TokenCleanupOptions Options { get; }
public TokenCleanupBackgroundWorker( public TokenCleanupBackgroundWorker(
AbpTimer timer, AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory, IServiceScopeFactory serviceScopeFactory,
IOptions<TokenCleanupOptions> options) IOptions<TokenCleanupOptions> options)
: base( : base(
timer, timer,
serviceScopeFactory) serviceScopeFactory)
{ {
Options = options.Value; Options = options.Value;
@ -27,8 +27,7 @@ namespace Volo.Abp.IdentityServer.Tokens
await workerContext await workerContext
.ServiceProvider .ServiceProvider
.GetRequiredService<TokenCleanupService>() .GetRequiredService<TokenCleanupService>()
.CleanAsync() .CleanAsync();
;
} }
} }
} }

Loading…
Cancel
Save