fix(storage): use strict INSERT for batch issue creation (GH#956)
Add insertIssuesStrict function that uses plain INSERT instead of INSERT OR IGNORE. Update bulkInsertIssues and transactional CreateIssues to use the strict variant. This fixes a race condition where INSERT OR IGNORE could silently skip duplicate insertions, but the code would still attempt to record events for those "inserted" issues, causing FOREIGN KEY constraint failures. The strict INSERT will now fail explicitly if a duplicate is encountered, which should never happen since checkForExistingIDs runs first within the same transaction. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -297,14 +297,15 @@ func (t *sqliteTxStorage) CreateIssues(ctx context.Context, issues []*types.Issu
|
||||
}
|
||||
|
||||
// GH#956: Check for conflicts with existing IDs in database before inserting.
|
||||
// This prevents INSERT OR IGNORE from silently skipping duplicates, which would
|
||||
// cause FK constraint failures when recording events for non-inserted issues.
|
||||
// This prevents duplicates from causing FK constraint failures when recording events.
|
||||
if err := checkForExistingIDs(ctx, t.conn, issues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Insert all issues
|
||||
if err := insertIssues(ctx, t.conn, issues); err != nil {
|
||||
// Insert all issues using strict mode (fails on duplicates)
|
||||
// GH#956: Use insertIssuesStrict instead of insertIssues to prevent FK constraint errors
|
||||
// from silent INSERT OR IGNORE failures under concurrent load.
|
||||
if err := insertIssuesStrict(ctx, t.conn, issues); err != nil {
|
||||
return fmt.Errorf("failed to insert issues: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user