Skip to content

Refactor: Implement non-blocking async file operations and UI loading states - #19

Open
BradMoyetones wants to merge 1 commit into
starc007:mainfrom
BradMoyetones:refactor/async-file-ops
Open

BradMoyetones wants to merge 1 commit into
starc007:mainfrom
BradMoyetones:refactor/async-file-ops

Conversation

@BradMoyetones

Copy link
Copy Markdown

Description

This PR refactors the file system commands to prevent blocking the Tauri IPC threads, aligning with Tauri's best practices for I/O operations. It also introduces seamless loading states on the frontend to improve the UX during large file operations, without cluttering the global store.

Changes Made

  • Backend (src-tauri/src/commands.rs): Converted synchronous I/O commands (delete_entry, rename_entry, move_entry, create_note, etc.) to async fn. Wrapped the underlying filesystem calls using tauri::async_runtime::spawn_blocking to offload them to a background thread pool, preventing any potential UI or IPC freezes.
  • Frontend (src/stores/vault.ts): Wrapped the corresponding ipc calls in promises and implemented toast.promise from Sonner. This natively provides loading, success, and error toast notifications immediately when interacting with the vault (e.g. moving to trash, renaming) without the need to introduce additional loading state variables into the UI components.

Motivation

To ensure the application remains highly responsive and doesn't limit performance on modern hardware when handling large vaults or heavy OS-level operations.

@starc007

Copy link
Copy Markdown
Owner

Reviewed at 86b4d4d. Moving blocking I/O off the main thread makes sense, but these three issues need addressing before merge:

  1. Build failure: The new @tiptap/core and @tiptap/pm dependencies resolve to 3.30.1 while the existing extensions remain on 3.23.6. A clean bun install --frozen-lockfile followed by bunx tsc --noEmit fails with incompatible Tiptap/ProseMirror types in NoteEditor.tsx and noteFind.ts. The parent commit passes. Please keep the versions aligned and regenerate the lockfile.

  2. Concurrent operations can overwrite notes: spawn_blocking allows note creation to run concurrently, but available_path checks for an unused filename before fs::write without reserving it. Two requests can select the same path and overwrite content while both report success. A temporary test with 32 concurrent same-title creations produced only 16 distinct paths. Please serialize conflicting mutations or reserve filenames atomically, and add regression coverage.

  3. Stale active view after rename/move/delete: These actions now capture view before awaiting IPC. With delayed IPC, switching from A to B during A's rename switches the user back when it completes. Deleting inactive A and opening it while deletion is pending leaves the active view pointing at a removed tab. Please read the current view immediately before applying the final state update.

Validation: all 59 existing Rust tests pass; the added concurrency reproduction fails. The view issues were reproduced with delayed IPC mocks.

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.

2 participants