open-webui/backend/open_webui
Claude 860bde8842
fix(stream): close replay race, cursor-efficient resume, bounded client bookkeeping
Three review findings, all valid:

1. Race: log-then-emit instead of emit-then-log
   The previous ordering emitted the live WS frame first and appended
   to Redis afterward. A client disconnecting in that window and
   reconnecting before the append completed would issue resume-stream,
   see nothing newer, and never ask again — permanently losing that
   frame (most painfully the terminal done:True frame). Inverted the
   order: the log is now the source of truth for what was "sent", and
   the live emit follows. A reconnect that races the append now may
   see a replayed frame before the live frame arrives in the new
   session, but the seq idempotency guard in chatEventHandler drops
   the duplicate harmlessly. Duplicates are safe; losses are not.

2. Resume reads no longer full-scan
   XADD now uses an explicit stream ID of `0-{seq}` (the per-emitter
   seq counter guarantees strict monotonicity), so _stream_log_read
   can start XRANGE at `0-{after_seq+1}` and let Redis skip entries
   already delivered. Near-tail resumes (the common case) go from
   O(MAXLEN) to O(missed frames). Dropped the now-redundant seq field
   from the stream entries and the Python-side seq filter — the
   envelope still carries seq internally for client-side idempotency.

3. Client map is now pruned
   resumeSeqByMessageId was growing unboundedly across the session.
   Now:
     - cleared on loadChat (chat switch)
     - cleared on initNewChat (new chat)
     - individual entries deleted in chatCompletionEventHandler's
       done:true branch (most messages evict quickly this way)
   Long-lived sessions no longer accumulate dead keys for every
   completed message they've ever seen.
2026-04-14 21:34:44 +00:00
..
data refac: mv backend files to /open_webui dir 2024-09-04 16:54:48 +02:00
internal refac 2026-04-12 19:41:02 -05:00
migrations refac 2026-04-01 18:26:46 -05:00
models refac 2026-04-13 21:29:03 -05:00
retrieval fix(retrieval): offload Loader.load to a worker thread so file uploads stop blocking the event loop (#23705) 2026-04-14 10:55:46 -05:00
routers fix(retrieval): offload Loader.load to a worker thread so file uploads stop blocking the event loop (#23705) 2026-04-14 10:55:46 -05:00
socket fix(stream): close replay race, cursor-efficient resume, bounded client bookkeeping 2026-04-14 21:34:44 +00:00
static refac 2026-03-23 23:39:52 -05:00
storage refac 2026-04-12 19:08:30 -05:00
test refac 2026-03-17 17:58:01 -05:00
tools fix(retrieval): offload sync VECTOR_DB_CLIENT calls in async paths via AsyncVectorDBClient (#23706) 2026-04-14 10:50:18 -05:00
utils refac 2026-04-14 10:55:11 -05:00
__init__.py refac (#22987) 2026-03-24 15:41:26 -05:00
alembic.ini fix: Alembic CLI commands from failing 2025-08-15 04:17:47 -04:00
config.py refac 2026-04-14 00:07:50 -05:00
constants.py refac 2026-04-13 14:08:58 -05:00
env.py refac 2026-04-13 16:25:44 -05:00
functions.py refac: async db 2026-04-12 14:22:11 -05:00
main.py fix(middleware): replace BaseHTTPMiddleware HTTP middlewares with pure ASGI implementations (#23709) 2026-04-14 10:47:48 -05:00
tasks.py refac 2026-03-17 17:58:01 -05:00