Skip to content

Conversation

@jmg-duarte
Copy link
Contributor

@jmg-duarte jmg-duarte commented Jan 22, 2026

Description

This PR migrates the orderbook API from Warp to Axum. The migration modernizes our web framework while maintaining API
compatibility, with improved code organization and reduced complexity (~200 lines removed).

Changes

  • Replace Warp filters with Axum Router and centralized AppState for dependency injection
  • Migrate all 18 API endpoints (v1 and v2) to Axum handler functions
  • Update dependencies: remove warp, add axum, tower, tower-http
  • Reorganize routes hierarchically with .nest(), alphabetically by prefix
  • Fix route conflicts using .merge() for multiple HTTP methods on same path
  • Fix bug in get_trades_v2 (use database_read instead of database_write)
  • Add comprehensive E2E test suite for HTTP behavior validation in malformed_requests.rs

Breaking Changes:

  • JSON deserialization errors now return 422 instead of 400 (Axum convention)
  • Deserialization error responses return plain text instead of JSON

How to test

Existing tests + staging

I deployed these changes to base staging to ensure metrics were working, here's the graph

Screenshot 2026-01-23 at 12-42-46 Edit panel - GPv2 - Dashboards - Amazon Managed Grafana

Follow up:
image

Unmarked spots are running main, the wrong image was labeling endpoints with unknown because it was a fallback.
That code has been removed and replaced with the current metric labeling scheme.

That scheme can be improved (read, made less verbose and error prone while being more general) but we need to change the metrics label, which I didn't do to minimize changes.

@jmg-duarte jmg-duarte marked this pull request as ready for review January 23, 2026 15:08
@jmg-duarte jmg-duarte requested a review from a team as a code owner January 23, 2026 15:08
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the orderbook API from Warp to Axum, modernizing the web framework and improving code organization. The changes include replacing Warp filters with Axum Router, migrating API endpoints, updating dependencies, and adding an E2E test suite. The review focuses on identifying critical and high severity issues, with actionable suggestions for improvement, while adhering to the repository's stricter code review style guide. One comment was modified to explicitly reference a relevant repository rule.

jmg-duarte and others added 7 commits January 26, 2026 11:25
This commit migrates the orderbook HTTP API from the warp web framework
to axum. The migration includes:

- Replace warp filters with axum Router and handlers
- Update HTTP status codes to match axum conventions (422 for JSON
  deserialization errors, proper 400/404 distinction)
- Restructure API with centralized AppState shared across handlers
- Implement axum-compatible middleware for metrics and tracing
- Remove warp dependency and related tracing utilities
- Update e2e tests to reflect new HTTP behavior

Breaking changes:
- Invalid JSON payloads now return 422 (Unprocessable Entity) instead
  of 400
- Path parameter validation now returns 400 for malformed values
- Error response format remains compatible

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed critical issues identified in PR review:
- Fixed route conflicts by using .merge() for multiple HTTP methods on same paths
- Changed get_trades_v2 to use database_read instead of database_write
- Reorganized routes alphabetically by prefix using .nest() for better maintainability
- Made METRIC_LABELS a module-level const for reusability
- Removed convert_json_response helper (too simple to warrant abstraction)
- Optimized Arc wrapping by using trait references directly
- Applied per-method middleware before merging to ensure correct metric labels
- Simplified test code by removing unnecessary verbose match expressions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Path(auction_id): Path<AuctionId>,
) -> impl IntoResponse {
let result = state
.database_write
Copy link
Contributor

Choose a reason for hiding this comment

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

These handlers could also use database_read like their v1 counter parts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines 147 to 148
axum::routing::get(get_user_orders::get_user_orders_handler)
.layer(middleware::from_fn(with_labelled_metric("v1/get_user_orders"))),
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we reduce the usage of with_labelled_metrics? Given that axums paths just use a simple string to define them this should be easier than before even.
I think a structure similar to what we had before would be nicer to read. Not sure if this possible though since these handlers all have different types so some boxing or so would probably be needed. 🤔

let routes = [
    ("v1/solver_competition/latest", axum::routing::get(handler)
];

routes.into_iter().map(|(path, handler)|  {
    with_labelled_metric(path, handler)
})
.collect()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's a small issue with your approach — not all routes match their label 😭

IMO we should make them match the label and in that case, we get better, we should be able to apply a middleware wholesale because we can get the path with placeholder

We might be able to simplify further with the TraceLayer and MatchedPath too
https://docs.rs/axum/latest/axum/extract/struct.MatchedPath.html

In summary: if the team is ok with the rename (I am!) we can make this whole thing even simpler

We can also move with this as is, and rename later so we are sure nothing broke

@extrawurst
Copy link
Contributor

JSON deserialization errors now return 422 instead of 400 (Axum convention)

Is this in our API docs anywhere that we have to update aswell?

@jmg-duarte jmg-duarte force-pushed the jmgd/axum/orderbook-2 branch from 45e0f9a to 9af007d Compare January 30, 2026 22:07
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.

5 participants