Add hangfire

This commit is contained in:
Michał Zieliński
2025-10-12 18:28:14 +02:00
parent de5b8fbe16
commit b24aaab679
6 changed files with 152 additions and 0 deletions

View File

@@ -8,6 +8,9 @@
<ItemGroup>
<PackageReference Include="Google.Apis.Auth" Version="1.70.0" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.21" />
<PackageReference Include="Hangfire.Core" Version="1.8.21" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.21" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.17">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -1,7 +1,10 @@
using System.Text;
using BimAI.API.Services;
using BimAI.Infrastructure.Data;
using BimAI.Infrastructure.Jobs;
using BimAI.Infrastructure.Sync;
using Hangfire;
using Hangfire.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
@@ -18,6 +21,29 @@ builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Start Hangfire section
builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection"),
new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true,
SchemaName = "Hangfire"
}
)
);
builder.Services.AddHangfireServer(options =>
{
options.ServerName = builder.Configuration["Hangfire:ServerName"];
options.WorkerCount = builder.Configuration.GetValue<int>("Hangfire:WorkerCount", 5);
});
// End Hangfire section
// Start auth section
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = jwtSettings["SecretKey"];
@@ -65,7 +91,22 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseHangfireDashboard(builder.Configuration["Hangfire:DashboardPath"] ?? "/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new HangfireAuthorizationFilter() },
DashboardTitle = "BimAI - Job Dashboard"
});
app.UseAuthorization();
app.UseAuthorization();
app.MapControllers();
RecurringJob.AddOrUpdate<ProductSyncJob>(
"product-sync",
job => job.ExecuteAsync(),
Cron.Daily(2, 0), // Every day at 2:00 AM
new RecurringJobOptions
{
TimeZone = TimeZoneInfo.Local
});
app.Run();

View File

@@ -0,0 +1,20 @@
using Hangfire.Dashboard;
namespace BimAI.API.Services;
public class HangfireAuthorizationFilter: IDashboardAsyncAuthorizationFilter
{
public Task<bool> AuthorizeAsync(DashboardContext context)
{
var httpContext = context.GetHttpContext();
var env = httpContext.RequestServices.GetService<IWebHostEnvironment>();
if (env.IsDevelopment())
{
return Task.FromResult(true);
}
var isAuthenticated = httpContext.User.Identity?.IsAuthenticated ?? false;
return Task.FromResult(isAuthenticated);
}
}

View File

@@ -0,0 +1,31 @@
using BimAI.Infrastructure.Sync;
using Microsoft.Extensions.Logging;
namespace BimAI.Infrastructure.Jobs;
public class ProductSyncJob
{
private readonly ProductSyncService _productSyncService;
private readonly ILogger<ProductSyncJob> _logger;
public ProductSyncJob(ProductSyncService productSyncService, ILogger<ProductSyncJob> logger)
{
_productSyncService = productSyncService;
_logger = logger;
}
public async Task ExecuteAsync()
{
_logger.LogInformation("Starting product sync...");
try
{
await _productSyncService.RunAsync();
_logger.LogInformation("Product sync finished.");
} catch (Exception ex)
{
_logger.LogError(ex, "Error during product sync.");
throw;
}
}
}

57
docker-compose.yml Normal file
View File

@@ -0,0 +1,57 @@
services:
mssql:
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: bimai-mssql
hostname: bimai-mssql
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=BimAI_Dev_Pass_2024!
- MSSQL_PID=Developer
ports:
- "1433:1433"
volumes:
- mssql-data:/var/opt/mssql
- ./docker/mssql/init:/docker-entrypoint-initdb.d
networks:
- bimai-network
healthcheck:
test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "BimAI_Dev_Pass_2024!" -Q "SELECT 1" || exit 1
interval: 10s
timeout: 3s
retries: 10
start_period: 10s
mongodb:
image: mongo:7.0
container_name: bimai-mongodb
hostname: bimai-mongodb
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=BimAI_Mongo_2024!
- MONGO_INITDB_DATABASE=bimai
ports:
- "27017:27017"
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
- ./docker/mongodb/init:/docker-entrypoint-initdb.d
networks:
- bimai-network
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
bimai-network:
driver: bridge
volumes:
mssql-data:
name: bimai-mssql-data
mongodb-data:
name: bimai-mongodb-data
mongodb-config:
name: bimai-mongodb-config