Skip to content

fix(files): edited files marked locked in files list after close - #9355

Merged
mejo- merged 1 commit into
mainfrom
fix/file-is-locked-after-close
Oct 13, 2026
Merged

mejo- merged 1 commit into
mainfrom
fix/file-is-locked-after-close

Conversation

@ShGKme

@ShGKme ShGKme commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

馃摑 Summary

Caused by:

onSave() {
if (this.fileNode) {
this.fileNode.mtime = new Date()
this.fileNode.size = new Blob([this.serialize()]).size
emit('files:node:updated', this.fileNode)
}

  1. After session is connected, the file is locked
  2. fetchFile fetches the locked file, stored later in this.fileNode
  3. On save, local file node copy is updated with the new size and mtime ...
  4. ... and sent to Files
  5. With the updated size/mtime, Files also receives attributes.lock = 1

From my understanding, the Text frontend doesn't actually know if the file is locked or not after the file is saved and the session connection is closed. /close endpoint may and may not unlock the file.

Instead of changing the lock and other properties locally, we can fetch the actual updated node state.
This way we have all the properties and attributes updated.

This, unfortunately, adds one more request.

I added it to the close method instead of onSave. onSave's cheap (no-request) update is kept for a case when the file is edited in the folder description (README.md). Only on viewer closed when the session is actually closed the file is updated in Files app completely.

This may result in flickering for a second on close:

  1. File is update to "locked" from onSave
  2. Then to "unlocked" on new node fetch in close().

IMO, we can:

  • Either remove update in onSave completely (but then there is no visual update on README from description)
  • Or add additional flag to check if this save is on close...

What fo you think?

Additionally, SyncService.close method is slightly refactored, to the returned promise is resolved after the request finishes, not on just sent. Local state and even is still sync.

馃弫 Checklist

  • Code is properly formatted (npm run lint / npm run stylelint / composer run cs:check)
  • Sign-off message is added to all commits
  • Tests (unit, integration and/or end-to-end) passing and the changes are covered with tests
  • Documentation (README or documentation) has been updated or is not required

馃 AI (if applicable)

  • The content of this PR was partly or fully generated using AI tools
  • The AI-generated content was reviewed, comprehended and tested by a human

@ShGKme ShGKme self-assigned this Oct 8, 2026
@ShGKme ShGKme added bug Something isn't working 3. to review labels Oct 8, 2026
@benjaminfrueh

Copy link
Copy Markdown
Contributor

@ShGKme thank you for this, I didn't test but it makes sense to me to fetch it again on close.

I think the new fetchNode() request can race with the POST /close sent just before in this.disconnect() -> this.syncService.close(), because the close() call in SyncService.close() is not awaited. If the PROPFIND is handled before the server has released the lock (e.g. slow db), the file could stay marked as locked.

Awaiting it there could fix it but connection.value would then only be cleared after the response, maybe have to move that up and unsure about other side effects this could have. Curious what @max-nextcloud thinks about this.

@ShGKme

ShGKme commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

because the close() call in SyncService.close() is not awaited

Ah, yes, I see.
Can we make it awaited?

Something like:

async close() {
	const activeConnection = this.connection.value 

	this.backend?.disconnect()

	// Clear connection immediately so hasActiveConnection turns false and we can reconnect.
	this.connection.value = undefined
	this.bus.emit('close')

	if (activeConnection) {
		await close(activeConnection)
			// Log and ignore possible network issues.
			.catch((e) => {
				logger.info('Failed to close connection.', { e })
			})
	}
}

@max-nextcloud max-nextcloud left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hi Grigorii,
Thanks a lot for looking into this. Your fix looks good with the addition you proposed in the comment.
Shall I apply the proposed change and take this over (i.e. merge and backport)?

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Added a fixup! commit with the discussed change.

Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
@ShGKme
ShGKme force-pushed the fix/file-is-locked-after-close branch from 3f25b4f to 43ebb2a Compare October 12, 2026 20:14
@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main and squashed

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Cypress fail seems unrelated.
But Playwright test might be related, checking.

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Ah, no, the same problem in other PRs.

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

/backport to stable35 please

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

/backport to stable34 please

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

/backport to stable33 please

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

/backport to stable32 please

@ShGKme

ShGKme commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

/backport to stable31 please

@mejo-
mejo- merged commit ebf09dd into main Oct 13, 2026
62 of 68 checks passed
@mejo-
mejo- deleted the fix/file-is-locked-after-close branch October 13, 2026 07:16
@backportbot

backportbot Bot commented Oct 13, 2026

Copy link
Copy Markdown

The backport to stable31 failed. Please do this backport manually.

# Switch to the target branch and update it
git checkout stable31
git pull origin stable31

# Create the new backport branch
git checkout -b backport/9355/stable31

# Cherry pick the change from the commit sha1 of the change against the default branch
# This might cause conflicts, resolve them
git cherry-pick 43ebb2ac

# Push the cherry pick commit to the remote repository and open a pull request
git push origin backport/9355/stable31

Error: Failed to check for changes with origin/stable31: No changes found in backport branch


Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File is marked as "Locked by editing online in Text" in Files after closing edited file

4 participants