Skip to content

Conversation

@mscolnick
Copy link
Contributor

@mscolnick mscolnick commented Nov 6, 2025

This PR track contents that we wrong to avoid reloading on our own writes when file watching.

@vercel
Copy link

vercel bot commented Nov 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
marimo-docs Ready Ready Preview Comment Nov 6, 2025 6:08pm

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a mechanism to prevent unnecessary file reloads when the file system change was triggered by the application's own save operation. The implementation tracks the last saved content and compares it with the current file content before reloading.

  • Adds _last_saved_content tracking to AppFileManager to store the content of the last persisted save
  • Implements file_content_matches_last_save() method to check if current file content matches the last save
  • Updates the file change handler in sessions.py to skip reload when content matches the last save

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
marimo/_server/file_manager.py Adds content tracking via _last_saved_content field, implements comparison method, and updates _save_file signature to use keyword arguments
marimo/_server/sessions.py Adds early return in file change handler when content matches last save to avoid unnecessary reloads
tests/_server/test_file_manager.py Adds comprehensive test coverage for the new file_content_matches_last_save() functionality
Comments suppressed due to low confidence (2)

marimo/_server/file_manager.py:66

  • The reload() method should clear _last_saved_content after successfully loading external changes. Without this, if an external change is reloaded, subsequent saves will still compare against the old content, potentially causing incorrect skip behavior. Add self._last_saved_content = None after line 66 to reset tracking when external changes are loaded.
    def reload(self) -> set[CellId_t]:
        """
        Reload the app from the file.

        Return any new cell IDs that were added or code that was changed.
        """
        prev_cell_manager = self.app.cell_manager
        self.app = self._load_app(self.path)

marimo/_server/file_manager.py:345

  • The copy() method directly writes to the filesystem using shutil.copy() without updating _last_saved_content. If the destination is the same as self.filename, this could lead to incorrect behavior where the file watcher detects a change but file_content_matches_last_save() returns False even though the application made the change. Consider updating _last_saved_content if destination == self.filename.
    def copy(self, request: CopyNotebookRequest) -> str:
        source, destination = request.source, request.destination
        shutil.copy(source, destination)
        return os.path.basename(destination)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +368 to +381
def file_content_matches_last_save(self) -> bool:
"""Check if the current file content matches the last saved content.
This is used to avoid reloading the file when we detect our own writes.
Returns:
bool: True if the file content matches the last save, False otherwise.
"""
if self.filename is None or self._last_saved_content is None:
return False

try:
current_content = Path(self.filename).read_text(encoding="utf-8")
return current_content.strip() == self._last_saved_content
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

There's a potential race condition where the file could be modified between the file watcher detecting a change and this comparison being executed. While the file change locks in sessions.py provide some protection, consider the scenario where: 1) save writes file A, 2) file watcher queues change event, 3) external tool writes file B, 4) this method runs and compares file B with saved content A. The method would return False and trigger a reload, but then the save for file B might complete before the reload, causing the reload to skip. Consider adding a timestamp-based check or file system modification time comparison as an additional validation.

Copilot uses AI. Check for mistakes.
if persist:
self._create_file(filename, contents)
# Record the last saved content to avoid reloading our own writes
self._last_saved_content = contents.strip()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could save just the hash

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it saves a bit on space (not much), but requires hashing each time

)

# Now the file should match the last save
assert manager.file_content_matches_last_save() is True
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add another call mocking debug to make sure that we are skipping? Or maybe mock reload to make sure never called?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i have this already in a followup PR, will push it up in a bit

@mscolnick mscolnick merged commit 1067a06 into main Nov 6, 2025
48 of 65 checks passed
@mscolnick mscolnick deleted the ms/better-file-watching branch November 6, 2025 20:36
mscolnick added a commit that referenced this pull request Nov 13, 2025
)" (#7161)

This reverts commit 928e8a0.

We can revert this change now and support watch and autosave due to this
change: #7099
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