Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
# context since the per-section split (nobodies-collective/Humans#858).
run: |
dotnet tool install --global dotnet-ef --version 10.0.*
for ctx in HumansDbContext SystemSettingsDbContext ContainersDbContext; do
for ctx in HumansDbContext SystemSettingsDbContext ContainersDbContext AgentDbContext; do
dotnet ef migrations has-pending-model-changes \
--context "$ctx" \
--project src/Humans.Infrastructure \
Expand Down Expand Up @@ -174,7 +174,7 @@ jobs:
- name: Apply per-section baselines from scratch
run: |
set -euo pipefail
for ctx in SystemSettingsDbContext ContainersDbContext; do
for ctx in SystemSettingsDbContext ContainersDbContext AgentDbContext; do
db="humans_$(echo "$ctx" | tr '[:upper:]' '[:lower:]')"
docker exec "${{ steps.pg.outputs.container }}" \
psql -U humans -d postgres -c "CREATE DATABASE $db"
Expand All @@ -193,7 +193,7 @@ jobs:
# Belt-and-suspenders: Layer 1 already runs this in the build job,
# but re-checking after a real apply guards against any state the
# apply step might have observed differently from a static check.
for ctx in HumansDbContext SystemSettingsDbContext ContainersDbContext; do
for ctx in HumansDbContext SystemSettingsDbContext ContainersDbContext AgentDbContext; do
dotnet ef migrations has-pending-model-changes \
--context "$ctx" \
--project src/Humans.Infrastructure \
Expand Down
35 changes: 35 additions & 0 deletions src/Humans.Infrastructure/Data/AgentDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Humans.Domain.Entities;
using Humans.Infrastructure.Data.Configurations.Agent;
using Microsoft.EntityFrameworkCore;

namespace Humans.Infrastructure.Data;

/// <summary>
/// Per-section database context for the Agent section
/// (nobodies-collective/Humans#858): maps only <c>agent_conversations</c>,
/// <c>agent_messages</c> and <c>agent_settings</c>, with its own
/// <c>__EFMigrationsHistory_Agent</c> table and migrations under
/// <c>Migrations/Agent/</c>. Same database, same connection — the split
/// is a code-side partition of the EF model.
/// </summary>
/// <remarks>
/// Internal-sealed like <see cref="HumansDbContext"/> (issue #750): repositories
/// are the only consumers. Configurations are applied explicitly (not by
/// assembly scanning) so this model can never accrete another section's tables.
/// </remarks>
internal sealed class AgentDbContext(DbContextOptions<AgentDbContext> options)
: DbContext(options)
{
public DbSet<AgentConversation> AgentConversations => Set<AgentConversation>();
public DbSet<AgentMessage> AgentMessages => Set<AgentMessage>();
public DbSet<AgentSettings> AgentSettings => Set<AgentSettings>();

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.ApplyConfiguration(new AgentConversationConfiguration());
builder.ApplyConfiguration(new AgentMessageConfiguration());
builder.ApplyConfiguration(new AgentSettingsConfiguration());
}
}
33 changes: 33 additions & 0 deletions src/Humans.Infrastructure/Data/AgentDbContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace Humans.Infrastructure.Data;

/// <summary>
/// Design-time factory used by <c>dotnet ef … --context AgentDbContext</c>.
/// Mirrors <see cref="HumansDbContextFactory"/>; the migrations-history table must
/// match the runtime registration so CI's from-scratch apply records baselines in
/// <c>__EFMigrationsHistory_Agent</c>.
/// </summary>
internal sealed class AgentDbContextFactory : IDesignTimeDbContextFactory<AgentDbContext>
{
public AgentDbContext CreateDbContext(string[] args)
{
var connectionString =
Environment.GetEnvironmentVariable("ConnectionStrings__DefaultConnection")
?? "Host=localhost;Database=humans_design_time;Username=humans;Password=humans";

var optionsBuilder = new DbContextOptionsBuilder<AgentDbContext>();
optionsBuilder.UseNpgsql(
connectionString,
npgsqlOptions =>
{
npgsqlOptions.UseNodaTime();
npgsqlOptions.MigrationsAssembly("Humans.Infrastructure");
npgsqlOptions.MigrationsHistoryTable("__EFMigrationsHistory_Agent");
npgsqlOptions.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
});

return new AgentDbContext(optionsBuilder.Options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Humans.Infrastructure.Data.Configurations;
namespace Humans.Infrastructure.Data.Configurations.Agent;

public class AgentConversationConfiguration : IEntityTypeConfiguration<AgentConversation>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Humans.Infrastructure.Data.Configurations;
namespace Humans.Infrastructure.Data.Configurations.Agent;

public class AgentMessageConfiguration : IEntityTypeConfiguration<AgentMessage>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using NodaTime;

namespace Humans.Infrastructure.Data.Configurations;
namespace Humans.Infrastructure.Data.Configurations.Agent;

public class AgentSettingsConfiguration : IEntityTypeConfiguration<AgentSettings>
{
Expand Down
4 changes: 1 addition & 3 deletions src/Humans.Infrastructure/Data/HumansDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ internal sealed class HumansDbContext(DbContextOptions<HumansDbContext> options)
public DbSet<FeedbackMessage> FeedbackMessages => Set<FeedbackMessage>();
public DbSet<Issue> Issues => Set<Issue>();
public DbSet<IssueComment> IssueComments => Set<IssueComment>();
public DbSet<AgentConversation> AgentConversations => Set<AgentConversation>();
public DbSet<AgentMessage> AgentMessages => Set<AgentMessage>();
public DbSet<AgentSettings> AgentSettings => Set<AgentSettings>();
public DbSet<AccountMergeRequest> AccountMergeRequests => Set<AccountMergeRequest>();
public DbSet<CommunicationPreference> CommunicationPreferences => Set<CommunicationPreference>();
public DbSet<BudgetYear> BudgetYears => Set<BudgetYear>();
Expand Down Expand Up @@ -139,6 +136,7 @@ public DbSet<HoldedExpenseOutboxEvent> HoldedExpenseOutboxEvents
[
typeof(Configurations.SystemSettings.SystemSettingConfiguration).Namespace!,
typeof(Configurations.Containers.ContainerConfiguration).Namespace!,
typeof(Configurations.Agent.AgentConversationConfiguration).Namespace!,
];

protected override void OnModelCreating(ModelBuilder builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static IServiceCollection AddHumansPersistence(
// HumansDbContext by DatabaseMigrationHostedService in registration order.
services.AddSectionDbContext<SystemSettingsDbContext>(sentinelTable: "system_settings");
services.AddSectionDbContext<ContainersDbContext>(sentinelTable: "containers");
services.AddSectionDbContext<AgentDbContext>(sentinelTable: "agent_conversations");

services.AddHostedService<DatabaseMigrationHostedService>();

Expand Down
Loading
Loading