Skip to content

fix(explorer): serialize and configure refresh polling - #522

Open
itaober wants to merge 2 commits into
esmuellert:mainfrom
itaober:fix/coalesce-explorer-refresh
Open

fix(explorer): serialize and configure refresh polling#522
itaober wants to merge 2 commits into
esmuellert:mainfrom
itaober:fix/coalesce-explorer-refresh

Conversation

@itaober

@itaober itaober commented Aug 23, 2026

Copy link
Copy Markdown

Summary

Prevent CodeDiff's explorer polling from launching overlapping Git work, and allow users to configure the polling interval.

This affects repositories undergoing large external change bursts—for example, coding agents editing many files, code generators, formatters, rebases, or branch switches. When a refresh takes longer than the polling interval, the next tick previously started another asynchronous scan. Repeated overlap could accumulate Git processes and file descriptors, increase CPU and security-scanner activity, apply stale callbacks out of order, and eventually fail with EMFILE: too many open files.

Root cause

The 500ms poll introduced in #483 starts git status and mutable revision synchronization on every tick without checking whether the previous cycle has finished.

In a large or rapidly changing working tree:

  1. A refresh takes longer than the polling interval.
  2. Later ticks start additional Git operations.
  3. Concurrent scans accumulate and may finish out of order.
  4. Process handles and file descriptors remain occupied until every scan settles.

Changes

  • Keep at most one explorer refresh cycle in flight.
  • Serialize both status scanning and mutable revision buffer synchronization.
  • Collapse any number of overlapping requests into one trailing refresh, preserving the latest state without parallel scans.
  • Cancel pending work when the explorer is closed.
  • Extend explorer.auto_refresh:
    • true: poll every 500ms, preserving the current default.
    • false: disable automatic polling.
    • positive integer: use a custom interval in milliseconds.
  • Reject invalid interval values with a clear error.
  • Document the API and add regression coverage for configuration, overlap coalescing, result-processing ordering, mutable synchronization, and cleanup.

Benefits

  • Prevents refresh storms during bulk external code changes.
  • Avoids stale refresh callbacks overwriting newer explorer or index content.
  • Reduces unnecessary Git, CPU, file-descriptor, and endpoint-security overhead.
  • Preserves automatic detection with the existing default behavior.
  • Lets large repositories choose a less aggressive interval without disabling refresh entirely.

Configuration

require("codediff").setup({
  explorer = {
    auto_refresh = 2000, -- poll every 2 seconds
  },
})

Validation

  • Focused explorer refresh spec: 9 passed
  • Full Lua suite: 84 spec files passed
  • stylua --check on modified Lua and test files
  • git diff --check
  • Independent functionality and code-quality review against the repository conventions and itaober guidelines: no remaining findings

Related

@itaober itaober changed the title fix(explorer): coalesce overlapping refreshes fix(explorer): serialize and configure refresh polling Aug 23, 2026
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.

1 participant