Skip to content

Review upload queue scoring against community and stale baselines

Historical reference only: stale-v0.72a-experimental-clean and analysis\stale-v0.72a-experimental-clean are retired reference sources, not active branch targets or current baselines. Use them only as provenance or idea-extraction sources; landed status is determined against main. See Historical References.

Summary

This note reviews the current upload queue-scoring path in eMule-main against:

  • analysis/community-0.72
  • analysis/stale-v0.72a-experimental-clean

The result is straightforward:

  • the core queue score and consumer shape is inherited from stock/community
  • the current broadband queue-score extras are inherited from the stale experimental branch
  • one meaningful semantic drift exists in main: the low-ratio bonus is now added after float-to-integer truncation instead of inside the float score pipeline

No separate bug item is opened from this review. The actionable follow-up remains FEAT-023, because the non-stock pieces are policy extras rather than accidental scheduler breakage.

Outcome Adopted Under FEAT-023

FEAT-023 now resolves the review decision on app branch feature/feat023-queue-scoring:

  • keep the stock/community score core unchanged
  • keep cooldown score suppression at effective score 0
  • keep the LowID divisor in the effective full-score path
  • restore stale low-ratio bonus placement inside the float score pipeline before:
  • LowID divisor
  • old-client penalty
  • final truncation
  • keep the inherited admission-vs-selection split unchanged
  • expose score breakdown state in desktop queue/upload/client-detail UI

This means the drift described below remains accurate for historical main at review time, but it is no longer the chosen FEAT-023 target semantics.

Baseline Comparison

Score formula

Common stock/community core in UploadClient.cpp:

  • base score is wait time in seconds, or capped upload-session time when already downloading
  • optional credit multiplier via credits->GetScoreRatio(GetIP())
  • optional file-priority multiplier via GetFilePrioAsNumber() / 10.0f
  • legacy old-client penalty: eMule <= 0x19 gets * 0.5f
  • result truncated to uint32

Branch deltas:

Behavior community-0.72 stale experimental current main
Slow-upload cooldown forces score 0 No Yes Yes
LowID score divisor No Yes Yes
Low-ratio file bonus No Yes Yes
Low-ratio bonus position n/a Added to float score before LowID divisor and old-client penalty Added after float truncation as integer bonus

Relevant code anchors:

  • community-0.72: UploadClient.cpp:180
  • stale-v0.72a-experimental-clean: UploadClient.cpp:182
  • main: UploadClient.cpp:180

Score consumers

These consumer shapes are effectively inherited from stock/community and preserved on main:

  • next uploader selection uses full score: UploadQueue.cpp:121, :138
  • queue rank uses full score: UploadQueue.cpp:909, :914
  • queue list and web UI display full score:
  • QueueListCtrl.cpp:262, :396
  • ClientDetailDialog.cpp:166
  • WebServer.cpp:2029
  • soft-queue-limit admission does not use full score; it uses GetCombinedFilePrioAndCredit():
  • UploadQueue.cpp:653
  • same split exists in community UploadQueue.cpp:627
  • same split exists in stale UploadQueue.cpp:715
  • max-score cache uses GetScore(true, false) rather than displayed rank score:
  • UploadQueue.cpp:796, :800
  • same behavior exists in community UploadQueue.cpp:763

Findings

1. Admission vs selection mismatch is inherited stock behavior, not a new branch regression

The queue soft-limit gate filters entrants using GetCombinedFilePrioAndCredit(), while actual queue order and rank use GetScore(false). This means waiting time and some score extras do not influence admission when the soft limit is already reached.

This is not new:

  • community does it
  • stale does it
  • current main preserves it

Decision: keep as-is for now and document it as inherited behavior. Do not treat it as a queue-scoring bug unless future user reports show starvation or visibly unfair soft-limit rejection.

2. Cooldown score suppression is an intentional broadband policy carry-over

IsInSlowUploadCooldown() returning queue score 0 came from the stale broadband branch and is still coherent with the stabilized controller: recycled weak slots are requeued for protocol compatibility but intentionally held back from immediate reselection.

Decision: keep under broadband policy. This belongs to FEAT-015/FEAT-023, not to core stock queue fairness.

3. LowID divisor is also intentional broadband policy, but only in the full-score path

The LowID divisor is a stale-branch seeding policy carry-over. It affects:

  • next-client selection
  • queue rank
  • displayed score

It does not affect:

  • soft-limit admission, which still uses GetCombinedFilePrioAndCredit()

Decision: keep for now, but document clearly in FEAT-023 that this is not a universal queue-priority rule. It is a full-score-only policy layer.

4. The low-ratio bonus semantics drifted from stale and should be treated as the main review outcome

In stale experimental, low-ratio bias was added to the float score before:

  • LowID divisor
  • old-client penalty
  • final truncation

In current main, the low-ratio bonus is added after:

  • old-client penalty
  • LowID divisor
  • float truncation to uint32

Practical effect:

  • the bonus is now stronger and more absolute than in stale
  • LowID clients no longer have that bonus reduced by the divisor
  • legacy-client penalty no longer scales that bonus down
  • near-threshold fractional score differences are discarded before the bonus is applied

This is the only clear semantic drift found in the current score formula.

Decision: resolved under FEAT-023 in favor of the stale semantics. The low-ratio bonus should move back into the float pipeline before divisor, penalty, and truncation.

5. Test coverage is currently missing at the score-policy layer

emulebb-build-tests currently has upload-queue flow tests, but no dedicated queue-score formula or consumer consistency tests.

Decision: no further queue-score retuning should land without a deterministic seam and table-driven score tests.

Recommendations

Keep

  • community-inherited score core
  • community-inherited admission-vs-selection split
  • cooldown score suppression
  • LowID divisor as a broadband-only policy layer

Implement explicitly under FEAT-023

  • low-ratio bonus placement restored to stale semantics
  • cooldown remains an explicit effective-score suppression
  • LowID divisor remains a full-score-only policy layer
  • desktop UI should present base score, effective score, and active modifiers

Required tests before any retune

  • score parity for the community stock path
  • stale-vs-main comparison for low-ratio bonus and LowID divisor
  • cooldown forcing score 0
  • admission gate using GetCombinedFilePrioAndCredit() while rank/selection use GetScore
  • GetScore(true, false) cache behavior versus displayed GetScore(false)

Follow-up Routing

  • FEAT-023 remains the home for queue-score extras and any retune/removal decision
  • no separate bug entry opened from this review
  • if future work wants to unify admission and selection semantics, that should be a new, explicit follow-up rather than an untracked side effect of FEAT-023