Skip to content

fix(editor): use versioned dirty state and debounced cache writes, also avoid full string conversion of editor buffer #2145

Open
bajrangCoder wants to merge 9 commits into
Acode-Foundation:mainfrom
bajrangCoder:editor-versioned-dirty-cache
Open

fix(editor): use versioned dirty state and debounced cache writes, also avoid full string conversion of editor buffer #2145
bajrangCoder wants to merge 9 commits into
Acode-Foundation:mainfrom
bajrangCoder:editor-versioned-dirty-cache

Conversation

@bajrangCoder
Copy link
Copy Markdown
Member

@bajrangCoder bajrangCoder commented Jun 2, 2026

  • track editor dirty state with version metadata and CodeMirror Text equality
  • debounce cache snapshots and flush pending writes on switch/pause/save
  • avoid full doc string conversion for tab switches and equality checks
  • use mtime metadata for external file change detection
  • disable native webview selection menu in terminal
  • add setting to change cursor width and set default to 2 instead of 1

- track editor dirty state with version metadata and CodeMirror Text equality
- debounce cache snapshots and flush pending writes on switch/pause/save
- avoid full doc string conversion for tab switches and equality checks
- use mtime metadata for external file change detection
@bajrangCoder bajrangCoder added the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Jun 2, 2026
@github-actions github-actions Bot removed the CI: RUN ON-DEMAND PREVIEW RELEASES Triggers an on-demand preview build for this pull request via CI workflow. label Jun 2, 2026
@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Preview Release for this, has been built.

Click here to view that github actions build

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

This PR overhauls the editor's dirty-state tracking by introducing versioned state (docVersion/savedVersion/cacheVersion), mtime-based external file change detection, and debounced/flushed cache writes. It also avoids full document string conversions during tab switches and equality checks.

  • Version tracking: replaces the async isChanged() poll with synchronous version metadata, catching undo-to-clean via Text.eq against a stored #savedDoc reference.
  • Debounced cache: writes are batched with a 1500 ms timer, flushed on tab switch and app pause; writeToCache snapshots docVersion before I/O so a concurrent edit schedules a follow-up write instead of leaving the cache silently stale.
  • Save race fix: savedDoc and savedVersion are captured before writeFile + stat() awaits, so edits arriving during I/O correctly mark the file unsaved.

Confidence Score: 3/5

Four of the five data integrity regressions from prior rounds are properly resolved, but the cache-write path after a confirmed external-file reload still does not execute as intended — the version guard short-circuits the write, leaving stale cache content on disk that will be silently shown on the next restart.

The remaining gap is in checkFiles.js: after markLoaded resets cacheVersion and docVersion both to zero, the scheduleCacheWrite(0) call hits the guard cacheVersion === docVersion and returns without writing. The mtime optimisation then prevents the safety-net content comparison from catching the stale cache on startup.

src/lib/checkFiles.js and src/lib/editorFile.js — the interaction between markLoaded resetting cacheVersion to match docVersion and the scheduleCacheWrite guard that relies on that equality to skip writes.

Important Files Changed

Filename Overview
src/lib/editorFile.js Core of the PR: adds docVersion/savedVersion/cacheVersion and the mark* lifecycle methods plus scheduleCacheWrite/flushCacheWrite. Several previously identified race conditions are resolved, but the version guard in scheduleCacheWrite can block a forced write after markLoaded resets both cacheVersion and docVersion to zero.
src/lib/checkFiles.js Adds mtime shortcut and disk-conflict detection. The scheduleCacheWrite(0) call after an external-file reload is blocked by the version guard, so a stale cache is not overwritten on that path.
src/lib/saveFile.js Properly snapshots savedDoc and savedVersion before I/O awaits, fixing the prior race; formatOnSave wrapped in try/finally to restore markChanged on exceptions.
src/lib/editorManager.js Replaces async isChanged() poll with synchronous markEdited(); adds flushCacheWrites() and per-tab cache flush on tab switch.
src/lib/openFile.js Seeds savedMtime/diskMtime from stat at open time; uses Text.eq for the reopen comparison instead of string equality.
src/lib/saveState.js Persists new version metadata fields for session restore.
src/main.js pauseHandler now awaits flushCacheWrites() before saving state.
src/utils/helpers.js Adds null-safe normalizeMtime and getStatMtime helpers.

Sequence Diagram

sequenceDiagram
    participant User
    participant DocSyncListener
    participant EditorFile
    participant CacheTimer
    participant SaveFile
    participant Disk

    User->>DocSyncListener: keypress (docChanged)
    DocSyncListener->>EditorFile: "markEdited() -> docVersion++"
    DocSyncListener->>CacheTimer: checkTimeout (debounce)
    CacheTimer->>EditorFile: scheduleCacheWrite(1500ms)
    EditorFile->>CacheTimer: debounce timer set

    User->>SaveFile: save command
    SaveFile->>EditorFile: flushCacheWrite() [cancel timer, await write]
    EditorFile->>Disk: writeToCache(docVersion snapshot)
    Disk-->>EditorFile: "done, cacheVersion = snapshot"
    SaveFile->>SaveFile: snapshot savedDoc + savedVersion
    SaveFile->>Disk: writeFile(data)
    SaveFile->>Disk: "stat() -> mtime"
    SaveFile->>EditorFile: markSaved(mtime, savedDoc, savedVersion)
    EditorFile->>EditorFile: "isUnsaved = hasUnsavedChanges()"

    Note over User,Disk: Tab switch path
    User->>DocSyncListener: switch tab
    DocSyncListener->>EditorFile: flushCacheWrite() [background]
    EditorFile->>Disk: "writeToCache() if cacheVersion != docVersion"
Loading

Reviews (6): Last reviewed commit: "fix(editor): restore format save guard" | Re-trigger Greptile

Comment thread src/lib/editorFile.js
Comment thread src/lib/editorFile.js
@bajrangCoder

This comment was marked as outdated.

Comment thread src/lib/saveFile.js Outdated
@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

This comment was marked as outdated.

Comment thread src/lib/checkFiles.js
@bajrangCoder

This comment was marked as outdated.

Comment thread src/lib/saveFile.js
@bajrangCoder

This comment was marked as outdated.

@bajrangCoder bajrangCoder added this to the Acode v1.12.0(970) milestone Jun 3, 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