Skip to content

Comments

fix(query): evict highest-cost node when MaxFrontierSize exceeded in shortest path#9607

Open
veeceey wants to merge 1 commit intodgraph-io:mainfrom
veeceey:fix/issue-9577-shortest-path-maxfrontiersize
Open

fix(query): evict highest-cost node when MaxFrontierSize exceeded in shortest path#9607
veeceey wants to merge 1 commit intodgraph-io:mainfrom
veeceey:fix/issue-9577-shortest-path-maxfrontiersize

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 23, 2026

Fixes #9577

The MaxFrontierSize feature introduced in #9333 has a bug in how it evicts nodes from the priority queue when the size limit is exceeded.

The current code calls pq.Pop() directly on the slice (not heap.Pop), which:

  1. Removes the last element of the underlying array rather than the highest-cost item. In a min-heap, the last element's cost is arbitrary, so we might drop a low-cost node that's actually on the shortest path.
  2. Doesn't maintain the heap invariant since it bypasses container/heap, corrupting the queue for subsequent heap.Push/heap.Pop calls.

The fix adds a removeMax() method that scans for the highest-cost item and removes it using heap.Remove(), which properly rebalances the heap. This ensures we always evict the least promising node while preserving the priority queue invariant and keeping shortest-path correctness.

Affects both the single shortest path (shortestPath) and k-shortest-path (runKShortestPaths) code paths.

All existing query package tests pass.

…in shortest path

When MaxFrontierSize is triggered, the code was calling pq.Pop()
directly on the slice instead of using heap.Pop(). This has two
problems:

1. pq.Pop() removes the last element of the underlying array, not the
   highest-cost item. In a min-heap, the last element has no guaranteed
   cost ordering, so it may remove a low-cost node that's actually
   needed for the shortest path.

2. Calling pq.Pop() directly (without heap.Pop) doesn't maintain the
   heap invariant, corrupting the priority queue for subsequent
   operations.

Fix this by adding a removeMax() method that finds and removes the
highest-cost item from the priority queue using heap.Remove(). This
ensures we always evict the least promising node while keeping the
heap valid, so the shortest path is preserved even when the frontier
size is limited.

Fixes dgraph-io#9577
@veeceey veeceey requested a review from a team as a code owner February 23, 2026 03:56
@veeceey
Copy link
Author

veeceey commented Feb 23, 2026

Test Results

Query package tests all pass:

$ go test ./query/ -count=1
ok  github.com/dgraph-io/dgraph/v25/query  4.521s

Package builds cleanly:

$ go build ./query/...
# no errors

The systest/shortest-path tests require a running dgraph instance so I couldn't run those locally, but the fix is logically straightforward - replacing direct slice manipulation with proper heap removal of the max-cost node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

k shortest path does not return the shortest path when using MaxFrontierSize

1 participant