fix: prevent UNIQUE constraint race with gunicorn multi-worker

Use INSERT OR IGNORE instead of SELECT-then-INSERT for
default admin user creation, avoiding the race condition
when multiple gunicorn workers initialize simultaneously.
This commit is contained in:
Yuyao Huang 2026-05-09 10:19:58 +08:00
parent 2629e8f2cd
commit 2a3482c2c0
2 changed files with 11 additions and 11 deletions

View File

@ -80,6 +80,8 @@ uv add gunicorn
uv run gunicorn -w 4 -b 0.0.0.0:5000 app:app uv run gunicorn -w 4 -b 0.0.0.0:5000 app:app
``` ```
> **Note:** The `-b` flag is required because gunicorn is a separate WSGI server and does not read Flask's `config.py`. The values in `config.py` (`HOST`, `PORT`) only apply to Flask's built-in dev server (`app.run()`).
## Project Structure ## Project Structure
``` ```

View File

@ -86,14 +86,12 @@ def init_db():
conn.commit() conn.commit()
import bcrypt import bcrypt
cur = conn.execute("SELECT COUNT(*) FROM users WHERE role = 'admin'")
if cur.fetchone()[0] == 0:
password_hash = bcrypt.hashpw( password_hash = bcrypt.hashpw(
config.DEFAULT_ADMIN_PASSWORD.encode("utf-8"), config.DEFAULT_ADMIN_PASSWORD.encode("utf-8"),
bcrypt.gensalt() bcrypt.gensalt()
).decode("utf-8") ).decode("utf-8")
conn.execute( conn.execute(
"INSERT INTO users (username, password_hash, role, max_goals) VALUES (?, ?, ?, ?)", "INSERT OR IGNORE INTO users (username, password_hash, role, max_goals) VALUES (?, ?, ?, ?)",
(config.DEFAULT_ADMIN_USERNAME, password_hash, "admin", 100) (config.DEFAULT_ADMIN_USERNAME, password_hash, "admin", 100)
) )
conn.commit() conn.commit()