feat(creator): overhaul Creator flow, editor duplication, and staging setup #83
@@ -30,6 +30,7 @@ services:
|
||||
- ASPNETCORE_ENVIRONMENT=Staging
|
||||
- ConnectionStrings__PostgresConnection=Host=db;Database=${POSTGRES_DB:-nexus_stage_db};Username=${POSTGRES_USER:-nexus_user_stage};Password=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
|
||||
- ConnectionStrings__QdrantConnection=http://qdrant:6334
|
||||
- Qdrant__ApiKey=${QDRANT_API_KEY:-}
|
||||
- ConnectionStrings__Neo4jConnection=bolt://neo4j:7687
|
||||
- Neo4j__Username=${NEO4J_USERNAME:-neo4j}
|
||||
- Neo4j__Password=${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
|
||||
|
||||
@@ -37,6 +37,12 @@ if grep -q "CHANGE_ME_TO_SECURE_ADMIN_PASSWORD" "$ENV_FILE"; then
|
||||
sed -i "s/NEXUS_ADMIN_PASSWORD=CHANGE_ME_TO_SECURE_ADMIN_PASSWORD/NEXUS_ADMIN_PASSWORD=$ADMIN_PASS/g" "$ENV_FILE"
|
||||
fi
|
||||
|
||||
if grep -q "^QDRANT_API_KEY=$" "$ENV_FILE" || grep -q "^QDRANT_API_KEY=[[:space:]]*$" "$ENV_FILE"; then
|
||||
echo "🔐 Generating secure random Qdrant API key in $ENV_FILE..."
|
||||
QD_KEY=$(openssl rand -hex 16)
|
||||
sed -i "s/^QDRANT_API_KEY=.*/QDRANT_API_KEY=$QD_KEY/g" "$ENV_FILE"
|
||||
fi
|
||||
|
||||
# Load staging variables for local execution context (needed for ports/migrations)
|
||||
# Clean up carriage returns just in case
|
||||
POSTGRES_USER=$(grep "^POSTGRES_USER=" "$ENV_FILE" | cut -d'=' -f2- | tr -d '\r')
|
||||
|
||||
@@ -55,7 +55,15 @@ public static class DependencyInjection
|
||||
|
||||
// Qdrant Client registration
|
||||
var qdrantUrl = configuration.GetConnectionString("QdrantConnection") ?? "http://localhost:6334";
|
||||
services.AddSingleton<QdrantClient>(sp => new QdrantClient(new Uri(qdrantUrl)));
|
||||
var qdrantApiKey = configuration["Qdrant:ApiKey"];
|
||||
services.AddSingleton<QdrantClient>(sp =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(qdrantApiKey))
|
||||
{
|
||||
return new QdrantClient(new Uri(qdrantUrl), apiKey: qdrantApiKey);
|
||||
}
|
||||
return new QdrantClient(new Uri(qdrantUrl));
|
||||
});
|
||||
|
||||
// Neo4j Driver registration (supports optional authentication)
|
||||
var neo4jUrl = configuration.GetConnectionString("Neo4jConnection") ?? "bolt://localhost:7687";
|
||||
|
||||
@@ -91,6 +91,10 @@ builder.Services.AddCascadingAuthenticationState();
|
||||
|
||||
builder.Services.AddApplication();
|
||||
builder.Services.AddInfrastructure(builder.Configuration);
|
||||
builder.Services.AddHealthChecks()
|
||||
.AddCheck<NexusReader.Web.Services.DatabaseHealthCheck>("Database")
|
||||
.AddCheck<NexusReader.Web.Services.QdrantHealthCheck>("Qdrant")
|
||||
.AddCheck<NexusReader.Web.Services.Neo4jHealthCheck>("Neo4j");
|
||||
|
||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(
|
||||
NexusReader.Application.DependencyInjection.Assembly,
|
||||
@@ -295,6 +299,7 @@ if (!allowRegistration || !allowPasswordReset)
|
||||
}
|
||||
|
||||
app.MapStaticAssets();
|
||||
app.MapHealthChecks("/health");
|
||||
app.MapHub<NexusReader.Infrastructure.RealTime.SyncHub>("/synchub");
|
||||
|
||||
// API endpoint for WASM client to fetch EPUB content
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using NexusReader.Data.Persistence;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NexusReader.Web.Services;
|
||||
|
||||
public class DatabaseHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly AppDbContext _dbContext;
|
||||
|
||||
public DatabaseHealthCheck(AppDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var canConnect = await _dbContext.Database.CanConnectAsync(cancellationToken);
|
||||
if (canConnect)
|
||||
{
|
||||
return HealthCheckResult.Healthy("Database is accessible.");
|
||||
}
|
||||
return HealthCheckResult.Unhealthy("Cannot connect to the database.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Database health check failed with exception.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Neo4j.Driver;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NexusReader.Web.Services;
|
||||
|
||||
public class Neo4jHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly IDriver _driver;
|
||||
|
||||
public Neo4jHealthCheck(IDriver driver)
|
||||
{
|
||||
_driver = driver;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _driver.VerifyConnectivityAsync();
|
||||
return HealthCheckResult.Healthy("Neo4j database is accessible.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Neo4j database connectivity check failed.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Qdrant.Client;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NexusReader.Web.Services;
|
||||
|
||||
public class QdrantHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly QdrantClient _qdrantClient;
|
||||
|
||||
public QdrantHealthCheck(QdrantClient qdrantClient)
|
||||
{
|
||||
_qdrantClient = qdrantClient;
|
||||
}
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Simple check: query collection existence to verify connection is alive
|
||||
_ = await _qdrantClient.CollectionExistsAsync("knowledge_units", cancellationToken);
|
||||
return HealthCheckResult.Healthy("Qdrant database is accessible.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Qdrant database health check failed.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user