mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-07 23:34:17 +02:00
fix: Update appsettings.example.json to include server URLs
This commit is contained in:
@@ -13,16 +13,31 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
// ── First-run setup ──────────────────────────────────────────────────────────
|
// ── First-run setup (once) ──────────────────────────────────────────────────
|
||||||
FirstRunSetup.EnsureAppSettings();
|
FirstRunSetup.EnsureAppSettings();
|
||||||
|
|
||||||
|
// ── Bootstrap logger (replaced by full Serilog once host starts) ────────────
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.WriteTo.Console()
|
||||||
|
.CreateBootstrapLogger();
|
||||||
|
|
||||||
|
// ── Auto-restart loop ───────────────────────────────────────────────────────
|
||||||
|
const int maxConsecutiveFailures = 5;
|
||||||
|
var consecutiveFailures = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var startTime = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// ── Serilog ──────────────────────────────────────────────────────────────────
|
// ── Serilog ──────────────────────────────────────────────────────────
|
||||||
builder.Host.UseSerilog((context, config) =>
|
builder.Host.UseSerilog((context, config) =>
|
||||||
config.ReadFrom.Configuration(context.Configuration));
|
config.ReadFrom.Configuration(context.Configuration));
|
||||||
|
|
||||||
// ── SQLite + EF Core ──────────────────────────────────────────────────────────
|
// ── SQLite + EF Core ─────────────────────────────────────────────────
|
||||||
var defaultDbPath = Path.Combine(AppContext.BaseDirectory, "echohub.db");
|
var defaultDbPath = Path.Combine(AppContext.BaseDirectory, "echohub.db");
|
||||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
|
||||||
?? $"Data Source={defaultDbPath}";
|
?? $"Data Source={defaultDbPath}";
|
||||||
@@ -30,7 +45,7 @@ var connectionString = builder.Configuration.GetConnectionString("DefaultConnect
|
|||||||
builder.Services.AddDbContext<EchoHubDbContext>(options =>
|
builder.Services.AddDbContext<EchoHubDbContext>(options =>
|
||||||
options.UseSqlite(connectionString));
|
options.UseSqlite(connectionString));
|
||||||
|
|
||||||
// ── JWT Authentication ────────────────────────────────────────────────────────
|
// ── JWT Authentication ───────────────────────────────────────────────
|
||||||
var jwtSecret = builder.Configuration["Jwt:Secret"]
|
var jwtSecret = builder.Configuration["Jwt:Secret"]
|
||||||
?? throw new InvalidOperationException("Jwt:Secret must be configured.");
|
?? throw new InvalidOperationException("Jwt:Secret must be configured.");
|
||||||
var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "EchoHub.Server";
|
var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "EchoHub.Server";
|
||||||
@@ -74,11 +89,11 @@ builder.Services.AddAuthentication(options =>
|
|||||||
|
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
|
|
||||||
// ── Controllers + SignalR ───────────────────────────────────────────────────────
|
// ── Controllers + SignalR ────────────────────────────────────────────
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddSignalR();
|
builder.Services.AddSignalR();
|
||||||
|
|
||||||
// ── Services ──────────────────────────────────────────────────────────────────
|
// ── Services ─────────────────────────────────────────────────────────
|
||||||
builder.Services.AddSingleton<JwtTokenService>();
|
builder.Services.AddSingleton<JwtTokenService>();
|
||||||
builder.Services.AddSingleton<PresenceTracker>();
|
builder.Services.AddSingleton<PresenceTracker>();
|
||||||
builder.Services.AddSingleton<ImageToAsciiService>();
|
builder.Services.AddSingleton<ImageToAsciiService>();
|
||||||
@@ -89,7 +104,7 @@ builder.Services.AddHttpClient("ImageDownload", client =>
|
|||||||
client.MaxResponseContentBufferSize = 10 * 1024 * 1024; // 10 MB
|
client.MaxResponseContentBufferSize = 10 * 1024 * 1024; // 10 MB
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Rate Limiting ────────────────────────────────────────────────────────────
|
// ── Rate Limiting ────────────────────────────────────────────────────
|
||||||
builder.Services.AddRateLimiter(options =>
|
builder.Services.AddRateLimiter(options =>
|
||||||
{
|
{
|
||||||
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||||
@@ -116,7 +131,7 @@ builder.Services.AddRateLimiter(options =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── CORS ─────────────────────────────────────────────────────────────────────
|
// ── CORS ─────────────────────────────────────────────────────────────
|
||||||
var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>();
|
var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>();
|
||||||
|
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
@@ -134,19 +149,49 @@ builder.Services.AddCors(options =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
await using var app = builder.Build();
|
||||||
|
|
||||||
// ── Database initialization ───────────────────────────────────────────────────
|
// ── Database initialization ──────────────────────────────────────────
|
||||||
await DatabaseSetup.InitializeAsync(app.Services);
|
await DatabaseSetup.InitializeAsync(app.Services);
|
||||||
|
|
||||||
// ── Middleware ─────────────────────────────────────────────────────────────────
|
// ── Middleware ────────────────────────────────────────────────────────
|
||||||
app.UseCors();
|
app.UseCors();
|
||||||
app.UseRateLimiter();
|
app.UseRateLimiter();
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
// ── Routing ───────────────────────────────────────────────────────────────────
|
// ── Routing ──────────────────────────────────────────────────────────
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
app.MapHub<ChatHub>(HubConstants.ChatHubPath);
|
app.MapHub<ChatHub>(HubConstants.ChatHubPath);
|
||||||
|
|
||||||
app.Run();
|
await app.RunAsync();
|
||||||
|
|
||||||
|
// Graceful shutdown (Ctrl+C) — exit the loop
|
||||||
|
Log.Information("Server shut down gracefully");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var uptime = DateTimeOffset.UtcNow - startTime;
|
||||||
|
|
||||||
|
// If server ran for over 60 seconds, it's a runtime crash — reset failure count
|
||||||
|
if (uptime.TotalSeconds > 60)
|
||||||
|
consecutiveFailures = 0;
|
||||||
|
|
||||||
|
consecutiveFailures++;
|
||||||
|
Log.Fatal(ex, "Server crashed after {Uptime:g} (failure {Count}/{Max})",
|
||||||
|
uptime, consecutiveFailures, maxConsecutiveFailures);
|
||||||
|
|
||||||
|
if (consecutiveFailures >= maxConsecutiveFailures)
|
||||||
|
{
|
||||||
|
Log.Fatal("Too many consecutive failures, server will not restart");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var delaySeconds = Math.Min(Math.Pow(2, consecutiveFailures), 30);
|
||||||
|
Log.Information("Restarting server in {Delay}s...", delaySeconds);
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(delaySeconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.CloseAndFlush();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"Urls": "http://0.0.0.0:5000",
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Data Source=echohub.db"
|
"DefaultConnection": "Data Source=echohub.db"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user