ronantakizawa/codereview-bench huggingface dataset:
Repository: phidatahq/phidata
File: cookbook/03_agents/context_management/instruction_tags.py (Python)

Code before:
"""

from agno.agent import Agent
from agno.models.openai import OpenAIChat

# Default behavior: instructions without tags
# The instructions are added directly to the system message
agent_without_tags = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    instructions=[
        "You are a helpful assistant.",
        "Always be concise and clear.",
        "Use bullet points when listing items.",
    ],
)

# With instruction tags enabled
# The instructions are wrapped in <instructions> tags
agent_with_tags = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    instructions=[
        "You are a helpful assistant.",
        "Always be concise and clear.",
        "Use bullet points when listing items.",
    ],
    add_instruction_tags=True,
)

print("=== Agent without instruction tags (default) ===")
agent_without_tags.print_response("What are the benefits of exercise?")

print("\n=== Agent with instruction tags ===")
agent_with_tags.print_response("What are the benefits of exercise?")


Review comment (suggestion):
```suggestion
    use_instruction_tags=True,
```

Wdyt? To me, this sounds better

Code after:
"""

from agno.agent import Agent
from agno.models.openai import OpenAIChat

# Default behavior: instructions without tags
# The instructions are added directly to the system message
agent_without_tags = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    instructions=[
        "You are a helpful assistant.",
        "Always be concise and clear.",
        "Use bullet points when listing items.",
    ],
)

# With instruction tags enabled
# The instructions are wrapped in <instructions> tags
agent_with_tags = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    instructions=[
        "You are a helpful assistant.",
        "Always be concise and clear.",
        "Use bullet points when listing items.",
    ],
    use_instruction_tags=True,
)

print("=== Agent without instruction tags (default) ===")
agent_without_tags.print_response("What are the benefits of exercise?")

print("\n=== Agent with instruction tags ===")
agent_with_tags.print_response("What are the benefits of exercise?")
Repository: phidatahq/phidata
File: libs/agno/agno/knowledge/chunking/document.py (Python)

Code before:
        # Handle overlap if specified
        if self.overlap > 0:
            overlapped_chunks = []
            for i in range(len(chunks)):
                if i > 0:
                    # Add overlap from previous chunk
                    prev_text = chunks[i - 1].content[-self.overlap :]
                    meta_data = chunk_meta_data.copy()
                    meta_data["chunk"] = chunks[i].meta_data["chunk"]
                    if prev_text:
                        # Overlap prepends text from previous chunk, changing this chunk's content.
                        # Must regenerate ID based on actual content, otherwise documents without
                        # id/name would all get id=None regardless of their different content.
                        overlap_content = prev_text + chunks[i].content
                        chunk_id = self._generate_chunk_id(document, meta_data["chunk"], overlap_content)
                        meta_data["chunk_size"] = len(overlap_content)
                        overlapped_chunks.append(
                            Document(
                                id=chunk_id,
                                name=document.name,
                                meta_data=meta_data,
                                content=overlap_content,
                            )
                        )
                    else:
                        overlapped_chunks.append(chunks[i])
                else:
                    overlapped_chunks.append(chunks[i])
            chunks = overlapped_chunks

        return chunks


Review comment (bug):
**Additional bug fix (unrelated to chunk ID):** The original code silently dropped chunks when `prev_text` was empty. This `else` branch preserves the original chunk in that edge case, matching the pattern already used in `markdown.py`.

Code after:
                if i > 0:
                    # Add overlap from previous chunk
                    prev_text = chunks[i - 1].content[-self.overlap :]
                    meta_data = chunk_meta_data.copy()
                    # Use the chunk's existing metadata and ID instead of stale chunk_number
                    meta_data["chunk"] = chunks[i].meta_data["chunk"]
                    chunk_id = chunks[i].id
                    meta_data["chunk_size"] = len(prev_text + chunks[i].content)

                    if prev_text:
                        overlapped_chunks.append(
                            Document(
                                id=chunk_id,
                                name=document.name,
                                meta_data=meta_data,
                                content=prev_text + chunks[i].content,
                            )
                        )
                    else:
                        overlapped_chunks.append(chunks[i])
                else:
                    overlapped_chunks.append(chunks[i])
            chunks = overlapped_chunks

        return chunks
Repository: phidatahq/phidata
File: cookbook/02_agents/human_in_the_loop/confirmation_required_mcp_toolkit.py (Python)

