mobile: fix the empty torrent list on the direct XML-RPC mount, plus a round of fixes - #3134
Conversation
- Fix the empty torrent list on the direct XML-RPC mount (reported on the bundling PR): the tracker fetch sent ?action=getalltrackers with no hashes. httprpc treats that as "all torrents", but the direct mount's stub builds one t.multicall per given hash and silently sends nothing for an empty list - its callback never fires, and the list render lives in that callback. Name every hash explicitly, like the desktop's getAllTrackers, and short-circuit the zero-torrent case (the render also removes deleted torrents' rows, so it must still run) - Insert torrents that appear between full renders (e.g. added from another session) at their sorted position instead of appending them to the end of the list - Toast torrents added from elsewhere (another session, rss, automation), like the deletion toasts; a local add keeps its upload receipt and scroll-to-torrent instead. Skip the first render cycle, when every torrent counts as new - Dismiss the on-screen keyboard on scroll for all text fields, not just the quick search - Commit a new-label edit only via its check button or the return key; tapping or scrolling away now cancels instead of saving
|
@xombiemp I have cherry-picked both commits and the torrent list is populating now... It is looking good :) |
|
Tested this on a large torrent list and it regresses into the same blank screen it fixes. Claude explains it better, sorry for the slop: getalltrackers is a GET and this names every hash in the query string; on a ~950-torrent view that's a ~46 KB URL, which nginx rejects with 414 Request-URI Too Large before it reaches PHP — the request fails, the callback never runs, list stays empty. The wall is nginx's default large_client_header_buffers (8 KB) ≈ ~150 hashes (measured: 105 hashes/5 KB reaches PHP, 950/46 KB → 414). Small lists test clean, which is why the reporter's did, but a few hundred+ torrents gets the Options:
In any case, test it (well, everything) against a rtorrent/ruTorrent with around 5k torrents loaded. It's more common than you'd think. |
|
@xirvik Not sure I'm following this one completely. AI seems to think the in repo backends are not affected: On stock httprpc, the wire request for a large list is byte-for-byte identical before and after our PR. On the direct mount, the hashes travel as an XML POST body — no URL, no 414. The regression needs a transport that (a) puts the query in a GET URL and (b) does its >50 collapse somewhere our fetch doesn't pass through. So is there a backend I'm not aware of? |
Naming every hash regressed large lists on transports that carry the query string in the request line: at ~950 torrents the URL outgrows nginx's default buffers and is 414-rejected before PHP could collapse it (stock httprpc was unaffected — its stub override collapses >50 hashes to the hashless form and POSTs a body either way). The PHP transports all treat a hashless getalltrackers as "all torrents", which is exactly what this fetch wants, so send that form. Enumerate the hashes only when a probe shows the active transport is the base XML-RPC stub — the one case that silently drops the hashless form, and the bug the enumeration was added for. There the hashes travel as POSTed XML with the stub's existing fragmentation, so no list size can overflow anything.
|
@xirvik I implemented your suggestion 3. Can you try it out on your system where it failed previously? |
I'm not totally sure the fail wasn't due to my own tests - sorry about this, I suspect I made you waste a bit of time on this one. |
Summary
Follow-up to #3128. The headline fix is the empty torrent list reported by @Abzie in the #3128 discussion, which affects installs using the direct XML-RPC mount (no httprpc):
?action=getalltrackerswith no hashes. httprpc happens to treat an empty hash list as "all torrents", but the direct mount's stub (rTorrentStub.prototype.getalltrackers) builds onet.multicallper given hash — with none given it produces zero commands, andrTorrentStubsilently drops command-less requests without invoking the callback. The mobile list render runs inside that callback, so the list stayed empty forever while settings/add pages worked. The fetch now names every hash explicitly, exactly like the desktop'sgetAllTrackers, and short-circuits the zero-torrent case (the render also removes deleted torrents' rows, so it must still run).Also in this round:
Test plan
Made with Cursor