[PR #21909] Fix: redis release lock atomic #26332

Open
opened 2026-04-20 06:26:35 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/21909
Author: @jmleksan
Created: 2/26/2026
Status: 🔄 Open

Base: devHead: fix/Redis-release-lock-atomic


📝 Commits (1)

  • f5f0bc0 fix: atomic Redis lock release and renew

📊 Changes

2 files changed (+42 additions, -13 deletions)

View changed files

📝 backend/open_webui/socket/main.py (+7 -7)
📝 backend/open_webui/socket/utils.py (+35 -6)

📄 Description

Pull Request Checklist

This is to ensure large feature PRs are discussed with the community first, before starting work on it. If the community does not want this feature or it is not relevant for Open WebUI as a project, it can be identified in the discussion before working on the feature and submitting the PR.

Before submitting, make sure you've checked the following:

  • Target branch: Verify that the pull request targets the dev branch. PRs targeting main will be immediately closed.
  • Description: Provide a concise description of the changes made in this pull request down below.
  • Changelog: Ensure a changelog entry following the format of Keep a Changelog is added at the bottom of the PR description.
  • Documentation: Add docs in Open WebUI Docs Repository. Document user-facing behavior, environment variables, public APIs/interfaces, or deployment steps. (N/A: internal lock implementation, no user-facing changes.)
  • Dependencies: Are there any new or upgraded dependencies? If so, explain why, update the changelog/docs, and include any compatibility notes. (None.)
  • Testing: Perform manual tests to verify the implemented fix/feature works as intended AND does not break any other functionality. Include reproducible steps to demonstrate the issue before the fix. Test edge cases (URL encoding, HTML entities, types). Take this as an opportunity to make screenshots of the feature/fix and include them in the PR description.
  • Agentic AI Code: Confirm this Pull Request is not written by any AI Agent or has at least gone through additional human review AND manual testing. If any AI Agent is the co-author of this PR, it may lead to immediate closure of the PR.
  • Code review: Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards?
  • Design & Architecture: Prefer smart defaults over new settings; use local state for ephemeral UI logic. Open a Discussion for major architectural or UX changes.
  • Git Hygiene: Keep PRs atomic (one logical change). Clean up commits and rebase on dev to ensure no unrelated commits (e.g. from main) are included. Push updates to the existing PR branch instead of closing and reopening.
  • Title Prefix: To clearly categorize this pull request, prefix the pull request title using one of the following:
    • fix: Bug fix or error correction

Changelog Entry

Description

  • fix: Make Redis lock release atomic and fix acquire_lock typo.
    Redis lock release previously used a non-atomic GET-then-DEL sequence. We could GET our value, decide to delete, then—before our DEL runs—the key could expire and another process could acquire it; our DEL would then remove their lock. This change uses a Lua script so that “delete only if value equals my lock_id” runs atomically on Redis, ensuring we never release another process’s lock. Also renames aquire_lock to acquire_lock and updates all call sites.

  • 🔒 Redis lock release race. Releasing a Redis lock after TTL expiry could delete another process's lock because the previous implementation used a non-atomic GET-then-DEL sequence. Release now uses a Lua script so that "delete key only if value equals my lock_id" runs atomically on Redis, ensuring only the owning process can remove the key.

Added

  • Lua script _RELEASE_LOCK_IF_OWNER_SCRIPT for atomic “delete key only if value matches lock_id” in RedisLock.

Changed

  • RedisLock.release_lock() now calls the registered Lua script instead of separate GET/DEL.
  • Method name: aquire_lockacquire_lock in backend/open_webui/socket/utils.py and all references in backend/open_webui/socket/main.py (acquire_func, session_acquire_func, and fallback lambdas).

Fixed

  • Redis lock release race: Releasing a lock after TTL expiry could delete another process’s lock; release is now atomic so only the owning process can remove the key.

Security

  • (none; correctness fix reduces risk of mistaken lock release in multi-process/WebSocket cleanup.)

Breaking Changes

  • BREAKING CHANGE: The public method RedisLock.aquire_lock has been renamed to acquire_lock. Any external code calling aquire_lock must be updated. Internal call sites in this repo are updated.

Additional Information

  • Redis has no built-in “delete if value equals” command; the Lua script runs on the server so the check and delete are a single atomic operation.
  • Release remains best-effort (exceptions swallowed); if the script fails, TTL will still clear the key.

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/21909 **Author:** [@jmleksan](https://github.com/jmleksan) **Created:** 2/26/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `fix/Redis-release-lock-atomic` --- ### 📝 Commits (1) - [`f5f0bc0`](https://github.com/open-webui/open-webui/commit/f5f0bc0d4d714f13dad19a61e3edd3510600028c) fix: atomic Redis lock release and renew ### 📊 Changes **2 files changed** (+42 additions, -13 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/socket/main.py` (+7 -7) 📝 `backend/open_webui/socket/utils.py` (+35 -6) </details> ### 📄 Description # Pull Request Checklist This is to ensure large feature PRs are discussed with the community first, before starting work on it. If the community does not want this feature or it is not relevant for Open WebUI as a project, it can be identified in the discussion before working on the feature and submitting the PR. **Before submitting, make sure you've checked the following:** - [x] **Target branch:** Verify that the pull request targets the `dev` branch. **PRs targeting `main` will be immediately closed.** - [x] **Description:** Provide a concise description of the changes made in this pull request down below. - [x] **Changelog:** Ensure a changelog entry following the format of [Keep a Changelog](https://keepachangelog.com/) is added at the bottom of the PR description. - [x] **Documentation:** Add docs in [Open WebUI Docs Repository](https://github.com/open-webui/docs). Document user-facing behavior, environment variables, public APIs/interfaces, or deployment steps. *(N/A: internal lock implementation, no user-facing changes.)* - [x] **Dependencies:** Are there any new or upgraded dependencies? If so, explain why, update the changelog/docs, and include any compatibility notes. *(None.)* - [x] **Testing:** Perform manual tests to **verify the implemented fix/feature works as intended AND does not break any other functionality**. Include reproducible steps to demonstrate the issue before the fix. Test edge cases (URL encoding, HTML entities, types). Take this as an opportunity to **make screenshots of the feature/fix and include them in the PR description**. - [x] **Agentic AI Code:** Confirm this Pull Request is **not written by any AI Agent** or has at least **gone through additional human review AND manual testing**. If any AI Agent is the co-author of this PR, it may lead to immediate closure of the PR. - [x] **Code review:** Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards? - [x] **Design & Architecture:** Prefer smart defaults over new settings; use local state for ephemeral UI logic. Open a Discussion for major architectural or UX changes. - [x] **Git Hygiene:** Keep PRs atomic (one logical change). Clean up commits and rebase on `dev` to ensure no unrelated commits (e.g. from `main`) are included. Push updates to the existing PR branch instead of closing and reopening. - [x] **Title Prefix:** To clearly categorize this pull request, prefix the pull request title using one of the following: - **fix**: Bug fix or error correction --- # Changelog Entry ### Description - **fix: Make Redis lock release atomic and fix acquire_lock typo.** Redis lock release previously used a non-atomic GET-then-DEL sequence. We could GET our value, decide to delete, then—before our DEL runs—the key could expire and another process could acquire it; our DEL would then remove their lock. This change uses a Lua script so that “delete only if value equals my lock_id” runs atomically on Redis, ensuring we never release another process’s lock. Also renames `aquire_lock` to `acquire_lock` and updates all call sites. - 🔒 **Redis lock release race.** Releasing a Redis lock after TTL expiry could delete another process's lock because the previous implementation used a non-atomic GET-then-DEL sequence. Release now uses a Lua script so that "delete key only if value equals my lock_id" runs atomically on Redis, ensuring only the owning process can remove the key. ### Added - Lua script `_RELEASE_LOCK_IF_OWNER_SCRIPT` for atomic “delete key only if value matches lock_id” in `RedisLock`. ### Changed - `RedisLock.release_lock()` now calls the registered Lua script instead of separate GET/DEL. - Method name: `aquire_lock` → `acquire_lock` in `backend/open_webui/socket/utils.py` and all references in `backend/open_webui/socket/main.py` (`acquire_func`, `session_acquire_func`, and fallback lambdas). ### Fixed - **Redis lock release race:** Releasing a lock after TTL expiry could delete another process’s lock; release is now atomic so only the owning process can remove the key. ### Security - (none; correctness fix reduces risk of mistaken lock release in multi-process/WebSocket cleanup.) ### Breaking Changes - **BREAKING CHANGE**: The public method `RedisLock.aquire_lock` has been renamed to `acquire_lock`. Any external code calling `aquire_lock` must be updated. Internal call sites in this repo are updated. --- ### Additional Information - Redis has no built-in “delete if value equals” command; the Lua script runs on the server so the check and delete are a single atomic operation. - Release remains best-effort (exceptions swallowed); if the script fails, TTL will still clear the key. ### Contributor License Agreement <!-- 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. --> By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-20 06:26:35 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#26332