Code before:
"""🤝 Human-in-the-Loop: Adding User Confirmation to Tool Calls

This example shows how to implement human-in-the-loop functionality with MCP Servers in your Agno tools.
It shows how to:
- Handle user confirmation during tool execution
- Gracefully cancel operations based on user choice

Some practical applications:
- Confirming sensitive operations before execution
- Reviewing API calls before they're made
- Validating data transformations
- Approving automated actions in critical systems

Run `uv pip install openai httpx rich agno` to install dependencies.
"""

import asyncio

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.anthropic import Claude
from agno.tools.mcp import MCPTools
from rich.console import Console
from rich.prompt import Prompt

console = Console()

Review comment (suggestion):
```suggestion
"""Human-in-the-Loop: Adding User Confirmation to Tool Calls
```

Code after:
"""Human-in-the-Loop: Adding User Confirmation to Tool Calls

This example shows how to implement human-in-the-loop functionality with MCP Servers in your Agno tools.
It shows how to:
- Handle user confirmation during tool execution
- Gracefully cancel operations based on user choice

Some practical applications:
- Confirming sensitive operations before execution
- Reviewing API calls before they're made
- Validating data transformations
- Approving automated actions in critical systems

Run `uv pip install openai httpx rich agno` to install dependencies.
"""

import asyncio

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.anthropic import Claude
from agno.tools.mcp import MCPTools
from rich.console import Console
from rich.prompt import Prompt

console = Console()
Repository: pingcap/tidb
File: pkg/executor/importer/import.go (Go)

Code before:
		}
	}
	if err2 = e.checkCSVOnlyOptions(); err2 != nil {
		return err2
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

func (e *LoadDataController) getFileRealSize(ctx context.Context,
	fileMeta mydump.SourceFileMeta, store storage.ExternalStorage) int64 {
	if fileMeta.Compression == mydump.CompressionNone {
		return fileMeta.FileSize
	}
	compressRatio, err := mydump.SampleFileCompressRatio(ctx, fileMeta, store)
	if err != nil {
		e.logger.Warn("failed to get compress ratio", zap.String("file", fileMeta.Path), zap.Error(err))
		return fileMeta.FileSize
	}
	return int64(compressRatio * float64(fileMeta.FileSize))
}

// update format of the validated file by its extension.
func (e *LoadDataController) updateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		if e.Parameters != nil {
			e.Parameters.Format = e.Format
		}
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	for ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}

Review comment (suggestion):
```suggestion
func (e *LoadDataController) detectAndUpdateFormat(path string) {
```

Code after:
			return err
		}
	}
	if e.InImportInto && isAutoDetectingFormat && e.Format != DataFormatCSV {
		if err2 = e.checkNonCSVFormatOptions(); err2 != nil {
			return err2
		}
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

// update format of the validated file by its extension.
func (e *LoadDataController) detectAndUpdateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		e.logger.Info("detect and update import plan format based on file extension",
			zap.String("file", path), zap.String("detected format", e.Format))
		e.Parameters.Format = e.Format
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	if ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}
}

func (e *LoadDataController) getSourceType() mydump.SourceType {
	switch e.Format {
	case DataFormatParquet:
		return mydump.SourceTypeParquet
	case DataFormatDelimitedData, DataFormatCSV:
		return mydump.SourceTypeCSV
	default:
		// DataFormatSQL
Repository: pingcap/tidb
File: pkg/executor/importer/import.go (Go)

Code before:
				fileMeta := mydump.SourceFileMeta{
					Path:        path,
					FileSize:    size,
					Compression: compressTp,
					Type:        sourceType,
				}
				fileMeta.RealSize = mydump.EstimateRealSizeForFile(ctx, fileMeta, s)
				return &fileMeta, nil
			}); err != nil {
			return err
		}
	}
	if err2 = e.checkNonCSVFormatOptions(isDataFormatAuto); err2 != nil {
		return err2
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

// update format of the validated file by its extension.
func (e *LoadDataController) detectAndUpdateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		e.logger.Info("detect and update import plan format based on file extension", zap.String("file", path), zap.String("detected format", e.Format))
		e.Parameters.Format = e.Format
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	for ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}
}

func (e *LoadDataController) getSourceType() mydump.SourceType {
	switch e.Format {

Review comment (suggestion):
```suggestion
		e.logger.Info("detect and update import plan format based on file extension",
			zap.String("file", path), zap.String("detected format", e.Format))
```

Code after:
				fileMeta := mydump.SourceFileMeta{
					Path:        path,
					FileSize:    size,
					Compression: compressTp,
					Type:        sourceType,
				}
				fileMeta.RealSize = mydump.EstimateRealSizeForFile(ctx, fileMeta, s)
				return &fileMeta, nil
			}); err != nil {
			return err
		}
	}
	if e.InImportInto && isAutoDetectingFormat && e.Format != DataFormatCSV {
		if err2 = e.checkNonCSVFormatOptions(); err2 != nil {
			return err2
		}
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

// update format of the validated file by its extension.
func (e *LoadDataController) detectAndUpdateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		e.logger.Info("detect and update import plan format based on file extension",
			zap.String("file", path), zap.String("detected format", e.Format))
		e.Parameters.Format = e.Format
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	if ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}
}
Repository: pingcap/tidb
File: pkg/executor/importer/import.go (Go)

Code before:
			return err
		}
	}
	if err2 = e.checkNonCSVFormatOptions(isDataFormatAuto); err2 != nil {
		return err2
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

// update format of the validated file by its extension.
func (e *LoadDataController) detectAndUpdateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		e.logger.Info("detect and update import plan format based on file extension", zap.String("file", path), zap.String("detected format", e.Format))
		e.Parameters.Format = e.Format
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	for ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}
}

func (e *LoadDataController) getSourceType() mydump.SourceType {
	switch e.Format {
	case DataFormatParquet:
		return mydump.SourceTypeParquet
	case DataFormatDelimitedData, DataFormatCSV:
		return mydump.SourceTypeCSV
	default:
		// DataFormatSQL
		return mydump.SourceTypeSQL
	}
}

Review comment (suggestion):
```suggestion
	if ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
```
we don't support multiple compression types

Code after:
			return err
		}
	}
	if e.InImportInto && isAutoDetectingFormat && e.Format != DataFormatCSV {
		if err2 = e.checkNonCSVFormatOptions(); err2 != nil {
			return err2
		}
	}

	e.dataFiles = dataFiles
	e.TotalFileSize = totalSize
	return nil
}

// update format of the validated file by its extension.
func (e *LoadDataController) detectAndUpdateFormat(path string) {
	if e.Format == DataFormatAuto {
		e.Format = parseFileType(path)
		e.logger.Info("detect and update import plan format based on file extension",
			zap.String("file", path), zap.String("detected format", e.Format))
		e.Parameters.Format = e.Format
	}
}

func parseFileType(path string) string {
	path = strings.ToLower(path)
	ext := filepath.Ext(path)
	// avoid duplicate compress extension
	if ext == ".gz" || ext == ".gzip" || ext == ".zstd" || ext == ".zst" || ext == ".snappy" {
		path = strings.TrimSuffix(path, ext)
		ext = filepath.Ext(path)
	}
	switch ext {
	case ".sql":
		return DataFormatSQL
	case ".parquet":
		return DataFormatParquet
	default:
		// if file do not contain file extension, use ".csv" as default format
		return DataFormatCSV
	}
}

