Skip to content

session.list_jobs builds and sorts the full job set before paging #67

@nficano

Description

@nficano

Summary

Second-pass performance/code-quality audit finding. JobManager.List fully materializes the caller-visible job set, repeatedly rematerializes filtered lists, sorts all matches, and only then applies Skip/Take for the requested page.

Evidence

  • src/Arcp.Runtime/JobManager.Listing.cs:19 starts by collecting all principal-visible jobs via FilterByPrincipal.
  • src/Arcp.Runtime/JobManager.Listing.cs:20 runs ApplyFilter, whose status/agent/date branches each call .Where(...).ToList().
  • src/Arcp.Runtime/JobManager.Listing.cs:21 sorts the complete filtered set with .OrderBy(...).ToList().
  • src/Arcp.Runtime/JobManager.Listing.cs:25 applies Skip(skip).Take(take) only after the full list exists.

Why it matters

Each session.list_jobs page is O(n log n) over every visible job and allocates multiple intermediate lists. A client paginating through a long-running runtime repeats that work on every page, so the advertised limit does not bound server-side work.

Proposed fix

Use a stable keyset cursor such as (created_at, job_id) and page from a maintained ordered index, or at least apply filtering and limit + 1 while streaming a single ordered snapshot. Convert status filters to a set once per request.

Acceptance criteria

  • limit bounds the amount of page materialization to limit + 1 entries after cursor positioning.
  • Pagination remains stable when multiple jobs share the same CreatedAt.
  • A regression/benchmark covers a large job registry and verifies that requesting a small page does not sort/rematerialize every visible job.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions