Skip to content

storage-sqlite: no file lock is taken on Windows, so two servers, or a server and migrate, can open the same database #642

Open

Description

@LeeroyHannigan

extenddb serve takes an exclusive lock on <database>.lock before it opens a SQLite file and holds it until it exits, and init, migrate and destroy take the same lock, so a second server or a migration refuses to start while a server holds the file (crates/storage-sqlite/src/serve_lock.rs:4-17 on main at cf321f0). The lock is flock(2) and exists only under #[cfg(unix)]. On every other platform try_lock_exclusive logs a warning and returns Ok(()) (serve_lock.rs:265-272), so each caller goes on as if it held the lock. #391, which added the lock, lists this as a limitation.

@extenddb/win32-x64 is on npm for 0.1.9 to 0.1.14, @extenddb/dev 0.1.14 lists it as an optional dependency (npm view), and it is built with --features sqlite,dev-mode from the win32-x64 row of .github/workflows/npm-build-matrix.yml (:57-59, :131). The launcher's default database is .extenddb/data.db under the directory it is started from (packaging/npm/index.js:25-26, 111), so two launches from one project directory open the same file.

Startup recovery removes restore targets left CREATING and rebuilds indexes left mid-build, which destroys the work of another server that is still running on the file, and the module documentation gives that as the reason for the lock (serve_lock.rs:6-12). Writers inside one process are serialized by write_lock, and nothing serializes two processes. This is read from the code and hasn't been run on Windows.

A fix could take LockFileEx with LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY on Windows; the system releases the lock when the process exits, as with flock. std::fs::File::try_lock covers both platforms from Rust 1.89, and the workspace rust-version is 1.88 (Cargo.toml:24), so until that changes the call would go through windows-sys.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions