Skip to content

fix(auth): make advisory locks dialect-aware and harden SQLite DSN - #10509

Merged
mudler merged 2 commits into
masterfrom
fix/advisorylock-sqlite-dialect
Jun 25, 2026
Merged

fix(auth): make advisory locks dialect-aware and harden SQLite DSN#10509
mudler merged 2 commits into
masterfrom
fix/advisorylock-sqlite-dialect

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Fixes #10506.

Two failures hit deployments that use the default SQLite auth database (LOCALAI_AUTH=true without LOCALAI_AUTH_DATABASE_URL=postgres://...):

1. no such function: pg_advisory_lock on SQLite

core/services/advisorylock executed PostgreSQL-only SQL (pg_advisory_lock / pg_try_advisory_lock / pg_advisory_unlock) unconditionally. The auth DB can be SQLite, so the job store, agent store and node registry migrations failed with migrating job tables: advisorylock: acquiring lock 105: no such function: pg_advisory_lock (non-fatal in standalone startup, fatal in distributed mode).

WithLockCtx / TryWithLockCtx now branch on the gorm dialect:

  • PostgreSQL keeps the existing cross-process advisory lock (byte-for-byte unchanged).
  • SQLite / any other dialect uses a context-aware, per-key in-process lock (buffered-channel mutex). A SQLite auth DB is effectively single-process, so serializing guarded sections within the process is sufficient; we cannot and need not coordinate across processes the way a PG advisory lock does.

2. database is locked over network storage

The SQLite auth DSN set no busy timeout, so transient SQLITE_BUSY over network-backed storage (SMB/CIFS/NFS, e.g. Azure Files / Azure Container Apps) failed AutoMigrate immediately with failed to migrate auth tables: database is locked (the reporter's Azure case).

buildSQLiteDSN now sets _busy_timeout=5000 and _txlock=immediate (caller-supplied values preserved). WAL is intentionally not enabled - its shared-memory mmap does not work over network filesystems, which is the failing environment. Docs note that PostgreSQL should be used when the data directory lives on shared storage.

Tests

  • New non-Docker SQLite specs for advisorylock: executes under lock, serializes concurrent goroutines on the same key, returns error on already-cancelled context, and TryWithLockCtx returns (false, nil) when the key is held.
  • buildSQLiteDSN unit tests: plain path, :memory:, pre-existing query string, and no-override of caller-supplied pragmas.
  • Existing PostgreSQL advisorylock testcontainer specs and the auth InitDB SQLite test still pass.

Verification

gofmt clean; go vet clean (with and without -tags auth); full advisorylock suite incl. Postgres testcontainers green; auth DSN + InitDB tests green; golangci-lint --new-from-merge-base=origin/master reports 0 issues.

Assisted-by: Claude:claude-opus-4-8 [Claude Code]

mudler added 2 commits June 25, 2026 12:52
Fixes #10506.

Two failures hit deployments that use the default SQLite auth database:

1. advisorylock executed PostgreSQL-only SQL (pg_advisory_lock /
   pg_try_advisory_lock) unconditionally. On a SQLite auth DB the job
   store, agent store and node registry migrations failed with
   "no such function: pg_advisory_lock". WithLockCtx/TryWithLockCtx now
   branch on the gorm dialect: PostgreSQL keeps the cross-process advisory
   lock, every other dialect uses a context-aware, per-key in-process lock
   (a SQLite auth DB is effectively single-process, so serializing within
   the process is sufficient).

2. The SQLite auth DSN set no busy timeout, so transient SQLITE_BUSY over
   network-backed storage (SMB/CIFS/NFS, e.g. Azure Files) failed the auth
   migration immediately with "database is locked". The DSN now sets
   _busy_timeout=5000 and _txlock=immediate (caller-supplied values are
   preserved). WAL is intentionally not enabled since its shared-memory
   mmap does not work over network filesystems. Docs note that PostgreSQL
   should be used when the data directory lives on shared storage.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
Exercises the exact caller chain that failed in the issue:
auth.InitDB(sqlite) -> jobs.NewJobStore -> advisorylock.WithLockCtx ->
AutoMigrate. Before the dialect-aware advisory lock fix this failed with
"no such function: pg_advisory_lock"; the test now asserts it migrates
cleanly on a SQLite auth DB.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
@mudler
mudler merged commit f72046b into master Jun 25, 2026
60 checks passed
@mudler
mudler deleted the fix/advisorylock-sqlite-dialect branch June 25, 2026 15:18
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.

Authentication initialisation failed with database is locked

2 participants