fix: sync ID counters after import to prevent collisions

When importing issues with explicit high IDs (e.g., bd-100), the
issue_counters table wasn't being updated. This caused the next
auto-generated issue to collide with existing IDs (bd-4 instead of bd-101).

Changes:
- Add SyncAllCounters() to scan all issues and update counters atomically
- Add SyncCounterForPrefix() for granular counter synchronization
- Call SyncAllCounters() in import command after creating issues
- Add comprehensive tests for counter sync functionality
- Update TestImportCounterSyncAfterHighID to verify fix

The fix uses a single efficient SQL query to prevent ID collisions
with subsequently auto-generated issues.
This commit is contained in:
v4rgas
2025-10-13 19:56:34 -03:00
committed by Steve Yegge
parent 187d291647
commit 73f5acadfa
4 changed files with 95 additions and 0 deletions

View File

@@ -479,3 +479,68 @@ func TestMultiProcessIDGeneration(t *testing.T) {
t.Errorf("Expected no errors, got %d", len(errors))
}
}
func TestSyncCounterForPrefix(t *testing.T) {
store, cleanup := setupTestDB(t)
defer cleanup()
ctx := context.Background()
// Set config for issue prefix
if err := store.SetConfig(ctx, "issue_prefix", "bd"); err != nil {
t.Fatalf("Failed to set issue prefix: %v", err)
}
// Create a few auto-generated issues (bd-1, bd-2, bd-3)
for i := 0; i < 3; i++ {
issue := &types.Issue{
Title: "Auto issue",
Status: types.StatusOpen,
Priority: 1,
IssueType: types.TypeTask,
}
if err := store.CreateIssue(ctx, issue, "test"); err != nil {
t.Fatalf("Failed to create issue: %v", err)
}
}
// Sync counter to 100
if err := store.SyncCounterForPrefix(ctx, "bd", 100); err != nil {
t.Fatalf("SyncCounterForPrefix failed: %v", err)
}
// Next auto-generated issue should be bd-101
issue := &types.Issue{
Title: "After sync",
Status: types.StatusOpen,
Priority: 1,
IssueType: types.TypeTask,
}
if err := store.CreateIssue(ctx, issue, "test"); err != nil {
t.Fatalf("Failed to create issue after sync: %v", err)
}
if issue.ID != "bd-101" {
t.Errorf("Expected ID bd-101 after sync, got %s", issue.ID)
}
// Syncing to a lower value should not decrease the counter
if err := store.SyncCounterForPrefix(ctx, "bd", 50); err != nil {
t.Fatalf("SyncCounterForPrefix failed: %v", err)
}
// Next issue should still be bd-102, not bd-51
issue2 := &types.Issue{
Title: "After lower sync",
Status: types.StatusOpen,
Priority: 1,
IssueType: types.TypeTask,
}
if err := store.CreateIssue(ctx, issue2, "test"); err != nil {
t.Fatalf("Failed to create issue: %v", err)
}
if issue2.ID != "bd-102" {
t.Errorf("Expected ID bd-102 (counter should not decrease), got %s", issue2.ID)
}
}