Skip to content

fix(editor): never write back a recipe renamed or deleted in another tab - #809

Merged
LeMyst merged 1 commit into
cooklang:mainfrom
LeMyst:fix/rename-autosave-race
Oct 28, 2026
Merged

LeMyst merged 1 commit into
cooklang:mainfrom
LeMyst:fix/rename-autosave-race

Conversation

@LeMyst

@LeMyst LeMyst commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Closes #808

An editor tab open on a recipe that is then renamed or deleted elsewhere no longer writes the old file back.

  • Server: PUT /api/recipes/{path} honours If-Match: * (RFC 9110). When the file is missing it answers 412 instead of creating it. The check runs under RECIPE_FILES, the lock rename and delete already take, so they can't slip in between the check and the write. No entity tags are issued, so any other If-Match value gets 412 too. Without the header, PUT still creates a file, as documented, so other API clients are unaffected.
  • Editor: both of its saves send If-Match: *, so the editor never creates a recipe file (/new does that). On a 412 it stops autosaving, shows "Not saved: renamed or deleted elsewhere" in the save status (sticky while typing), and shows the server's message once. The text stays unsaved, so leaving the page asks first and the changes can be copied out.
  • docs/api.md is regenerated with the header's description.

Tests

  • recipe_file_api_test::save_with_if_match_never_creates_a_file:
    • If-Match: * saves over an existing file, and refuses a missing .cook or .menu with 412 without creating it;
    • another If-Match value is refused;
    • a PUT without the header still creates the file.
  • editor-rename.spec.ts, two new cases, each with two tabs on one recipe: tab A renames it (or it's deleted), then tab B types. B shows the status, the old name is not created again, B sends no further saves, and its text is still unsaved. Without the editor's header both fail (B shows "Saved" and the old file is back).
  • cargo clippy --all-targets clean, cargo test --workspace 1873 passed. Full chromium Playwright run green, apart from the specs that spawn target/debug/cook, which doesn't exist in my local setup. The shopping-list specs were rerun with --workers=1, as on CI.

The status text is English, like the rest of the editor's save statuses (the editor isn't translated yet).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MmrM91dHzvQoaerCcR9wra

An editor tab still open on a recipe that was renamed or deleted
elsewhere (another tab, another device) autosaved to its old path, and
`PUT /api/recipes` creates a missing file: the old name came back beside
the new one, or the deleted recipe reappeared. The editor's own rename
was already guarded; other tabs were not.

The editor now saves with `If-Match: *`, and the save endpoint refuses
it with `412` when the file is missing, checked under the lock rename
and delete take. The editor then stops saving, says the file was
renamed or deleted elsewhere, and keeps the text as unsaved, so leaving
asks first. `PUT` without the header still creates a file.

Since in-editor rename came in with 2c6e839 (cooklang#623).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmrM91dHzvQoaerCcR9wra
@LeMyst
LeMyst marked this pull request as ready for review October 28, 2026 21:01
@LeMyst
LeMyst merged commit df83728 into cooklang:main Oct 28, 2026
6 checks passed
dubadub pushed a commit that referenced this pull request Nov 3, 2026
The editor's save status (Modified, Saving..., Saved, Save failed, and
since #809 "Not saved: renamed or deleted elsewhere") and its save
notices were written in English in the template, whatever the page's
language. Three of them already had messages in every locale, unused.

The status and the notices now come from the locales: the existing
`editor-unsaved-changes`, `editor-saving`, `editor-saved` and
`editor-save-failed`, and new `editor-not-saved-gone`,
`editor-save-failed-detail` and `editor-file-gone` in all nine. The
refusal of a file renamed or deleted elsewhere is explained in the
page's words instead of the server's English message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmrM91dHzvQoaerCcR9wra
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.

Editor autosave brings back a recipe renamed or deleted in another tab

1 participant