22 changed files with 858 additions and 613 deletions
@ -1,277 +0,0 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
using OpenIddict.Abstractions; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.OpenIddict.Applications; |
|||
using Volo.Abp.OpenIddict.Scopes; |
|||
using Volo.Abp.PermissionManagement; |
|||
|
|||
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder; |
|||
|
|||
public class ClientDataSeederContributor : IDataSeedContributor, ITransientDependency |
|||
{ |
|||
private readonly IOpenIddictApplicationManager _applicationManager; |
|||
private readonly IOpenIddictApplicationRepository _applicationRepository; |
|||
|
|||
private readonly IOpenIddictScopeManager _scopeManager; |
|||
private readonly IOpenIddictScopeRepository _scopeRepository; |
|||
|
|||
private readonly IPermissionDataSeeder _permissionDataSeeder; |
|||
private readonly IConfiguration _configuration; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public ClientDataSeederContributor( |
|||
IOpenIddictApplicationManager applicationManager, |
|||
IOpenIddictApplicationRepository applicationRepository, |
|||
IOpenIddictScopeManager scopeManager, |
|||
IOpenIddictScopeRepository scopeRepository, |
|||
IPermissionDataSeeder permissionDataSeeder, |
|||
IConfiguration configuration, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
_applicationManager = applicationManager; |
|||
_applicationRepository = applicationRepository; |
|||
_scopeManager = scopeManager; |
|||
_scopeRepository = scopeRepository; |
|||
_permissionDataSeeder = permissionDataSeeder; |
|||
_configuration = configuration; |
|||
_currentTenant = currentTenant; |
|||
} |
|||
|
|||
public async virtual Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
using (_currentTenant.Change(context.TenantId)) |
|||
{ |
|||
await SeedOpenIddictAsync(); |
|||
} |
|||
} |
|||
|
|||
#region OpenIddict
|
|||
|
|||
private async Task SeedOpenIddictAsync() |
|||
{ |
|||
await CreateScopeAsync("lingyun-abp-application"); |
|||
await CreateApplicationAsync("lingyun-abp-application"); |
|||
} |
|||
|
|||
private async Task CreateScopeAsync(string scope) |
|||
{ |
|||
if (await _scopeRepository.FindByNameAsync(scope) == null) |
|||
{ |
|||
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor() |
|||
{ |
|||
Name = scope, |
|||
DisplayName = scope + " access", |
|||
DisplayNames = |
|||
{ |
|||
[CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问", |
|||
[CultureInfo.GetCultureInfo("en")] = "Abp API Application Access" |
|||
}, |
|||
Resources = |
|||
{ |
|||
scope |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
private async Task CreateApplicationAsync(string scope) |
|||
{ |
|||
var configurationSection = _configuration.GetSection("OpenIddict:Applications"); |
|||
|
|||
var vueClientId = configurationSection["VueAdmin:ClientId"]; |
|||
if (!vueClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/'); |
|||
|
|||
if (await _applicationRepository.FindByClientIdAsync(vueClientId) == null) |
|||
{ |
|||
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor |
|||
{ |
|||
ClientId = vueClientId, |
|||
ClientSecret = configurationSection["VueAdmin:ClientSecret"], |
|||
ApplicationType = OpenIddictConstants.ApplicationTypes.Web, |
|||
ConsentType = OpenIddictConstants.ConsentTypes.Explicit, |
|||
DisplayName = "Abp Vue Admin Client", |
|||
PostLogoutRedirectUris = |
|||
{ |
|||
new Uri(vueClientRootUrl + "signout-callback"), |
|||
new Uri(vueClientRootUrl) |
|||
}, |
|||
RedirectUris = |
|||
{ |
|||
new Uri(vueClientRootUrl + "signin-callback"), |
|||
new Uri(vueClientRootUrl) |
|||
}, |
|||
Permissions = |
|||
{ |
|||
OpenIddictConstants.Permissions.Endpoints.Authorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Token, |
|||
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Introspection, |
|||
OpenIddictConstants.Permissions.Endpoints.Revocation, |
|||
OpenIddictConstants.Permissions.Endpoints.EndSession, |
|||
|
|||
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, |
|||
OpenIddictConstants.Permissions.GrantTypes.Implicit, |
|||
OpenIddictConstants.Permissions.GrantTypes.Password, |
|||
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, |
|||
OpenIddictConstants.Permissions.GrantTypes.DeviceCode, |
|||
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, |
|||
|
|||
OpenIddictConstants.Permissions.ResponseTypes.Code, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.None, |
|||
OpenIddictConstants.Permissions.ResponseTypes.Token, |
|||
|
|||
OpenIddictConstants.Permissions.Scopes.Roles, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Prefixes.Scope + scope |
|||
} |
|||
}); |
|||
|
|||
var vueClientPermissions = new string[1] |
|||
{ |
|||
"AbpIdentity.UserLookup" |
|||
}; |
|||
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions); |
|||
} |
|||
} |
|||
|
|||
var internalServiceClientId = configurationSection["InternalService:ClientId"]; |
|||
if (!internalServiceClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
if (await _applicationRepository.FindByClientIdAsync(internalServiceClientId) == null) |
|||
{ |
|||
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor |
|||
{ |
|||
ClientId = internalServiceClientId, |
|||
ClientSecret = configurationSection["InternalService:ClientSecret"] ?? "1q2w3e*", |
|||
ClientType = OpenIddictConstants.ClientTypes.Confidential, |
|||
ConsentType = OpenIddictConstants.ConsentTypes.Explicit, |
|||
ApplicationType = OpenIddictConstants.ApplicationTypes.Native, |
|||
DisplayName = "Abp Vue Admin Client", |
|||
Permissions = |
|||
{ |
|||
OpenIddictConstants.Permissions.Endpoints.Authorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Token, |
|||
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Introspection, |
|||
OpenIddictConstants.Permissions.Endpoints.Revocation, |
|||
OpenIddictConstants.Permissions.Endpoints.EndSession, |
|||
|
|||
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, |
|||
OpenIddictConstants.Permissions.GrantTypes.Implicit, |
|||
OpenIddictConstants.Permissions.GrantTypes.Password, |
|||
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, |
|||
OpenIddictConstants.Permissions.GrantTypes.DeviceCode, |
|||
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, |
|||
|
|||
OpenIddictConstants.Permissions.ResponseTypes.Code, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.None, |
|||
OpenIddictConstants.Permissions.ResponseTypes.Token, |
|||
|
|||
OpenIddictConstants.Permissions.Scopes.Roles, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Prefixes.Scope + scope |
|||
} |
|||
}); |
|||
|
|||
var internalServicePermissions = new string[2] |
|||
{ |
|||
"AbpIdentity.UserLookup","AbpIdentity.Users" |
|||
}; |
|||
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, internalServiceClientId, internalServicePermissions); |
|||
} |
|||
} |
|||
|
|||
var oauthClientId = configurationSection["VueOAuthClient:ClientId"]; |
|||
if (!oauthClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get<List<string>>(); |
|||
|
|||
if (await _applicationRepository.FindByClientIdAsync(oauthClientId) == null) |
|||
{ |
|||
var application = new OpenIddictApplicationDescriptor |
|||
{ |
|||
ClientId = oauthClientId, |
|||
ClientSecret = null, |
|||
ApplicationType = OpenIddictConstants.ApplicationTypes.Web, |
|||
ConsentType = OpenIddictConstants.ConsentTypes.Implicit, |
|||
DisplayName = "OAuth Client", |
|||
PostLogoutRedirectUris = { }, |
|||
RedirectUris = { }, |
|||
Permissions = |
|||
{ |
|||
OpenIddictConstants.Permissions.Endpoints.Authorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Token, |
|||
OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, |
|||
OpenIddictConstants.Permissions.Endpoints.Introspection, |
|||
OpenIddictConstants.Permissions.Endpoints.Revocation, |
|||
OpenIddictConstants.Permissions.Endpoints.EndSession, |
|||
|
|||
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, |
|||
OpenIddictConstants.Permissions.GrantTypes.RefreshToken, |
|||
|
|||
OpenIddictConstants.Permissions.ResponseTypes.Code, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.CodeToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, |
|||
OpenIddictConstants.Permissions.ResponseTypes.None, |
|||
OpenIddictConstants.Permissions.ResponseTypes.Token, |
|||
|
|||
OpenIddictConstants.Permissions.Scopes.Roles, |
|||
OpenIddictConstants.Permissions.Scopes.Profile, |
|||
OpenIddictConstants.Permissions.Scopes.Email, |
|||
OpenIddictConstants.Permissions.Scopes.Address, |
|||
OpenIddictConstants.Permissions.Scopes.Phone, |
|||
OpenIddictConstants.Permissions.Prefixes.Scope + scope |
|||
} |
|||
}; |
|||
|
|||
oauthClientRootUrls.ForEach(url => |
|||
{ |
|||
application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/'))); |
|||
application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signout-callback")); |
|||
|
|||
application.RedirectUris.AddIfNotContains(new Uri(url)); |
|||
application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signin-callback")); |
|||
application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html")); |
|||
}); |
|||
|
|||
await _applicationManager.CreateAsync(application); |
|||
|
|||
var oauthClientPermissions = new string[1] |
|||
{ |
|||
"AbpIdentity.UserLookup" |
|||
}; |
|||
await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions); |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using OpenIddict.Abstractions; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.OpenIddict; |
|||
using Volo.Abp.OpenIddict.Applications; |
|||
using Volo.Abp.OpenIddict.Scopes; |
|||
using Volo.Abp.PermissionManagement; |
|||
|
|||
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder; |
|||
public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase, IDataSeedContributor, ITransientDependency |
|||
{ |
|||
public ILogger<OpenIddictDataSeederContributor> Logger { protected get; set; } |
|||
|
|||
protected IPermissionDataSeeder PermissionDataSeeder { get; } |
|||
public OpenIddictDataSeederContributor( |
|||
IConfiguration configuration, |
|||
IOpenIddictApplicationRepository openIddictApplicationRepository, |
|||
IAbpApplicationManager applicationManager, |
|||
IOpenIddictScopeRepository openIddictScopeRepository, |
|||
IOpenIddictScopeManager scopeManager, |
|||
IPermissionDataSeeder permissionDataSeeder) |
|||
: base(configuration, openIddictApplicationRepository, applicationManager, openIddictScopeRepository, scopeManager) |
|||
{ |
|||
PermissionDataSeeder = permissionDataSeeder; |
|||
|
|||
Logger = NullLogger<OpenIddictDataSeederContributor>.Instance; |
|||
} |
|||
|
|||
public async virtual Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
var scope = "lingyun-abp-application"; |
|||
|
|||
Logger.LogInformation("Seeding the default scope..."); |
|||
await CreateScopeAsync(scope); |
|||
|
|||
Logger.LogInformation("Seeding the default applications..."); |
|||
await CreateApplicationAsync(scope); |
|||
} |
|||
|
|||
private async Task CreateScopeAsync(string scope) |
|||
{ |
|||
await CreateScopesAsync(new OpenIddictScopeDescriptor |
|||
{ |
|||
Name = scope, |
|||
DisplayName = scope + " access", |
|||
DisplayNames = |
|||
{ |
|||
[CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问", |
|||
[CultureInfo.GetCultureInfo("en")] = "Abp API Application Access" |
|||
}, |
|||
Resources = |
|||
{ |
|||
scope |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private async Task CreateApplicationAsync(string scope) |
|||
{ |
|||
var configurationSection = Configuration.GetSection("OpenIddict:Applications"); |
|||
var vueClientId = configurationSection["VueAdmin:ClientId"]; |
|||
if (!vueClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogInformation("Seeding application {vueClientId}...", vueClientId); |
|||
|
|||
var vueClientRootUrls = configurationSection.GetSection("VueAdmin:RootUrls").Get<List<string>>() ?? []; |
|||
|
|||
var vueClientRedirectUrls = new List<string>(); |
|||
var vueClientPostLogoutRedirectUrls = new List<string>(); |
|||
vueClientRootUrls.ForEach(url => |
|||
{ |
|||
vueClientRedirectUrls.Add(url.EnsureEndsWith('/')); |
|||
vueClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback"); |
|||
|
|||
vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/')); |
|||
vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback"); |
|||
}); |
|||
|
|||
await CreateOrUpdateApplicationAsync( |
|||
OpenIddictConstants.ApplicationTypes.Web, |
|||
vueClientId, |
|||
OpenIddictConstants.ClientTypes.Confidential, |
|||
OpenIddictConstants.ConsentTypes.Explicit, |
|||
"Abp Vue Admin Client", |
|||
configurationSection["VueAdmin:ClientSecret"] ?? "1q2w3e*", |
|||
[OpenIddictConstants.GrantTypes.AuthorizationCode, |
|||
OpenIddictConstants.GrantTypes.Implicit, |
|||
OpenIddictConstants.GrantTypes.Password, |
|||
OpenIddictConstants.GrantTypes.RefreshToken], |
|||
[OpenIddictConstants.Scopes.OpenId, |
|||
OpenIddictConstants.Scopes.Email, |
|||
OpenIddictConstants.Scopes.Roles, |
|||
OpenIddictConstants.Scopes.Address, |
|||
OpenIddictConstants.Scopes.Phone, |
|||
OpenIddictConstants.Scopes.Profile, |
|||
OpenIddictConstants.Scopes.OfflineAccess, |
|||
scope], |
|||
vueClientRedirectUrls, |
|||
vueClientPostLogoutRedirectUrls); |
|||
|
|||
var vueClientPermissions = new string[1] |
|||
{ |
|||
"AbpIdentity.UserLookup" |
|||
}; |
|||
await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions); |
|||
} |
|||
|
|||
var internalServiceClientId = configurationSection["InternalService:ClientId"]; |
|||
if (!internalServiceClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogInformation("Seeding application {internalServiceClientId}...", internalServiceClientId); |
|||
|
|||
await CreateOrUpdateApplicationAsync( |
|||
OpenIddictConstants.ApplicationTypes.Native, |
|||
internalServiceClientId, |
|||
OpenIddictConstants.ClientTypes.Confidential, |
|||
OpenIddictConstants.ConsentTypes.Explicit, |
|||
"Abp Internal Service Client", |
|||
configurationSection["InternalService:ClientSecret"] ?? "1q2w3e*", |
|||
[OpenIddictConstants.GrantTypes.ClientCredentials], |
|||
[OpenIddictConstants.ResponseTypes.Token, scope]); |
|||
} |
|||
|
|||
var oauthClientId = configurationSection["VueOAuthClient:ClientId"]; |
|||
if (!oauthClientId.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogInformation("Seeding application {oauthClientId}...", oauthClientId); |
|||
|
|||
var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get<List<string>>() ?? []; |
|||
|
|||
var oauthClientRedirectUrls = new List<string>(); |
|||
var oauthClientPostLogoutRedirectUrls = new List<string>(); |
|||
oauthClientRootUrls.ForEach(url => |
|||
{ |
|||
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/')); |
|||
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback"); |
|||
oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html"); |
|||
|
|||
oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/')); |
|||
oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback"); |
|||
}); |
|||
|
|||
await CreateOrUpdateApplicationAsync( |
|||
OpenIddictConstants.ApplicationTypes.Web, |
|||
oauthClientId, |
|||
OpenIddictConstants.ClientTypes.Public, |
|||
OpenIddictConstants.ConsentTypes.Implicit, |
|||
"Abp OAuth Client", |
|||
null, |
|||
[OpenIddictConstants.GrantTypes.AuthorizationCode, |
|||
OpenIddictConstants.GrantTypes.RefreshToken], |
|||
[OpenIddictConstants.Scopes.OpenId, |
|||
OpenIddictConstants.Scopes.Email, |
|||
OpenIddictConstants.Scopes.Roles, |
|||
OpenIddictConstants.Scopes.Address, |
|||
OpenIddictConstants.Scopes.Phone, |
|||
OpenIddictConstants.Scopes.Profile, |
|||
OpenIddictConstants.Scopes.OfflineAccess, |
|||
scope], |
|||
oauthClientRedirectUrls, |
|||
oauthClientPostLogoutRedirectUrls); |
|||
|
|||
var oauthClientPermissions = new string[1] |
|||
{ |
|||
"AbpIdentity.UserLookup" |
|||
}; |
|||
await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,121 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using Polly; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.LocalizationManagement; |
|||
public class LocalizationDynamicInitializer : ITransientDependency |
|||
{ |
|||
public ILogger<LocalizationDynamicInitializer> Logger { get; set; } |
|||
|
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected IOptions<AbpLocalizationManagementOptions> Options { get; } |
|||
protected IHostApplicationLifetime ApplicationLifetime { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected IStaticLocalizationSaver StaticLocalizationSaver { get; } |
|||
|
|||
public LocalizationDynamicInitializer( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<AbpLocalizationManagementOptions> options, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
IStaticLocalizationSaver staticLocalizationSaver) |
|||
{ |
|||
|
|||
ServiceProvider = serviceProvider; |
|||
Options = options; |
|||
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
StaticLocalizationSaver = staticLocalizationSaver; |
|||
|
|||
Logger = NullLogger<LocalizationDynamicInitializer>.Instance; |
|||
} |
|||
|
|||
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!Options.Value.SaveStaticLocalizationsToDatabase) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
if (runInBackground) |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null) |
|||
{ |
|||
cancellationToken = ApplicationLifetime.ApplicationStopping; |
|||
} |
|||
await ExecuteInitializationAsync(cancellationToken); |
|||
}, cancellationToken); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
return ExecuteInitializationAsync(cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
using (CancellationTokenProvider.Use(cancellationToken)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticLocalizationToDatabaseAsync(cancellationToken); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// No need to log here since inner calls log
|
|||
} |
|||
} |
|||
|
|||
protected virtual async Task SaveStaticLocalizationToDatabaseAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.SaveStaticLocalizationsToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await Policy |
|||
.Handle<Exception>(e => e is not OperationCanceledException) |
|||
.WaitAndRetryAsync( |
|||
8, |
|||
retryAttempt => TimeSpan.FromSeconds( |
|||
Volo.Abp.RandomHelper.GetRandom( |
|||
(int)Math.Pow(2, retryAttempt) * 8, |
|||
(int)Math.Pow(2, retryAttempt) * 12) |
|||
) |
|||
) |
|||
.ExecuteAsync(async _ => |
|||
{ |
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
await StaticLocalizationSaver.SaveAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
}, cancellationToken); |
|||
} |
|||
} |
|||
@ -0,0 +1,145 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using Polly; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.Notifications; |
|||
public class NotificationDynamicInitializer : ITransientDependency |
|||
{ |
|||
public ILogger<NotificationDynamicInitializer> Logger { get; set; } |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected IOptions<AbpNotificationsManagementOptions> Options { get; } |
|||
protected IHostApplicationLifetime ApplicationLifetime { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected IDynamicNotificationDefinitionStore DynamicNotificationDefinitionStore { get; } |
|||
protected IStaticNotificationSaver StaticNotificationSaver { get; } |
|||
|
|||
public NotificationDynamicInitializer( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<AbpNotificationsManagementOptions> options, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
IDynamicNotificationDefinitionStore dynamicNotificationDefinitionStore, |
|||
IStaticNotificationSaver staticNotificationSaver) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
Options = options; |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
DynamicNotificationDefinitionStore = dynamicNotificationDefinitionStore; |
|||
StaticNotificationSaver = staticNotificationSaver; |
|||
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
|
|||
Logger = NullLogger<NotificationDynamicInitializer>.Instance; |
|||
} |
|||
|
|||
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!Options.Value.SaveStaticNotificationsToDatabase && !Options.Value.IsDynamicNotificationsStoreEnabled) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
if (runInBackground) |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null) |
|||
{ |
|||
cancellationToken = ApplicationLifetime.ApplicationStopping; |
|||
} |
|||
await ExecuteInitializationAsync(cancellationToken); |
|||
}, cancellationToken); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
return ExecuteInitializationAsync(cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
using (CancellationTokenProvider.Use(cancellationToken)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticNotificationssToDatabaseAsync(cancellationToken); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await PreCacheDynamicNotificationsAsync(cancellationToken); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// No need to log here since inner calls log
|
|||
} |
|||
} |
|||
|
|||
protected virtual async Task SaveStaticNotificationssToDatabaseAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.SaveStaticNotificationsToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await Policy |
|||
.Handle<Exception>(e => e is not OperationCanceledException) |
|||
.WaitAndRetryAsync( |
|||
8, |
|||
retryAttempt => TimeSpan.FromSeconds( |
|||
Volo.Abp.RandomHelper.GetRandom( |
|||
(int)Math.Pow(2, retryAttempt) * 8, |
|||
(int)Math.Pow(2, retryAttempt) * 12) |
|||
) |
|||
) |
|||
.ExecuteAsync(async _ => |
|||
{ |
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
await StaticNotificationSaver.SaveAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
}, cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task PreCacheDynamicNotificationsAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.IsDynamicNotificationsStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
// Pre-cache notifications, so first request doesn't wait
|
|||
await DynamicNotificationDefinitionStore.GetGroupsAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // It will be cached in Initialize()
|
|||
} |
|||
} |
|||
} |
|||
@ -1,115 +0,0 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Polly; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.TextTemplating; |
|||
public class TextTemplateDefinitionInitializer : ITransientDependency |
|||
{ |
|||
protected IRootServiceProvider RootServiceProvider { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected AbpTextTemplatingCachingOptions TextTemplatingCachingOptions { get; } |
|||
|
|||
public TextTemplateDefinitionInitializer( |
|||
IRootServiceProvider rootServiceProvider, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
IOptions<AbpTextTemplatingCachingOptions> textTemplatingCachingOptions) |
|||
{ |
|||
RootServiceProvider = rootServiceProvider; |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
TextTemplatingCachingOptions = textTemplatingCachingOptions.Value; |
|||
} |
|||
|
|||
public async virtual Task InitializeDynamicTemplates(CancellationToken cancellationToken) |
|||
{ |
|||
if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase && !TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
using var scope = RootServiceProvider.CreateScope(); |
|||
var applicationLifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
var token = applicationLifetime?.ApplicationStopping ?? cancellationToken; |
|||
using (CancellationTokenProvider.Use(token)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticTemplateDefinitionsToDatabaseAsync(scope); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await PreCacheDynamicTemplateDefinitionsAsync(scope); |
|||
} |
|||
} |
|||
|
|||
private async Task SaveStaticTemplateDefinitionsToDatabaseAsync(IServiceScope serviceScope) |
|||
{ |
|||
if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await Policy |
|||
.Handle<Exception>() |
|||
.WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10)) |
|||
.ExecuteAsync(async _ => |
|||
{ |
|||
try |
|||
{ |
|||
// ReSharper disable once AccessToDisposedClosure
|
|||
var saver = serviceScope.ServiceProvider.GetRequiredService<IStaticTemplateSaver>(); |
|||
|
|||
await saver.SaveDefinitionTemplateAsync(); |
|||
|
|||
await saver.SaveTemplateContentAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
// ReSharper disable once AccessToDisposedClosure
|
|||
serviceScope.ServiceProvider |
|||
.GetService<ILogger<TextTemplateDefinitionInitializer>>()? |
|||
.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
}, CancellationTokenProvider.Token); |
|||
|
|||
} |
|||
|
|||
private async Task PreCacheDynamicTemplateDefinitionsAsync(IServiceScope serviceScope) |
|||
{ |
|||
if (!TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
// ReSharper disable once AccessToDisposedClosure
|
|||
var store = serviceScope.ServiceProvider.GetRequiredService<ITemplateDefinitionStore>(); |
|||
|
|||
await store.GetAllAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
// ReSharper disable once AccessToDisposedClosure
|
|||
serviceScope.ServiceProvider |
|||
.GetService<ILogger<TextTemplateDefinitionInitializer>>()? |
|||
.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using Polly; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.TextTemplating; |
|||
public class TextTemplateDynamicInitializer : ITransientDependency |
|||
{ |
|||
public ILogger<TextTemplateDynamicInitializer> Logger { get; set; } |
|||
|
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected IOptions<AbpTextTemplatingCachingOptions> Options { get; } |
|||
protected IHostApplicationLifetime ApplicationLifetime { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected ITemplateDefinitionStore TemplateDefinitionStore { get; } |
|||
protected IStaticTemplateSaver StaticTemplateSaver { get; } |
|||
|
|||
public TextTemplateDynamicInitializer( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<AbpTextTemplatingCachingOptions> options, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
ITemplateDefinitionStore templateDefinitionStore, |
|||
IStaticTemplateSaver staticTemplateSaver) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
Options = options; |
|||
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
TemplateDefinitionStore = templateDefinitionStore; |
|||
StaticTemplateSaver = staticTemplateSaver; |
|||
|
|||
Logger = NullLogger<TextTemplateDynamicInitializer>.Instance; |
|||
} |
|||
|
|||
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!Options.Value.SaveStaticTemplateDefinitionToDatabase && !Options.Value.IsDynamicTemplateDefinitionStoreEnabled) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
if (runInBackground) |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null) |
|||
{ |
|||
cancellationToken = ApplicationLifetime.ApplicationStopping; |
|||
} |
|||
await ExecuteInitializationAsync(cancellationToken); |
|||
}, cancellationToken); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
return ExecuteInitializationAsync(cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
using (CancellationTokenProvider.Use(cancellationToken)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticTextTemplatesToDatabaseAsync(cancellationToken); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await PreCacheDynamicTextTemplatesAsync(cancellationToken); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// No need to log here since inner calls log
|
|||
} |
|||
} |
|||
|
|||
protected virtual async Task SaveStaticTextTemplatesToDatabaseAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.SaveStaticTemplateDefinitionToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await Policy |
|||
.Handle<Exception>(e => e is not OperationCanceledException) |
|||
.WaitAndRetryAsync( |
|||
8, |
|||
retryAttempt => TimeSpan.FromSeconds( |
|||
Volo.Abp.RandomHelper.GetRandom( |
|||
(int)Math.Pow(2, retryAttempt) * 8, |
|||
(int)Math.Pow(2, retryAttempt) * 12) |
|||
) |
|||
) |
|||
.ExecuteAsync(async _ => |
|||
{ |
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
await StaticTemplateSaver.SaveDefinitionTemplateAsync(); |
|||
await StaticTemplateSaver.SaveTemplateContentAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
}, cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task PreCacheDynamicTextTemplatesAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.IsDynamicTemplateDefinitionStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
// Pre-cache tempte definitions, so first request doesn't wait
|
|||
await TemplateDefinitionStore.GetAllAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // It will be cached in Initialize()
|
|||
} |
|||
} |
|||
} |
|||
@ -1,94 +0,0 @@ |
|||
using LINGYUN.Abp.Webhooks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace LINGYUN.Abp.WebhooksManagement; |
|||
public class WebhookDefinitionInitializer : ITransientDependency |
|||
{ |
|||
protected IRootServiceProvider RootServiceProvider { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected WebhooksManagementOptions WebhooksManagementOptions { get; } |
|||
public WebhookDefinitionInitializer( |
|||
IRootServiceProvider rootServiceProvider, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
IOptions<WebhooksManagementOptions> webhooksManagementOptions) |
|||
{ |
|||
RootServiceProvider = rootServiceProvider; |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
WebhooksManagementOptions = webhooksManagementOptions.Value; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
public async virtual Task InitializeDynamicWebhooks(CancellationToken cancellationToken) |
|||
{ |
|||
if (!WebhooksManagementOptions.SaveStaticWebhooksToDatabase && !WebhooksManagementOptions.IsDynamicWebhookStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
using var scope = RootServiceProvider.CreateScope(); |
|||
var applicationLifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
var token = applicationLifetime?.ApplicationStopping ?? cancellationToken; |
|||
try |
|||
{ |
|||
using (CancellationTokenProvider.Use(cancellationToken)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticNotificationsToDatabaseAsync(scope); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await PreCacheDynamicNotificationsAsync(scope); |
|||
} |
|||
} |
|||
catch (OperationCanceledException) |
|||
{ |
|||
// ignore
|
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
scope.ServiceProvider |
|||
.GetService<ILogger<WebhookDefinitionInitializer>>()? |
|||
.LogException(ex); |
|||
} |
|||
} |
|||
|
|||
private async Task SaveStaticNotificationsToDatabaseAsync(IServiceScope serviceScope) |
|||
{ |
|||
if (!WebhooksManagementOptions.SaveStaticWebhooksToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var saver = serviceScope.ServiceProvider.GetRequiredService<IStaticWebhookSaver>(); |
|||
|
|||
await saver.SaveAsync(); |
|||
} |
|||
|
|||
private async Task PreCacheDynamicNotificationsAsync(IServiceScope serviceScope) |
|||
{ |
|||
if (!WebhooksManagementOptions.IsDynamicWebhookStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var store = serviceScope.ServiceProvider.GetRequiredService<IDynamicWebhookDefinitionStore>(); |
|||
|
|||
await store.GetGroupsAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
using JetBrains.Annotations; |
|||
using LINGYUN.Abp.Webhooks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using Polly; |
|||
using System; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace LINGYUN.Abp.WebhooksManagement; |
|||
public class WebhookDynamicInitializer : ITransientDependency |
|||
{ |
|||
public ILogger<WebhookDynamicInitializer> Logger { get; set; } |
|||
|
|||
protected IServiceProvider ServiceProvider { get; } |
|||
protected IOptions<WebhooksManagementOptions> Options { get; } |
|||
[CanBeNull] |
|||
protected IHostApplicationLifetime ApplicationLifetime { get; } |
|||
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
|||
protected IDynamicWebhookDefinitionStore DynamicWebhookDefinitionStore { get; } |
|||
protected IStaticWebhookSaver StaticWebhookSaver { get; } |
|||
|
|||
public WebhookDynamicInitializer( |
|||
IServiceProvider serviceProvider, |
|||
IOptions<WebhooksManagementOptions> options, |
|||
ICancellationTokenProvider cancellationTokenProvider, |
|||
IDynamicWebhookDefinitionStore dynamicWebhookDefinitionStore, |
|||
IStaticWebhookSaver staticWebhookSaver) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
Options = options; |
|||
ApplicationLifetime = ServiceProvider.GetService<IHostApplicationLifetime>(); |
|||
CancellationTokenProvider = cancellationTokenProvider; |
|||
DynamicWebhookDefinitionStore = dynamicWebhookDefinitionStore; |
|||
StaticWebhookSaver = staticWebhookSaver; |
|||
|
|||
Logger = NullLogger<WebhookDynamicInitializer>.Instance; |
|||
} |
|||
|
|||
public virtual Task InitializeAsync(bool runInBackground, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (!Options.Value.SaveStaticWebhooksToDatabase && !Options.Value.IsDynamicWebhookStoreEnabled) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
if (runInBackground) |
|||
{ |
|||
Task.Run(async () => |
|||
{ |
|||
if (cancellationToken == default && ApplicationLifetime?.ApplicationStopping != null) |
|||
{ |
|||
cancellationToken = ApplicationLifetime.ApplicationStopping; |
|||
} |
|||
await ExecuteInitializationAsync(cancellationToken); |
|||
}, cancellationToken); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
return ExecuteInitializationAsync(cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task ExecuteInitializationAsync(CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
using (CancellationTokenProvider.Use(cancellationToken)) |
|||
{ |
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await SaveStaticWebhooksToDatabaseAsync(cancellationToken); |
|||
|
|||
if (CancellationTokenProvider.Token.IsCancellationRequested) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await PreCacheDynamicWebhooksAsync(cancellationToken); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// No need to log here since inner calls log
|
|||
} |
|||
} |
|||
|
|||
protected virtual async Task SaveStaticWebhooksToDatabaseAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.SaveStaticWebhooksToDatabase) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await Policy |
|||
.Handle<Exception>(e => e is not OperationCanceledException) |
|||
.WaitAndRetryAsync( |
|||
8, |
|||
retryAttempt => TimeSpan.FromSeconds( |
|||
Volo.Abp.RandomHelper.GetRandom( |
|||
(int)Math.Pow(2, retryAttempt) * 8, |
|||
(int)Math.Pow(2, retryAttempt) * 12) |
|||
) |
|||
) |
|||
.ExecuteAsync(async _ => |
|||
{ |
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
await StaticWebhookSaver.SaveAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // Polly will catch it
|
|||
} |
|||
}, cancellationToken); |
|||
} |
|||
|
|||
protected virtual async Task PreCacheDynamicWebhooksAsync(CancellationToken cancellationToken) |
|||
{ |
|||
if (!Options.Value.IsDynamicWebhookStoreEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
cancellationToken.ThrowIfCancellationRequested(); |
|||
|
|||
// Pre-cache webhoks, so first request doesn't wait
|
|||
await DynamicWebhookDefinitionStore.GetGroupsAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.LogException(ex); |
|||
|
|||
throw; // It will be cached in Initialize()
|
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,9 @@ |
|||
{ |
|||
"version": "9.3.5", |
|||
"version": "10.0.2", |
|||
"name": "my-app-single", |
|||
"private": true, |
|||
"dependencies": { |
|||
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "4.3.5", |
|||
"@abp/qrcode": "9.3.5" |
|||
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "5.0.2", |
|||
"@abp/qrcode": "10.0.2" |
|||
} |
|||
} |
|||
Loading…
Reference in new issue