feat(data): add task numbers schema, allocator, and backfill migration
TaskEntity.Number is a global, monotonically increasing, never-reused integer (displayed as #123), allocated from AppSettingsEntity.NextTaskNumber via a single UPDATE...RETURNING statement rather than MAX(number)+1, which would reissue a deleted task's number. Both insert paths (TaskRepository. AddAsync and CreateChildAsync) route through the new TaskNumberAllocator, with a bounded retry on a unique-index collision. One migration adds the columns, backfills existing rows in creation order, and creates the unique index afterwards. Data-layer only; MCP/UI wiring is later slices.
This commit is contained in:
@@ -13,6 +13,9 @@ public class AppSettingsEntityConfiguration : IEntityTypeConfiguration<AppSettin
|
||||
builder.HasKey(s => s.Id);
|
||||
builder.Property(s => s.Id).HasColumnName("id").ValueGeneratedNever();
|
||||
|
||||
builder.Property(s => s.NextTaskNumber)
|
||||
.HasColumnName("next_task_number").IsRequired().HasDefaultValue(1);
|
||||
|
||||
builder.Property(s => s.DefaultClaudeInstructions)
|
||||
.HasColumnName("default_claude_instructions").IsRequired().HasDefaultValue(string.Empty);
|
||||
builder.Property(s => s.DefaultModel)
|
||||
|
||||
@@ -66,6 +66,7 @@ public class TaskEntityConfiguration : IEntityTypeConfiguration<TaskEntity>
|
||||
|
||||
builder.HasKey(t => t.Id);
|
||||
builder.Property(t => t.Id).HasColumnName("id");
|
||||
builder.Property(t => t.Number).HasColumnName("number").IsRequired();
|
||||
builder.Property(t => t.ListId).HasColumnName("list_id").IsRequired();
|
||||
builder.Property(t => t.Title).HasColumnName("title").IsRequired();
|
||||
builder.Property(t => t.Description).HasColumnName("description");
|
||||
@@ -136,6 +137,7 @@ public class TaskEntityConfiguration : IEntityTypeConfiguration<TaskEntity>
|
||||
.WithOne(w => w.Task)
|
||||
.HasForeignKey<WorktreeEntity>(w => w.TaskId);
|
||||
|
||||
builder.HasIndex(t => t.Number).IsUnique().HasDatabaseName("idx_tasks_number");
|
||||
builder.HasIndex(t => t.ListId).HasDatabaseName("idx_tasks_list_id");
|
||||
builder.HasIndex(t => t.Status).HasDatabaseName("idx_tasks_status");
|
||||
builder.HasIndex(t => new { t.ListId, t.SortOrder }).HasDatabaseName("idx_tasks_list_sort");
|
||||
|
||||
Reference in New Issue
Block a user