func (e *LoadDataController) getSourceType() mydump.SourceType {
	switch e.Format {
	case DataFormatParquet:
		return mydump.SourceTypeParquet
	case DataFormatDelimitedData, DataFormatCSV:
		return mydump.SourceTypeCSV
	default:
		// DataFormatSQL
Repository: pingcap/tidb
File: pkg/meta/model/table.go (Go)

Code before:

// SepAutoInc decides whether _rowid and auto_increment id use separate allocator.
func (t *TableInfo) SepAutoInc() bool {
	return t.Version >= TableInfoVersion5 && t.AutoIDCache == 1
}

// GetPartitionInfo returns the partition information.
func (t *TableInfo) GetPartitionInfo() *PartitionInfo {
	if t.Partition != nil && t.Partition.Enable {
		return t.Partition
	}
	return nil
}

// GetUpdateTime gets the table's updating time.
func (t *TableInfo) GetUpdateTime() time.Time {
	return TSConvert2Time(t.UpdateTS)
}

// Clone clones TableInfo.
func (t *TableInfo) Clone() *TableInfo {
	nt := *t
	nt.Columns = make([]*ColumnInfo, len(t.Columns))
	nt.Indices = make([]*IndexInfo, len(t.Indices))

	if t.ForeignKeys != nil {
		nt.ForeignKeys = make([]*FKInfo, len(t.ForeignKeys))
		for i := range t.ForeignKeys {
			nt.ForeignKeys[i] = t.ForeignKeys[i].Clone()
		}
	}

	for i := range t.Columns {
		nt.Columns[i] = t.Columns[i].Clone()
	}

	for i := range t.Indices {
		nt.Indices[i] = t.Indices[i].Clone()
	}

	if t.Partition != nil {
		nt.Partition = t.Partition.Clone()
	}
	if t.TTLInfo != nil {
		nt.TTLInfo = t.TTLInfo.Clone()
	}

	return &nt
}

// GetPkName will return the pk name if pk exists.

Review comment (suggestion):
use `if len(t.ForeignKeys) > 0` instead to cover `nil` and `[]*FKInfo{}`.

Code after:

// SepAutoInc decides whether _rowid and auto_increment id use separate allocator.
func (t *TableInfo) SepAutoInc() bool {
	return t.Version >= TableInfoVersion5 && t.AutoIDCache == 1
}

// GetPartitionInfo returns the partition information.
func (t *TableInfo) GetPartitionInfo() *PartitionInfo {
	if t.Partition != nil && t.Partition.Enable {
		return t.Partition
	}
	return nil
}

// GetUpdateTime gets the table's updating time.
func (t *TableInfo) GetUpdateTime() time.Time {
	return TSConvert2Time(t.UpdateTS)
}

// Clone clones TableInfo.
func (t *TableInfo) Clone() *TableInfo {
	nt := *t
	nt.Columns = make([]*ColumnInfo, len(t.Columns))
	nt.Indices = make([]*IndexInfo, len(t.Indices))
	nt.ForeignKeys = nil

	for i := range t.Columns {
		nt.Columns[i] = t.Columns[i].Clone()
	}

	for i := range t.Indices {
		nt.Indices[i] = t.Indices[i].Clone()
	}

	if len(t.ForeignKeys) > 0 {
		nt.ForeignKeys = make([]*FKInfo, len(t.ForeignKeys))
		for i := range t.ForeignKeys {
			nt.ForeignKeys[i] = t.ForeignKeys[i].Clone()
		}
	}

	if t.Partition != nil {
		nt.Partition = t.Partition.Clone()
	}
	if t.TTLInfo != nil {
		nt.TTLInfo = t.TTLInfo.Clone()
	}

	return &nt
}
Repository: pingcap/tidb
File: pkg/privilege/privileges/cache.go (Go)

Code before:
	case x.ColumnName > y.ColumnName:
		return 1
	case x.ColumnName < y.ColumnName:
		return -1
	}
	return 0
}

