Skip to content

Defer all startup HTTP downloads until after partfile + shared-file scan - #719

Merged
mrjimenez merged 2 commits into
amule-project:masterfrom
got3nks:fix/defer-startup-http-downloads
May 26, 2026
Merged

Defer all startup HTTP downloads until after partfile + shared-file scan#719
mrjimenez merged 2 commits into
amule-project:masterfrom
got3nks:fix/defer-startup-http-downloads

Conversation

@got3nks

@got3nks got3nks commented May 25, 2026

Copy link
Copy Markdown
Contributor

Summary

CamuleApp::OnInit() fires two startup HTTP downloads — the GitHub version check (amule.cpp:669) and the server.met auto-update (CServerList::Init()AutoUpdate()) — before the heavy local I/O at downloadqueue->LoadMetFiles() and sharedfiles->Reload().

On nodes with a large library this is up to a minute of saturated main thread. The wxWebSession worker thread that pumps libcurl's state machines competes for CPU with that main thread, libcurl's per-handle timeout / retry logic advances less, and the DNS resolution can wall-clock out before it ever gets a chance to complete.

Empirical confirmation from the startup log @Stoatwblr posted on #714: same hostname (upd.emule-security.org), same wxWebRequest backend, parallel execution — server.met fired before the 91k-shared-file scan and timed out after 48.8s; ipfilter.zip fired from a post-Reload main-thread event and downloaded in 3s.

Fix

Move both kicks past sharedfiles->Reload() so they fire with the main thread idle:

  • CServerList::Init() is split so the disk load + static-server load still run early (needed before ServerConnect), but the AutoServerlist HTTP kick is exposed as a public StartAutoUpdate() for the caller to invoke later.
  • CamuleApp::OnInit() calls StartAutoUpdate() and the version-check CHTTPDownloadThread right after sharedfiles->Reload() returns.

IPFilter's auto-update is already correctly deferred via its post-Reload main-thread event and is unchanged. The first-launch bootstrap-download block at amule.cpp:736 is already past the heavy I/O and is also unchanged.

Test plan

Refs #714.

The two startup HTTP downloads — the GitHub version check (amule.cpp:669)
and the server.met auto-update (CServerList::Init calling AutoUpdate) —
used to fire synchronously *before* the heavy local I/O in
CamuleApp::OnInit (downloadqueue->LoadMetFiles + sharedfiles->Reload).

On nodes with a large library this is up to a minute of saturated main
thread. The wxWebSession worker thread that pumps libcurl's state
machines competes for CPU with that main thread, libcurl's per-handle
timeout / retry logic advances less, and DNS resolution can wall-clock
out before it ever gets a chance to complete.

Stoatwblr's startup log on amule-project#714 is the empirical confirmation: same
hostname (upd.emule-security.org), same wxWebRequest backend, parallel
execution — server.met fired before the 91k-shared-file scan and timed
out after 48.8s; ipfilter.zip fired from a post-Reload main-thread
event and downloaded in 3s.

Move both kicks past sharedfiles->Reload so they fire with the main
thread idle. CServerList::Init is split so the disk load + static-server
load still run early (needed before ServerConnect), but the
AutoServerlist HTTP kick is exposed as StartAutoUpdate() for the caller
to invoke later. IPFilter's auto-update is already correctly deferred
via its post-Reload main-thread event and is unchanged. The
first-launch bootstrap-download block at amule.cpp:736 is already past
the heavy I/O and is also unchanged.

Refs amule-project#714.
@mrjimenez
mrjimenez merged commit fe4e287 into amule-project:master May 26, 2026
7 checks passed
@got3nks
got3nks deleted the fix/defer-startup-http-downloads branch May 27, 2026 15:15
ngosang added a commit to ngosang/amule that referenced this pull request Jul 30, 2026
…mule-project#687) (amule-project#719)

1bc9d6e (amule-project#694) added GET /flags/{code}.png, but nothing consumed it: the
country column of the peer list and of the ed2k server list still painted only
the bare uppercase code, duplicating the same one-liner cell in two views.

Both now render through a single new CountryCell in components.js: the 16x11
famfamfam flag from the route followed by the code, the layout the desktop
lists already use. The image URL is built relative to window.location.pathname
like BASE in api.js, so it survives a reverse-proxy subpath, and the route's
one-day Cache-Control means a peer list full of <img> tags doesn't re-fetch a
flag per country on reload.

country_code is an empty string when the daemon's GeoIP is off or the IP
doesn't resolve (amule-project#439, amule-project#440), so an empty code short-circuits to the dash the
cell already showed -- no <img>, and in particular no request for the
"/flags/.png" the route would 404. A well-formed code the flag set has no
artwork for (zz, GeoIP pseudo-codes like ap/eu) also 404s, so onError hides
the image and leaves the code readable instead of a broken-image icon.

The cell gains a title with the localized country name via Intl.DisplayNames
({ type: "region" }) in the UI language, as docs/api/REFERENCE.md prescribes:
no endpoint and no new translation keys, since the browser already has the
data. The formatter is built once per module load, not once per row.

Column width goes 52px -> 70px to fit flag + code + sort arrow; sortVal is
unchanged, so the column still sorts by code.

Verified against a live daemon: flags render in the Networks server list and
the Clients list, an empty country_code shows the dash alone, /flags/zz.png
falls back to the hidden image, the tooltip follows the EN/ES switch
(France/Francia), sorting works both directions, and the console stays clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants