Skip to content

Fix Learning notebook autosave - #3683

Open
Dhairya Patel (HABER7789) wants to merge 3 commits into
mainfrom
HABER7789/notebook-autosave
Open

Fix Learning notebook autosave#3683
Dhairya Patel (HABER7789) wants to merge 3 commits into
mainfrom
HABER7789/notebook-autosave

Conversation

@HABER7789

Copy link
Copy Markdown
Contributor

Learning notebooks are now saved after metadata changes and before moving to another unit, preventing unwanted save prompts and preserving learner edits.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

saveCourseWorkbook can report success even when the notebook remains dirty after saving, which can lead to stale-tab closure still prompting to save (or risking loss of edits).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR improves the VS Code Learning experience for *.workbook.ipynb notebooks by ensuring learner workbooks are auto-saved when Jupyter updates notebook metadata and by attempting to save workbooks before closing stale learning tabs, reducing unwanted “unsaved changes” prompts.

Changes:

  • Added LearningService.isCourseWorkbook and LearningService.saveCourseWorkbook (with per-notebook save queueing) to centralize workbook detection and serialized auto-save.
  • Updated learning notebook sync + notebook change handling to call saveCourseWorkbook after sync and on metadata/execution changes.
  • Updated stale-tab closing to save workbooks first and skip closing ones that could not be saved; adjusted notebook opening flow to explicitly show the notebook after the Jupyter API opens it.
File summaries
File Description
source/vscode/src/learning/service.ts Adds workbook detection and queued saving; ensures stale learning tabs are saved (and skips closing when save fails).
source/vscode/src/learning/notebookSync.ts Saves a course workbook after syncing when restoring sessions and uses service.isCourseWorkbook for context.
source/vscode/src/learning/index.ts Auto-saves workbooks on notebook metadata changes (and execution changes) via saveCourseWorkbook.
source/vscode/src/learning/commands.ts After opening via Jupyter’s API, explicitly shows the notebook document to ensure it is visible/active.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread source/vscode/src/learning/service.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

All reviewed changes are acceptable with no unresolved issues.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Comment thread source/vscode/src/learning/commands.ts Outdated
Comment thread source/vscode/src/learning/notebookSync.ts
Comment thread source/vscode/src/learning/notebookSync.ts
Comment thread source/vscode/src/learning/service.ts Outdated
Comment thread source/vscode/src/learning/service.ts
Comment thread source/vscode/src/learning/service.ts Outdated
}
}

if (request !== this._closeStaleTabsRequest) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is in case the user switched notebooks while we were busy saving?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that was the reason. It prevents an older tab closing operation from affecting the notebook the learner just opened. With your list before saving suggestion below, I think we can remove this counter.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We might still want it (with an explanatory comment) because we don't want to close the notebook that's now open. (e.g. open A, open B, open A - don't want to close A as part of processing open B)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, I see. The list would handle A -> B, but not A -> B-> A while the first save is still running. I'll keep the request check and add a comment explaining that.

Comment thread source/vscode/src/learning/service.ts Outdated
// is a working copy we created on the user's behalf, we're free to
// auto-save.
void e.notebook.save();
void learningService.saveCourseWorkbook(e.notebook);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we even need this if we save on close?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To my understanding, I think we still need it. Saving before closing only handles moving between units. This listener saves the kernel metadata (that you had found that Jupyter adds) after opening, so the notebook doesn't show a save prompt when the learner hasn't edited anything. It saves the change it would not revert it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But why would it be showing a save prompt if you weren't closing the notebook?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So you are right that the prompt only appears when the notebook is closed since I wanted to still test it, I asked Copilot to test the listener, and it created a temporary VS Code test that opened a copied course notebook and saw Jupyter change its metadata after opening. The listener saves that change before the notebook is later closed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, I'm not sure which side your comment supports. I agree that the notebook will be marked dirty when the language metadata changes, but I'm not sure I understand why that matters if we save before closing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Okay, I just misunderstood when the save was needed. I thought that when jupyter's metadata changed, we needed an immediate save because if we don't do that, it would prompt the "do you want to save" dialog box.

But, I just tested navigation between notebooks with and without that metadata save and as you mentioned saving before close was enough in both cases, no prompt. So, I was wrong for adding that metadata save.

Thanks for catching this, I will remove the metadata condition.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Metadata-only changes can still occur after synchronization without triggering a save.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +46 to +47
// Save after cell execution and update exercise completion.
if (!learningService.isCourseWorkbook(e.notebook.uri)) {
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