Skip to content

copy Omicron's sort order for mock API items#3033

Open
charliepark wants to merge 25 commits intomainfrom
sort_mock_api_items
Open

copy Omicron's sort order for mock API items#3033
charliepark wants to merge 25 commits intomainfrom
sort_mock_api_items

Conversation

@charliepark
Copy link
Contributor

@charliepark charliepark commented Feb 5, 2026

This PR copies the Omicron API's sorting in the mock API, so Console results more accurately reflect what a user would see on an actual rack.
Before:
Screenshot 2026-02-18 at 3 06 45 PM

After:
Screenshot 2026-02-18 at 3 05 57 PM

Screenshot 2026-02-18 at 3 08 08 PM Screenshot 2026-02-18 at 3 08 45 PM

This should not affect tables / lists with custom sort orders:
Screenshot 2026-02-18 at 3 09 01 PM

Closes #2776


Changes Made

  1. Updated mock-api/msw/util.ts
  • Added a sortItems() function that implements sorting for all sort modes:
    • name_ascending / name_descending - sorts alphabetically by name
    • id_ascending - sorts lexicographically by ID (UUID)
    • time_and_id_ascending / time_and_id_descending - sorts by timestamp, then by ID
  • Updated the paginated() function to:
    • Accept a sortBy parameter in the query options
    • Apply default sorting matching Omicron's behavior:
      • name_ascending for items with a name field (most common)
      • id_ascending for items without a name field
    • Sort items before paginating
  1. Updated mock-api/msw/util.spec.ts
  • Fixed the pagination test to expect lexicographically sorted results, matching how UUIDs are actually compared in Rust

Key Findings from Omicron Analysis

Based on the Omicron source code (https://github.com/uuid-rs/uuid):

  • UUIDs in Rust use lexicographic byte-by-byte comparison because the Ord trait is derived for Uuid(Bytes), which wraps a [u8; 16] array
  • Arrays in Rust compare element-by-element from left to right
  • This means my implementation using localeCompare() in JavaScript correctly matches Omicron's UUID sorting behavior

The mock API now properly sorts results by default, matching Omicron's pagination behavior where:

  • Most endpoints default to name_ascending (alphabetical by name)
  • Endpoints without names default to id_ascending (lexicographic by UUID)
  • Time-based sorting is only used when explicitly requested

Sources:

@vercel
Copy link

vercel bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
console Ready Ready Preview Feb 21, 2026 1:11am

Request Review

@charliepark
Copy link
Contributor Author

Can't say I love this, but I think this is just a quirk of the names we've given them and lexicographical ordering.
Screenshot 2026-02-06 at 10 41 29 AM

const { project } = useProjectSelector()
const snapshotsQuery = useQuery(q(api.snapshotList, { query: { project } }))
const snapshotsQuery = useQuery(
q(api.snapshotList, { query: { project, limit: ALL_ISH } })
Copy link
Contributor Author

@charliepark charliepark Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our snapshots dropdown was getting cut off; we should think about a more robust fix in a future PR for very long snapshot lists

@david-crespo
Copy link
Collaborator

I see the resolvePoolSelector fix and disk create page size, but what does the sorting buy us in terms of ensuring the console’s correctness as a client? It would make more sense to me if we let you change the sort order on a table — then we’d need to implement it on the API side at least enough to exercise the client.

@charliepark
Copy link
Contributor Author

Sorry; wrote and never hit the button to submit this.

My intent with this is less that we're ensuring correctness in the client, but more that it's a representation of the saga defaults that Omicron sets up. This is tied, in part, to #2932, which would actually add the "default" data to the mock DB, but this PR's intent is to render the mock DB's data in the console it in a similar order to how the API would return it.

@david-crespo
Copy link
Collaborator

david-crespo commented Feb 25, 2026

Fidelity to the real API logic is not necessarily a goal in itself. For me, it’s only a goal insofar as it helps us test (manually or automatically) the correctness of the client logic. That’s how we keep the mock server’s complexity manageable — we could go arbitrarily detailed in our imitation of Nexus, but we only do the minimum necessary to exercise the console. Lack of infidelity is more important to me than positive fidelity, and my worry is that this sorting logic as written is a kind of false fidelity — it's not actually very accurate to the API but it gives the impression that it should be. I might rather do nothing and be clear we're doing nothing (the status quo) than give that impression.

For example: in Nexus, the page token encodes not only the identifier for the last item in the previous page but also the sort mode and the limit [apparently not]. The idea is that after the first page, you don't need to pass sort_by or limit anymore — the page token is sufficient. This PR adds sort modes but does not go all the way toward encoding the relevant stuff in the token. The current composite token complicates things a lot by making the structure of the token conditional on the sort mode, but because it doesn't include the sort mode, it doesn't really add anything over using the ID as the page token.

Going back to using the ID as the token takes a lot of the complexity away, without losing much — see #3094. With that simplification in place it will be easier to ask whether this logic makes it easier to ensure the console is correct. Might also be worth considering going the other way, putting the sort mode in the page token.

@david-crespo
Copy link
Collaborator

Another thing I thought of that might be interesting: if we really wanted to know what sort modes were allowed on a given endpoint, we have that from the OpenAPI schema because every sort_by has a type that's an enum of the allowed values. We could inject that as an argument to the handler callback so it could be passed to the pagination function.

https://github.com/oxidecomputer/oxide.ts/blob/ce25ee603cf7b07a0ce5732766e78677ebf37964/oxide-openapi-gen-ts/src/client/msw-handlers.ts#L125-L136

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.

Update the mock API to alphabetize paginated list queries

2 participants