This commit is contained in:
2025-12-12 12:56:22 +08:00
parent 46e209081d
commit cd43abc7eb
7 changed files with 100 additions and 42 deletions

View File

@@ -12,6 +12,9 @@ using Atomx.Data.Services;
using Atomx.Utils.Json.Converts; using Atomx.Utils.Json.Converts;
using Blazored.LocalStorage; using Blazored.LocalStorage;
using FluentValidation; using FluentValidation;
using Hangfire;
using Hangfire.PostgreSql;
using Hangfire.PostgreSql.Factories;
using Mapster; using Mapster;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
@@ -19,7 +22,9 @@ using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Npgsql;
using Scalar.AspNetCore; using Scalar.AspNetCore;
using Serilog; using Serilog;
using System.Globalization; using System.Globalization;
@@ -62,7 +67,6 @@ builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClientApiService(builder.Configuration["WebApi:ServerUrl"] ?? "http://localhost"); builder.Services.AddHttpClientApiService(builder.Configuration["WebApi:ServerUrl"] ?? "http://localhost");
// ע<><D7A2> LocalizationProvider <20><> Server ģʽ<C4A3><CABD>ʹ<EFBFBD><CAB9> // ע<><D7A2> LocalizationProvider <20><> Server ģʽ<C4A3><CABD>ʹ<EFBFBD><CAB9>
// Use Scoped to avoid consuming scoped services from singleton
builder.Services.AddScoped<ILocalizationProvider, LocalizationProvider>(); builder.Services.AddScoped<ILocalizationProvider, LocalizationProvider>();
builder.Services.AddScoped<ILocalizationService, LocalizationService>(); builder.Services.AddScoped<ILocalizationService, LocalizationService>();
builder.Services.AddTransient(typeof(IStringLocalizer<>), typeof(JsonStringLocalizer<>)); builder.Services.AddTransient(typeof(IStringLocalizer<>), typeof(JsonStringLocalizer<>));
@@ -97,13 +101,36 @@ var connection = builder.Configuration.GetConnectionString("DefaultConnection")
builder.Services.AddDbContext<DataContext>(options => options.UseNpgsql(connection, p => p.MigrationsHistoryTable("__DbMigrationsHistory"))); builder.Services.AddDbContext<DataContext>(options => options.UseNpgsql(connection, p => p.MigrationsHistoryTable("__DbMigrationsHistory")));
// Redis <20><><EFBFBD><EFBFBD> // Redis <20><><EFBFBD><EFBFBD>
var redisConnection = builder.Configuration.GetConnectionString("cache"); var redisConnection = builder.Configuration.GetConnectionString("RedisConnection");
builder.Services.AddStackExchangeRedisCache(options => builder.Services.AddStackExchangeRedisCache(options =>
{ {
options.Configuration = redisConnection; options.Configuration = redisConnection;
options.InstanceName = builder.Configuration["RedisCache:InstanceName"]; options.InstanceName = builder.Configuration["RedisCache:InstanceName"];
}); });
// Hangfire <20><><EFBFBD><EFBFBD>
var hangfireConnection = builder.Configuration.GetConnectionString("HangfireConnection")
?? throw new InvalidOperationException("Connection string 'HangfireConnection' not found.");
// <20><><EFBFBD><EFBFBD>hangfire<72><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PostgreSQL<51>
builder.Services.AddHangfire(config =>
{
config.UsePostgreSqlStorage(
options =>
{
options.UseNpgsqlConnection(hangfireConnection);
},
new PostgreSqlStorageOptions
{
// Additional PostgreSQL storage options
PrepareSchemaIfNecessary = true,
QueuePollInterval = TimeSpan.FromSeconds(10) // <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>
}).UseFilter(new AutomaticRetryAttribute { Attempts = 3 });
});
// <20><><EFBFBD><EFBFBD> Hangfire <20>DZ<EFBFBD><C7B1>̺ͷ<CCBA><CDB7><EFBFBD><EFBFBD><EFBFBD>
builder.Services.AddHangfireServer();
// <20><>Ӧѹ<D3A6><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> // <20><>Ӧѹ<D3A6><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
builder.Services.AddResponseCompression(options => builder.Services.AddResponseCompression(options =>
{ {
@@ -222,6 +249,10 @@ app.UseRequestLocalization(new RequestLocalizationOptions
// app.MapHub<ChatHub>("/hubs/chat"); // app.MapHub<ChatHub>("/hubs/chat");
// app.MapHub<NotificationHub>("/hubs/notification"); // app.MapHub<NotificationHub>("/hubs/notification");
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
});
app.MapControllers(); app.MapControllers();
// Blazor <20><><EFBFBD>ã<EFBFBD>Server + WASM render modes<65><73> // Blazor <20><><EFBFBD>ã<EFBFBD>Server + WASM render modes<65><73>

View File

@@ -1,25 +1,37 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Host=8.129.21.55;Port=6543;Username=postgres;Password=docker-7788@postgres.com;Database=dev_atomx;", "DefaultConnection": "Host=8.129.21.55;Port=6543;Username=postgres;Password=docker-7788@postgres.com;Database=dev_atomx;",
"cache": "8.129.21.55:6999,password=docker-7788@redis.com" "HangfireConnection": "Host=8.129.21.55;Port=6543;Username=postgres;Password=docker-7788@postgres.com;Database=dev_hangfire;",
"RedisConnection": "8.129.21.55:6999,password=docker-7788@redis.com"
}, },
"RedisCache": { "RedisCache": {
"IPAddress": "8.129.21.55",
"Port": "6999",
"Password": "docker-7788@redis.com",
"InstanceName": "Atomx.Redis." "InstanceName": "Atomx.Redis."
}, },
"Orleans": {
},
"Hangfire": {
"WorkerCount": 2, //并发工作线程数
"Queues": [ "default" ], //队列名称
"RetryAttempts": 3 //失败重试次数
},
"WebApi": {
"ServerUrl": "http://localhost:5259"
},
"Authentication": { "Authentication": {
"JwtBearer": { "JwtBearer": {
"Issuer": "http://api.sampleapi.com", "Issuer": "http://jwt.atomlust.com", //谁颁发的token
"Audience": "SampleApi", "Audience": "atomx", //token的受众
"SecurityKey": "SecurityKey23456SecurityKey23456", "SecurityKey": "SecurityKey23456SecurityKey23456", //密钥
"ClockSkew": "10", "ClockSkew": "10", //允许的服务器时间偏差,单位为分钟
"AccessTokenExpirationMinutes": "60", "AccessTokenExpirationMinutes": "60", //访问令牌过期时间,单位为分钟
"RefreshTokenExpirationMinutes": "60", "RefreshTokenExpirationMinutes": "60", //刷新令牌过期时间,单位为分钟
"MaxRefreshTokensPerUser": "3" "MaxRefreshTokensPerUser": "3" //每个用户允许的最大刷新令牌数量
}, },
"Cookie": { "Cookie": {
"Name": ".Atomx.Auth", "Name": ".Atomx.Auth",
@@ -31,10 +43,6 @@
} }
}, },
"WebApi": {
"ServerUrl": "http://localhost:5259"
},
"Monitoring": { "Monitoring": {
"Enabled": true, "Enabled": true,
"ExcludeHealthChecks": true, "ExcludeHealthChecks": true,
@@ -70,16 +78,16 @@
"Seq": { "Seq": {
"ServerUrl": "http://log.atomlust.com/", "ServerUrl": "http://log.atomlust.com/",
"ApiKey": "bBWmvSE2LJh4KsMeidvF", "ApiKey": "bBWmvSE2LJh4KsMeidvF",
"MinimumLevel": "Warning", "MinimumLevel": "Information",
"LevelOverride": { "LevelOverride": {
"Microsoft": "Warning" "Microsoft": "Information"
} }
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Warning", "Default": "Information",
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Information"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*"

View File

@@ -7,7 +7,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Services\" />
<Folder Include="Configuration\" /> <Folder Include="Configuration\" />
<Folder Include="Events\" /> <Folder Include="Events\" />
</ItemGroup> </ItemGroup>

View File

@@ -1,7 +0,0 @@
namespace Atomx.Core
{
public class Class1
{
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
namespace Atomx.Core.Jos
{
/// <summary>
/// 多语言本地化任务
/// </summary>
public partial class LocalizationJob
{
readonly ILogger<LocalizationJob> _logger;
public LocalizationJob(ILogger<LocalizationJob> logger)
{
_logger = logger;
}
public void Execute()
{
_logger.LogInformation("LocalizationJob executed at: {time}", DateTimeOffset.Now);
// 在这里添加多语言本地化的具体任务逻辑
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Atomx.Core.Jos
{
/// <summary>
/// 多语言本地化任务
/// </summary>
public class LocalizationJobs
{
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Atomx.Core.Jos
{
public partial interface IBackgroundJobsService
{
}
public partial class BackgroundJobsService : IBackgroundJobsService
{
}
}