odysseus/routes
Joeseph Grey 2c394704c6
Some checks are pending
CI / Focused test guidance (report-only) (push) Waiting to run
CI / Python syntax (compileall) (push) Waiting to run
CI / JS syntax (node --check) (push) Waiting to run
CI / Python tests (pytest) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
ci / docker publish / build (amd64) (push) Waiting to run
ci / docker publish / build (arm64) (push) Waiting to run
ci / docker publish / merge manifest + tag (push) Blocked by required conditions
fix(personal): run directory indexing off the event loop (#5634)
* fix(personal): run directory indexing off the event loop (#5558)

POST /api/personal/add_directory called rag.index_personal_documents
inline from an async handler, so the whole indexing job (os.walk, file
reads, per-chunk embedding, Chroma inserts) ran on the event loop and
every other request queued behind it. Indexing a real directory froze
the UI and API for 25+ minutes with no sign of life.

Move the blocking section into the threadpool via run_in_threadpool.
personal_docs_manager.add_directory stays inside it because its
refresh_index() re-extracts text across tracked directories, which is
also blocking work. A module-level lock serializes index jobs so the
threadpool move does not introduce parallel jobs racing
PersonalDocsManager's unsynchronized list mutations and file writes;
they previously serialized on the blocked loop, so one-at-a-time is
behavior parity.

* fix(personal): serialize add/remove/reload on an async job lock

The #5558 fix took the job lock INSIDE the threadpool worker and only on the
add path, so (1) remove_directory and /reload mutated PersonalDocsManager's
unsynchronized list/index concurrently with an in-flight add — the inconsistent
state the PR claimed to prevent — and (2) a queued add blocked on the lock while
holding an AnyIO threadpool token, starving the shared pool.

Move the lock to an asyncio.Lock acquired in the async handler BEFORE offloading,
and route add, remove and reload through it. A waiting request now parks on the
event loop instead of pinning a worker, and all three mutators are serialized so
the 'add/remove are serialized and cannot leave inconsistent state' guarantee
holds. remove and reload also run their blocking work off the event loop. The
lock is per-router so each app binds it to its own loop; single-process scope.

Tests: add-vs-remove and add-vs-reload serialization regressions (async via
ASGITransport, since asyncio.Lock deadlocks starlette TestClient's portal); the
existing add-vs-add test converted to the same driver.

* fix(personal): route upload and delete through the index job lock

/api/personal/upload and DELETE /api/personal/file mutated the same
vector and tracking state add/remove/reload serialize on, outside
_index_job_lock and inline on the event loop.

Both now stage async work on the loop, then run the complete transition
(vector writes, disk change, personal_docs_manager update) in one
offloaded critical section under the shared lock, acquired before the
offload so queued requests park on the loop rather than pinning a
threadpool worker.

Adds add-vs-upload and add-vs-file ordering regressions.

* fix(personal): bound multi-file upload memory

---------

Co-authored-by: RaresKeY <158580472+RaresKeY@users.noreply.github.com>
2026-08-15 10:12:47 +01:00
..
admin_wipe refactor(routes): move admin_wipe domain into routes/admin_wipe/ subpackage (#5659) 2026-07-21 12:39:27 +02:00
cleanup refactor(routes): move cleanup domain into routes/cleanup/ subpackage (#5658) 2026-07-21 12:38:32 +02:00
compare refactor(routes): move compare domain into routes/compare/ subpackage (#5660) 2026-07-21 12:40:09 +02:00
contacts Merge remote-tracking branch 'origin/dev' 2026-07-07 00:51:34 +00:00
document refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
gallery fix(gallery): handle MPS float64 mask inputs (#5903) 2026-08-12 01:23:43 +01:00
history fix(history): defer full transcript hydration to model sends (#5929) 2026-08-10 19:39:21 +01:00
mcp refactor(routes): move mcp domain into routes/mcp/ subpackage (#5899) 2026-08-11 02:24:55 -06:00
memory fix(memory): don't let an unreadable store get overwritten with an empty one (#5831) 2026-08-06 02:33:50 -06:00
note fix(reminders): support OAuth SMTP accounts (#5649) 2026-07-22 16:03:35 +02:00
research fix(security): make research path lookup CodeQL-friendly (#5129) 2026-07-04 20:17:45 +02:00
search refactor(routes): move search domain into routes/search/ subpackage (#5779) 2026-07-28 22:26:29 +02:00
vault refactor(routes): move vault domain into routes/vault/ subpackage (#5780) 2026-08-03 20:44:00 +02:00
webhook refactor(routes): move webhook domain into routes/webhook/ subpackage (#5781) 2026-08-03 20:44:31 +02:00
__init__.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
_validators.py fix(hwfit): validate remote SSH detection targets (#3718) 2026-06-11 00:43:49 +02:00
admin_wipe_routes.py refactor(routes): move admin_wipe domain into routes/admin_wipe/ subpackage (#5659) 2026-07-21 12:39:27 +02:00
api_token_routes.py fix(api): normalize non-object JSON bodies to empty dict in token PATCH (#3976) 2026-06-15 18:05:15 +01:00
assistant_routes.py fix(auth): centralize password and username validation constants (#4120) 2026-06-16 09:52:15 +02:00
auth_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
backup_routes.py fix(memory): don't let an unreadable store get overwritten with an empty one (#5831) 2026-08-06 02:33:50 -06:00
calendar_routes.py fix(calendar): keep default creation transactional (#5806) 2026-08-12 04:51:52 +01:00
chat_helpers.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
chat_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
chatgpt_subscription_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
cleanup_routes.py refactor(routes): move cleanup domain into routes/cleanup/ subpackage (#5658) 2026-07-21 12:38:32 +02:00
codex_routes.py fix: improve uploaded document retrieval and deep research reuse (#4784) 2026-06-27 19:24:17 +01:00
compare_routes.py refactor(routes): move compare domain into routes/compare/ subpackage (#5660) 2026-07-21 12:40:09 +02:00
contacts_routes.py Merge remote-tracking branch 'origin/dev' 2026-07-07 00:51:34 +00:00
cookbook_helpers.py Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbook_output.py fix(cookbook): report dead finished downloads as completed instead of stopped (#4025) 2026-06-15 15:26:55 +09:00
cookbook_routes.py fix(cookbook): record real Windows pid for local serve so Stop kills the model (#5912) 2026-08-12 10:32:24 +01:00
copilot_routes.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
device_flow.py feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
diagnostics_routes.py feat(ui): add real-time diagnostic logs console (#974) 2026-06-15 10:32:51 +02:00
document_helpers.py refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
document_routes.py refactor(routes): move document domain into routes/document/ subpackage (#5885) 2026-08-04 03:54:55 -06:00
editor_draft_routes.py Ignore invalid editor draft payloads (#1533) 2026-06-03 14:07:03 +09:00
email_helpers.py fix(email): route summaries through shared LLM adapter (#5841) 2026-08-08 23:06:41 +02:00
email_pollers.py fix(email): route summaries through shared LLM adapter (#5841) 2026-08-08 23:06:41 +02:00
email_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
embedding_routes.py feat(paths): abstract runtime path logic for frozen distribution packages (#969) 2026-06-15 17:44:10 +01:00
emoji_routes.py refactor(constants): single source of truth for data dir (#3368) 2026-06-08 09:58:52 +02:00
font_routes.py Keep compact font family names together (#1263) 2026-06-03 14:24:30 +09:00
gallery_helpers.py Merge dev into main for testing 2026-06-28 14:07:23 +00:00
gallery_routes.py Merge dev into main for testing 2026-06-28 14:07:23 +00:00
history_routes.py refactor(routes): move history domain into routes/history/ subpackage (#5090) 2026-07-04 13:36:35 +02:00
hwfit_routes.py Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
mcp_routes.py refactor(routes): move mcp domain into routes/mcp/ subpackage (#5899) 2026-08-11 02:24:55 -06:00
memory_routes.py refactor(routes): move memory domain into routes/memory/ subpackage (#5007) 2026-06-30 17:52:14 +02:00
model_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
note_routes.py refactor(routes): move note domain into routes/note/ subpackage (#5236) 2026-07-20 13:52:30 +02:00
personal_routes.py fix(personal): run directory indexing off the event loop (#5634) 2026-08-15 10:12:47 +01:00
prefs_routes.py refactor(model-routing): centralize explicit foreground fallback policy (#6020) 2026-08-14 08:10:30 +01:00
preset_routes.py fix(ai): offload model resolution from async paths 2026-06-28 00:48:35 +01:00
research_routes.py refactor(routes): move research domain into routes/research/ subpackage 2026-06-28 14:34:11 +01:00
search_routes.py refactor(routes): move search domain into routes/search/ subpackage (#5779) 2026-07-28 22:26:29 +02:00
session_routes.py fix(history): defer full transcript hydration to model sends (#5929) 2026-08-10 19:39:21 +01:00
shell_routes.py Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
signature_routes.py Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
skills_routes.py fix(skills): use utility model for skill tests instead of chat default (#5746) 2026-07-30 09:06:31 +01:00
stt_routes.py refactor(uploads): centralize upload byte-limits in upload_limits.py (#3364) (#3518) 2026-06-09 01:24:30 +02:00
task_routes.py fix(tasks): gate cookbook serve task execution (#5235) 2026-07-05 13:19:04 +01:00
tts_routes.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
upload_routes.py fix(stabilization): harden attachment lifecycle and agent guard signals (#5420) 2026-07-11 15:14:14 +01:00
vault_routes.py refactor(routes): move vault domain into routes/vault/ subpackage (#5780) 2026-08-03 20:44:00 +02:00
webhook_routes.py refactor(routes): move webhook domain into routes/webhook/ subpackage (#5781) 2026-08-03 20:44:31 +02:00
workspace_routes.py feat(agent): confine agent file/shell tools to a selectable workspace (#3665) 2026-06-11 18:17:54 +02:00