Skip to content

BUG-151 - REST category mutations time out (503) because they block on the main UI thread under load

Summary

eMuleBB REST category mutations (categories/create, categories/update, categories/delete, categories/rename) are dispatched synchronously to the main window and wait for the UI thread to service the command. On large profiles (observed against a ~66k shared-file instance) and/or while a controller such as aMuTorrent polls the REST API, the UI thread does not service the dispatched message within the timeout, so the mutation returns 503 EMULE_UNAVAILABLE ("main window did not process REST command within N ms") or 503 "eMuleBB web API is busy".

As a result, a REST controller cannot reliably create/edit/delete categories. aMuTorrent has shipped a workaround that treats eMuleBB categories as read-only (import/display/assignment only, no writes pushed to eMuleBB). This item tracks the eMuleBB-side fix so REST category management works under normal load.

Current State

  • Category mutations run through the REST→UI dispatch path: the REST worker PostMessages WEB_REST_API_COMMAND to theApp.emuledlg->m_hWnd and blocks on WaitForSingleObject(..., kRestUiDispatchTimeoutMs) (WebServerJson.cpp ~4513-4537). On timeout it returns EMULE_UNAVAILABLE / "main window did not process REST command within N ms".
  • categories/create builds a Category_Struct, calls thePrefs.AddCat + SaveCats + RefreshCategoryUi (WebServerJson.cpp ~2958-2983) — work that is gated on UI-thread responsiveness.
  • Reproduced 2026-06-13 against 192.168.1.210:4711 (66,140 shared files):
  • With the aMuTorrent controller polling (snapshot + per-transfer detail calls every ~3s), POST /api/v1/categories and DELETE /api/v1/categories/{id} returned 503 repeatedly.
  • With the controller stopped, the identical DELETE returned 200 immediately — confirming the failure is UI-thread contention, not a bad request.

Why This Matters

Controller-driven category management (aMuTorrent, Arr workflows) is part of the RC integration story. Without a fix, controllers must lock category writes and users must manage categories only in the eMuleBB GUI. The single-web-worker plus synchronous UI dispatch also means routine polling can starve mutations.

Representative Sites

  • srchybrid/WebServerJson.cppcategories/create|update|delete|rename command handlers (~2958+).
  • srchybrid/WebServerJson.cpp — REST→UI synchronous dispatch (PostMessage(WEB_REST_API_COMMAND) + WaitForSingleObject, WebServerJsonSeams::kRestUiDispatchTimeoutMs, ~4513-4537).
  • 503 "web API is busy" backpressure guard (single web worker).

Intended Shape

Candidate directions (to be evaluated, not yet decided):

  • Reduce category mutations' dependence on a synchronous UI-thread round-trip: perform the preference/category-model mutation on a path that does not require the UI message pump to be idle, refreshing UI asynchronously afterwards.
  • And/or make the dispatch resilient under polling load (fair queueing so a mutation is not starved by snapshot GETs; bounded retry/backoff with a clear Retry-After).
  • Keep stock category semantics and persistence (thePrefs.AddCat/SaveCats).

Scope Constraints

  • eMuleBB-side (C++ app). Under the RC2 soft freeze this is post-0.7.3 unless explicitly reclassified as release-blocking.
  • Out of scope: the aMuTorrent-side lock, which already landed (clientMeta emulebb.capabilities.categoryWrite = false; CategoryManager skips read-only backends for category writes; web UI hides create/edit/delete for read-only ED2K backends).

Acceptance Criteria

  • [ ] POST/PUT/DELETE category REST mutations succeed under normal controller polling on a large (tens-of-thousands shared files) profile, without 503 EMULE_UNAVAILABLE.
  • [ ] Category model and persistence semantics are unchanged (categories created via REST appear identically to GUI-created ones).
  • [ ] A controller polling the snapshot endpoint cannot indefinitely starve a category mutation.
  • [ ] Debug, Release, and diagnostics Release x64 app builds pass before commit.

Notes

  • Provenance: operator testing of the aMuTorrent eMuleBB integration on 2026-06-13 (uploads/servers/history-metadata adapter fixes landed in the controller in the same session; category creation was locked there pending this fix).
  • Related: the single-web-worker "busy" 503 backpressure interacts with this; consider together.