// compareHost compares two host string using some special rules, return value 1, 0, -1 means > = <.
// TODO: Check how MySQL do it exactly, instead of guess its rules.
func compareHost(x, y string) int {
	// The more-specific, the smaller it is.
	// The pattern '%' means “any host” and is least specific.
	if x == "%" || y == "%" {
		if x == "%" && y == "%" {
			return 0
		}
		if y == `%` {
			return -1
		}
		// x == '%'
		return 1
	}

	// The empty string '' also means “any host” but sorts after '%'.
	if x == `` || y == `` {
		if x == `` && y == `` {
			return 0
		}
		if y == "" {
			return -1
		}
		// x == ``
		return 1
	}

	// One of them end with `%`.
	xEnd := strings.HasSuffix(x, `%`)
	yEnd := strings.HasSuffix(y, `%`)
	if xEnd || yEnd {
		switch {
		case !xEnd && yEnd:
			return -1
		case xEnd && !yEnd:
			return 1
		case xEnd && yEnd:
			// 192.168.199.% smaller than 192.168.%
			// A not very accurate comparison, compare them by length.
			if len(x) > len(y) {
				return -1
			}

Review comment (suggestion):
[nitpick] Mixing raw string literal (``) with double-quoted strings for empty values may confuse readers; consider using `""` consistently for empty strings.

Code after:
	case x.ColumnName > y.ColumnName:
		return 1
	case x.ColumnName < y.ColumnName:
		return -1
	}
	return 0
}

// compareHost compares two host string using some special rules, return value 1, 0, -1 means > = <.
// TODO: Check how MySQL do it exactly, instead of guess its rules.
func compareHost(x, y string) int {
	// The more-specific, the smaller it is.
	// The pattern '%' means “any host” and is least specific.
	if x == "%" || y == "%" {
		if x == "%" && y == "%" {
			return 0
		}
		if y == "%" {
			return -1
		}
		// x == '%'
		return 1
	}

	// The empty string '' also means “any host” but sorts after '%'.
	if x == "" || y == "" {
		if x == "" && y == "" {
			return 0
		}
		if y == "" {
			return -1
		}
		// x == ""
		return 1
	}

	// One of them end with `%`.
	xEnd := strings.HasSuffix(x, `%`)
	yEnd := strings.HasSuffix(y, `%`)
	if xEnd || yEnd {
		switch {
		case !xEnd && yEnd:
			return -1
		case xEnd && !yEnd:
			return 1
		case xEnd && yEnd:
			// 192.168.199.% smaller than 192.168.%
			// A not very accurate comparison, compare them by length.
			if len(x) > len(y) {
				return -1
			}
Repository: pingcap/tidb
File: pkg/domain/domain.go (Go)

Code before:
			case <-time.After(duration):
			}
			if !ok {
				logutil.BgLogger().Error("load privilege loop watch channel closed")
				watchCh = do.etcdClient.Watch(context.Background(), privilegeKey)
				count++
				if count > 10 {
					time.Sleep(time.Duration(count) * time.Second)
				}
				continue
			}

			// Skip the event from this TiDB-Server
			canSkip := true
			for _, event := range resp.Events {
				if event.Kv != nil {
					val := string(event.Kv.Value)
					if do.serverID != 0 && val != strconv.FormatUint(do.serverID, 10) {
						canSkip = false
						break
					}
				}
			}
			if canSkip {
				continue
			}

			count = 0
			err := do.privHandle.Update()
			metrics.LoadPrivilegeCounter.WithLabelValues(metrics.RetLabel(err)).Inc()
			if err != nil {
				logutil.BgLogger().Error("load privilege failed", zap.Error(err))
			}
		}
	}, "loadPrivilegeInLoop")
	return nil
}

// LoadSysVarCacheLoop create a goroutine loads sysvar cache in a loop,
// it should be called only once in BootstrapSession.
func (do *Domain) LoadSysVarCacheLoop(ctx sessionctx.Context) error {
	ctx.GetSessionVars().InRestrictedSQL = true
	err := do.rebuildSysVarCache(ctx)
	if err != nil {
		return err
	}
	var watchCh clientv3.WatchChan
	duration := 30 * time.Second
	if do.etcdClient != nil {
		watchCh = do.etcdClient.Watch(context.Background(), sysVarCacheKey)
	}

Review comment (suggestion):
I think it's better to make `canSkip` default to false and check resp to make it to true.
That's more fault-tolerant when event.Kv is not set or the values unmarshal get error. @CbcWestwolf 

Code after:
			case resp, ok = <-watchCh:
				if !ok {
					logutil.BgLogger().Error("load privilege loop watch channel closed")
					watchCh = do.etcdClient.Watch(do.ctx, privilegeKey)
					closeChanCnt++
					if closeChanCnt > 10 {
						time.Sleep(time.Duration(closeChanCnt) * time.Second)
					}
					continue
				}
				closeChanCnt = 0

				// Skip the event from this TiDB-Server
				eventCnt := len(resp.Events)
				for _, event := range resp.Events {
					if event.Kv != nil {
						val := event.Kv.Value
						if len(val) > 0 {
							var tmp PrivilegeEvent
							err := json.Unmarshal(val, &tmp)
							if err != nil {
								logutil.BgLogger().Warn("decode PrivilegeEvent unmarshal fail", zap.Error(err))
								continue
							}
							if do.serverID != 0 && do.serverID == tmp.ServerID {
								eventCnt--
							}
						}
					}
				}
				if eventCnt == 0 {
					continue
				}
			case <-time.After(duration):
			}

			err := do.privHandle.Update()
			metrics.LoadPrivilegeCounter.WithLabelValues(metrics.RetLabel(err)).Inc()
			if err != nil {
				logutil.BgLogger().Error("load privilege failed", zap.Error(err))
			}
		}
	}, "loadPrivilegeInLoop")
	return nil
}

// LoadSysVarCacheLoop create a goroutine loads sysvar cache in a loop,
// it should be called only once in BootstrapSession.
func (do *Domain) LoadSysVarCacheLoop(ctx sessionctx.Context) error {
	ctx.GetSessionVars().InRestrictedSQL = true
	err := do.rebuildSysVarCache(ctx)