mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-28 05:27:35 +00:00
perf: throttle last_active_at writes by default (#28177)
Presence tracking writes each user's last_active_at on every authenticated request, every API key request and every websocket heartbeat. The throttle for it already exists but ships unset, and unset means no throttle at all, so a stock deployment pays one UPDATE plus COMMIT per user per request. The 30 second frontend heartbeat alone is 2 write transactions per minute per open tab, before any actual UI traffic. Defaulting the throttle to 60 seconds collapses that to at most one write per user per worker per minute. Presence is only ever read at minute granularity, so nothing visible changes. 60 rather than the 300 to 500 the docs currently suggest, because a user counts as active for 3 minutes after their last write and that window is hardcoded in the backend and again in the frontend. Any interval at or above 180 seconds makes people who are actively using the instance drop out of the active user count. Letting the window follow the interval instead would need the value shipped to the client, so that is a separate change. 0 still disables the throttle, and now costs nothing at all: the decorator returns the undecorated function instead of a wrapper that re-checks a constant on every call. Closes #28165
This commit is contained in:
parent
da9245626e
commit
043cf330d2
2 changed files with 9 additions and 9 deletions
|
|
@ -353,12 +353,11 @@ DATABASE_SQLITE_PRAGMA_MMAP_SIZE = os.getenv('DATABASE_SQLITE_PRAGMA_MMAP_SIZE',
|
|||
# truncated. 67108864 ≈ 64 MB. Set to -1 for no limit (SQLite default).
|
||||
DATABASE_SQLITE_PRAGMA_JOURNAL_SIZE_LIMIT = os.getenv('DATABASE_SQLITE_PRAGMA_JOURNAL_SIZE_LIMIT', '67108864')
|
||||
|
||||
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = os.getenv('DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL', None)
|
||||
if DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL is not None:
|
||||
try:
|
||||
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = float(DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL)
|
||||
except Exception:
|
||||
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = 0.0
|
||||
# Seconds between presence writes per user per worker; keep under the 180s active-user window. 0 disables.
|
||||
try:
|
||||
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = float(os.getenv('DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL', '60'))
|
||||
except ValueError:
|
||||
DATABASE_USER_ACTIVE_STATUS_UPDATE_INTERVAL = 60.0
|
||||
|
||||
DATABASE_ENABLE_SESSION_SHARING = os.getenv('DATABASE_ENABLE_SESSION_SHARING', 'False').lower() == 'true'
|
||||
ENABLE_PUBLIC_ACTIVE_USERS_COUNT = os.getenv('ENABLE_PUBLIC_ACTIVE_USERS_COUNT', 'True').lower() == 'true'
|
||||
|
|
|
|||
|
|
@ -1109,16 +1109,17 @@ def throttle(interval: float = 10.0):
|
|||
different types, the return type of the function should be T | None.
|
||||
|
||||
:param interval: Duration in seconds to wait before allowing the function to be called again.
|
||||
Zero or negative disables throttling.
|
||||
"""
|
||||
|
||||
def decorator(func):
|
||||
if interval <= 0:
|
||||
return func
|
||||
|
||||
last_calls = {}
|
||||
lock = threading.Lock()
|
||||
|
||||
async def wrapper(*args, **kwargs):
|
||||
if interval is None:
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
key = (args, freeze(kwargs))
|
||||
now = time.time()
|
||||
if now - last_calls.get(key, 0) < interval:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue