Skip to content

Implement Priority Aging to Prevent Starvation in OutboundTxQueue #6

Description

@grantfox-oss

Implement Priority Aging to Prevent Starvation in OutboundTxQueue

Labels: hard reliability Official Campaign Maybe Rewarded
Component: src/queue/priority.rs


Problem

TxPriority (Low/Normal/Emergency) is assigned once, at push() time, and never changes. In a long-running offline scenario — the exact scenario this protocol targets — a Normal payment queued behind a steady stream of newly-arriving Emergency payments can wait indefinitely. Low-tier payments are worse off still. stellarconduit_core::gossip::queue::MessagePriority::urgency_score already solves an analogous problem for mesh-forwarding order by scoring on TTL and message age — this crate's local queue has no equivalent mechanism.

Requirements

  • Add an aging mechanism so a Normal/Low entry's effective dispatch priority increases the longer it waits, eventually reaching (or exceeding) Emergency's effective priority if it waits long enough. Do not mutate the original TxPriority the caller assigned — track effective priority separately (e.g. compute it at pop()/comparison time from priority + enqueued_at + "now").
  • Define and document your aging curve (linear, step-function, logarithmic — your choice, but justify it).
  • Preserve existing behavior for freshly-enqueued entries: a brand-new Low entry must not immediately outrank an old Emergency entry; aging should overtake other tiers only after a meaningful, documented wait threshold.
  • Ord/PartialOrd on the internal heap entry type currently only account for static priority + FIFO enqueued_at tie-break (see src/queue/priority.rs) — you'll need to change the comparison to account for a time-dependent effective priority, which requires either passing "now" into comparisons (tricky with BinaryHeap, which assumes a total order independent of external state) or re-scoring entries periodically. Pick an approach and justify the tradeoff (e.g. re-score/re-heapify on a timer vs. compute effective priority lazily on peek/pop and accept O(n) scans).

Acceptance Criteria

  • A Normal entry that has waited past the aging threshold pops ahead of a freshly-pushed Emergency entry.
  • A freshly-pushed Low/Normal entry does not jump ahead of tiers above it before the threshold.
  • Existing tests (test_higher_priority_pops_first, test_fifo_within_same_priority) still pass unmodified.
  • cargo fmt, cargo clippy -D warnings, and cargo test all pass.

Required Tests

  • test_aged_normal_outranks_fresh_emergency
  • test_fresh_low_does_not_outrank_anything
  • test_aging_curve_is_monotonic — effective priority never decreases as wait time increases.
  • test_existing_fifo_and_priority_tests_still_pass (i.e. don't regress current behavior).

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions