Skip to content

Conversation

@akshayutture-augment
Copy link

… deadlocks on MySQL (#80329)

* Split subquery when cleaning annotations

* update comment

* Raise batch size, now that we pay attention to it

* Iterate in batches

* Separate cancellable batch implementation to allow for multi-statement callbacks, add overload for single-statement use

* Use split-out utility in outer batching loop so it respects context cancellation

* guard against empty queries

* Use SQL parameters

* Use same approach for tags

* drop unused function

* Work around parameter limit on sqlite for large batches

* Bulk insert test data in DB

* Refactor test to customise test data creation

* Add test for catching SQLITE_MAX_VARIABLE_NUMBER limit

* Turn annotation cleanup test to integration tests

* lint

---------

Co-authored-by: Sofia Papagiannaki <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@akshayutture-augment
Copy link
Author

@greptileai

@greptile-apps
Copy link

greptile-apps bot commented Nov 14, 2025

Greptile Overview

Confidence Score: 2/5

  • This PR has critical performance concerns due to the 10x increase in cleanup frequency
  • The fetch-then-delete pattern is a solid improvement to prevent MySQL deadlocks, but two critical issues significantly lower the score: (1) the cleanup interval reduced from 10 to 1 minute will cause 10x more database load, and (2) incorrect log.Error usage will pollute error logs with routine operational messages
  • Pay close attention to pkg/services/cleanup/cleanup.go (cleanup interval change) and pkg/services/annotations/annotationsimpl/xorm_store.go (logging issues)

Important Files Changed

File Analysis

Filename Score Overview
pkg/services/annotations/annotationsimpl/xorm_store.go 2/5 Split cleanup into fetch-then-delete pattern to avoid MySQL deadlocks; added SQLite parameter limit handling; critical issue: using log.Error for non-error messages
pkg/services/cleanup/cleanup.go 1/5 Cleanup interval reduced from 10 minutes to 1 minute - 10x increase in execution frequency could significantly impact database performance
pkg/services/annotations/annotationsimpl/cleanup_test.go 4/5 Refactored tests for better isolation and batch insert performance; added test for large batch sizes with SQLite parameter limits

Sequence Diagram

sequenceDiagram
    participant CS as CleanUpService
    participant AC as AnnotationCleaner
    participant XR as xormRepositoryImpl
    participant DB as Database
    
    CS->>CS: ticker (1 minute interval)
    CS->>AC: Run(ctx, cfg)
    
    alt MaxAge cleanup
        AC->>XR: CleanAnnotations(ctx, cfg, annotationType)
        loop until done or cancelled
            XR->>DB: fetchIDs(table, condition)
            DB-->>XR: []int64 IDs
            alt SQLite with large batch
                XR->>XR: Build DELETE with inline IDs
            else
                XR->>XR: Build DELETE with placeholders
            end
            XR->>DB: deleteByIDs(table, ids)
            DB-->>XR: affected rows
            alt affected == 0
                XR-->>AC: totalAffected
            end
        end
    end
    
    alt MaxCount cleanup
        AC->>XR: CleanAnnotations(ctx, cfg, annotationType)
        loop until done or cancelled
            XR->>DB: fetchIDs with LIMIT/OFFSET
            DB-->>XR: []int64 IDs
            XR->>DB: deleteByIDs(table, ids)
            DB-->>XR: affected rows
        end
    end
    
    AC->>XR: CleanOrphanedAnnotationTags(ctx)
    loop until done or cancelled
        XR->>DB: fetchIDs(orphaned tags)
        DB-->>XR: []int64 IDs
        XR->>DB: deleteByIDs(annotation_tag, ids)
        DB-->>XR: affected rows
    end
    
    AC-->>CS: affected annotations, affected tags
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 7 comments

Edit Code Review Agent Settings | Greptile

if err != nil {
return 0, err
}
r.log.Error("Annotations to clean by time", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("Annotations to clean by time", "count", len(ids), "ids", ids, "cond", cond, "err", err)
r.log.Debug("Annotations to clean by time", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 534:534

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
			r.log.Debug("Annotations to clean by time", "count", len(ids), "ids", ids, "cond", cond, "err", err)
```

How can I resolve this? If you propose a fix, please make it concise.


affected, err := r.executeUntilDoneOrCancelled(ctx, sql)
x, y := r.deleteByIDs(ctx, "annotation", ids)
r.log.Error("cleaned annotations by time", "count", len(ids), "affected", x, "err", y)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("cleaned annotations by time", "count", len(ids), "affected", x, "err", y)
r.log.Debug("cleaned annotations by time", "count", len(ids), "affected", x, "err", y)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 537:537

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
			r.log.Debug("cleaned annotations by time", "count", len(ids), "affected", x, "err", y)
```

How can I resolve this? If you propose a fix, please make it concise.

if err != nil {
return 0, err
}
r.log.Error("Annotations to clean by count", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("Annotations to clean by count", "count", len(ids), "ids", ids, "cond", cond, "err", err)
r.log.Debug("Annotations to clean by count", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 554:554

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
			r.log.Debug("Annotations to clean by count", "count", len(ids), "ids", ids, "cond", cond, "err", err)
```

How can I resolve this? If you propose a fix, please make it concise.

r.log.Error("Annotations to clean by count", "count", len(ids), "ids", ids, "cond", cond, "err", err)

x, y := r.deleteByIDs(ctx, "annotation", ids)
r.log.Error("cleaned annotations by count", "count", len(ids), "affected", x, "err", y)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("cleaned annotations by count", "count", len(ids), "affected", x, "err", y)
r.log.Debug("cleaned annotations by count", "count", len(ids), "affected", x, "err", y)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 557:557

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
			r.log.Debug("cleaned annotations by count", "count", len(ids), "affected", x, "err", y)
```

How can I resolve this? If you propose a fix, please make it concise.

if err != nil {
return 0, err
}
r.log.Error("Tags to clean", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("Tags to clean", "count", len(ids), "ids", ids, "cond", cond, "err", err)
r.log.Debug("Tags to clean", "count", len(ids), "ids", ids, "cond", cond, "err", err)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 576:576

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
		r.log.Debug("Tags to clean", "count", len(ids), "ids", ids, "cond", cond, "err", err)
```

How can I resolve this? If you propose a fix, please make it concise.

r.log.Error("Tags to clean", "count", len(ids), "ids", ids, "cond", cond, "err", err)

x, y := r.deleteByIDs(ctx, "annotation_tag", ids)
r.log.Error("cleaned tags", "count", len(ids), "affected", x, "err", y)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: using log.Error for non-error informational messages - should be log.Debug or log.Info

Suggested change
r.log.Error("cleaned tags", "count", len(ids), "affected", x, "err", y)
r.log.Debug("cleaned tags", "count", len(ids), "affected", x, "err", y)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/annotations/annotationsimpl/xorm_store.go
Line: 579:579

Comment:
**syntax:** using `log.Error` for non-error informational messages - should be `log.Debug` or `log.Info`

```suggestion
		r.log.Debug("cleaned tags", "count", len(ids), "affected", x, "err", y)
```

How can I resolve this? If you propose a fix, please make it concise.

srv.cleanUpTmpFiles(ctx)

ticker := time.NewTicker(time.Minute * 10)
ticker := time.NewTicker(time.Minute * 1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: cleanup interval reduced from 10 minutes to 1 minute - this is a 10x increase in execution frequency that could significantly impact database performance

Suggested change
ticker := time.NewTicker(time.Minute * 1)
ticker := time.NewTicker(time.Minute * 10)
Prompt To Fix With AI
This is a comment left during a code review.
Path: pkg/services/cleanup/cleanup.go
Line: 77:77

Comment:
**logic:** cleanup interval reduced from 10 minutes to 1 minute - this is a 10x increase in execution frequency that could significantly impact database performance

```suggestion
	ticker := time.NewTicker(time.Minute * 10)
```

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants