Skip to content

Fetch inflight orders from DB#4087

Merged
MartinquaXD merged 13 commits intomainfrom
fetch-inflight-orders-from-db
Jan 26, 2026
Merged

Fetch inflight orders from DB#4087
MartinquaXD merged 13 commits intomainfrom
fetch-inflight-orders-from-db

Conversation

@MartinquaXD
Copy link
Copy Markdown
Contributor

@MartinquaXD MartinquaXD commented Jan 24, 2026

Description

In order to avoid solver solutions conflicting with each other once a solution for an order was proposed it will get removed from the auction until its submission deadline has been reached. So far this was managed entirely in-memory which can lead to issues whenever the autopilot gets restarted.

Changes

Since the DB scheme refactor a while ago we now have all the data we need to recover inflight orders from the DB. This PR replaces the in-memory inflight order handling by looking them up from the DB.

To make the query fast enough I added an index on the deadline column on the competition_auctions table. With that the query takes ~0.1ms to look up 10 auctions worth of inflight orders.

execution plan
"Unique  (cost=1352.80..1352.98 rows=35 width=57) (actual time=0.041..0.043 rows=1 loops=1)"
"  ->  Sort  (cost=1352.80..1352.89 rows=35 width=57) (actual time=0.040..0.041 rows=1 loops=1)"
"        Sort Key: pte.order_uid"
"        Sort Method: quicksort  Memory: 25kB"
"        ->  Nested Loop  (cost=1.86..1351.90 rows=35 width=57) (actual time=0.028..0.033 rows=1 loops=1)"
"              ->  Nested Loop Anti Join  (cost=1.29..1339.25 rows=4 width=24) (actual time=0.023..0.028 rows=1 loops=1)"
"                    Join Filter: (s.solution_uid = ps.uid)"
"                    ->  Nested Loop  (cost=0.86..1171.92 rows=4 width=24) (actual time=0.013..0.020 rows=2 loops=1)"
"                          ->  Index Scan using competition_auction_deadline on competition_auctions ca  (cost=0.43..11.96 rows=5 width=8) (actual time=0.005..0.006 rows=2 loops=1)"
"                                Index Cond: (deadline > 24300390)"
"                          ->  Index Scan using proposed_solutions_pkey on proposed_solutions ps  (cost=0.43..231.80 rows=19 width=16) (actual time=0.003..0.006 rows=1 loops=2)"
"                                Index Cond: (auction_id = ca.id)"
"                                Filter: is_winner"
"                                Rows Removed by Filter: 8"
"                    ->  Index Scan using settlements_auction_id on settlements s  (cost=0.43..41.69 rows=11 width=16) (actual time=0.003..0.003 rows=0 loops=2)"
"                          Index Cond: (auction_id = ca.id)"
"              ->  Index Only Scan using proposed_trade_executions_pkey on proposed_trade_executions pte  (cost=0.56..3.15 rows=1 width=73) (actual time=0.004..0.004 rows=1 loops=1)"
"                    Index Cond: ((auction_id = ps.auction_id) AND (solution_uid = ps.uid))"
"                    Heap Fetches: 1"
"Planning Time: 0.543 ms"
"Execution Time: 0.079 ms"

How to test

added a new unit test for the DB query

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 25, 2026

Reminder: Please update the DB Readme and comment whether migrations are reversible (include rollback scripts if applicable).

  • If creating new tables, update the tables list.
  • When adding a new index, consider using CREATE INDEX CONCURRENTLY for tables involved in the critical execution path.
  • For breaking changes, remember that during rollout k8s starts the new autopilot, runs the Flyway migration, and only then shuts down the old pod. That overlap means the previous version can still be processing requests on the migrated schema, so make it compatible first and ship the breaking DB change in the following release.

Caused by:

@MartinquaXD MartinquaXD marked this pull request as ready for review January 25, 2026 00:50
@MartinquaXD MartinquaXD requested a review from a team as a code owner January 25, 2026 00:50
Copy link
Copy Markdown
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 refactors the handling of in-flight orders from an in-memory solution to a database-backed one, which is a solid improvement for service robustness. However, a medium-severity logic error was identified in the database query used to fetch in-flight orders, which currently excludes orders actively being settled. This could lead to transaction conflicts and wasted gas due to on-chain reverts. Additionally, critical and high-severity issues related to an unsafe type cast, error handling, a flaky test, and a typo in a database migration also need to be addressed before merging.

Comment thread database/sql/V100__add_auction_deadline.sql
Comment thread crates/autopilot/src/infra/persistence/mod.rs
Comment thread crates/autopilot/src/run_loop.rs
Comment thread crates/database/src/solver_competition_v2.rs
Comment thread crates/database/src/solver_competition_v2.rs Outdated
Copy link
Copy Markdown
Contributor

@jmg-duarte jmg-duarte left a comment

Choose a reason for hiding this comment

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

🧹

Can be merged as is but I have a question

Comment thread crates/autopilot/src/run_loop.rs
Comment thread crates/autopilot/src/run_loop.rs
Copy link
Copy Markdown
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

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

LGTM

@MartinquaXD MartinquaXD added this pull request to the merge queue Jan 26, 2026
github-merge-queue Bot pushed a commit that referenced this pull request Jan 26, 2026
# Description
In order to avoid solver solutions conflicting with each other once a
solution for an order was proposed it will get removed from the auction
until its submission deadline has been reached. So far this was managed
entirely in-memory which can lead to issues whenever the autopilot gets
restarted.

# Changes
Since the DB scheme refactor a while ago we now have all the data we
need to recover inflight orders from the DB. This PR replaces the
in-memory inflight order handling by looking them up from the DB.

To make the query fast enough I added an index on the deadline column on
the `competition_auctions` table. With that the query takes ~0.1ms to
look up 10 auctions worth of inflight orders.

<details>
<summary>execution plan</summary>

```
"Unique  (cost=1352.80..1352.98 rows=35 width=57) (actual time=0.041..0.043 rows=1 loops=1)"
"  ->  Sort  (cost=1352.80..1352.89 rows=35 width=57) (actual time=0.040..0.041 rows=1 loops=1)"
"        Sort Key: pte.order_uid"
"        Sort Method: quicksort  Memory: 25kB"
"        ->  Nested Loop  (cost=1.86..1351.90 rows=35 width=57) (actual time=0.028..0.033 rows=1 loops=1)"
"              ->  Nested Loop Anti Join  (cost=1.29..1339.25 rows=4 width=24) (actual time=0.023..0.028 rows=1 loops=1)"
"                    Join Filter: (s.solution_uid = ps.uid)"
"                    ->  Nested Loop  (cost=0.86..1171.92 rows=4 width=24) (actual time=0.013..0.020 rows=2 loops=1)"
"                          ->  Index Scan using competition_auction_deadline on competition_auctions ca  (cost=0.43..11.96 rows=5 width=8) (actual time=0.005..0.006 rows=2 loops=1)"
"                                Index Cond: (deadline > 24300390)"
"                          ->  Index Scan using proposed_solutions_pkey on proposed_solutions ps  (cost=0.43..231.80 rows=19 width=16) (actual time=0.003..0.006 rows=1 loops=2)"
"                                Index Cond: (auction_id = ca.id)"
"                                Filter: is_winner"
"                                Rows Removed by Filter: 8"
"                    ->  Index Scan using settlements_auction_id on settlements s  (cost=0.43..41.69 rows=11 width=16) (actual time=0.003..0.003 rows=0 loops=2)"
"                          Index Cond: (auction_id = ca.id)"
"              ->  Index Only Scan using proposed_trade_executions_pkey on proposed_trade_executions pte  (cost=0.56..3.15 rows=1 width=73) (actual time=0.004..0.004 rows=1 loops=1)"
"                    Index Cond: ((auction_id = ps.auction_id) AND (solution_uid = ps.uid))"
"                    Heap Fetches: 1"
"Planning Time: 0.543 ms"
"Execution Time: 0.079 ms"
```
</details>

## How to test
added a new unit test for the DB query
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jan 26, 2026
@MartinquaXD MartinquaXD added this pull request to the merge queue Jan 26, 2026
github-merge-queue Bot pushed a commit that referenced this pull request Jan 26, 2026
# Description
In order to avoid solver solutions conflicting with each other once a
solution for an order was proposed it will get removed from the auction
until its submission deadline has been reached. So far this was managed
entirely in-memory which can lead to issues whenever the autopilot gets
restarted.

# Changes
Since the DB scheme refactor a while ago we now have all the data we
need to recover inflight orders from the DB. This PR replaces the
in-memory inflight order handling by looking them up from the DB.

To make the query fast enough I added an index on the deadline column on
the `competition_auctions` table. With that the query takes ~0.1ms to
look up 10 auctions worth of inflight orders.

<details>
<summary>execution plan</summary>

```
"Unique  (cost=1352.80..1352.98 rows=35 width=57) (actual time=0.041..0.043 rows=1 loops=1)"
"  ->  Sort  (cost=1352.80..1352.89 rows=35 width=57) (actual time=0.040..0.041 rows=1 loops=1)"
"        Sort Key: pte.order_uid"
"        Sort Method: quicksort  Memory: 25kB"
"        ->  Nested Loop  (cost=1.86..1351.90 rows=35 width=57) (actual time=0.028..0.033 rows=1 loops=1)"
"              ->  Nested Loop Anti Join  (cost=1.29..1339.25 rows=4 width=24) (actual time=0.023..0.028 rows=1 loops=1)"
"                    Join Filter: (s.solution_uid = ps.uid)"
"                    ->  Nested Loop  (cost=0.86..1171.92 rows=4 width=24) (actual time=0.013..0.020 rows=2 loops=1)"
"                          ->  Index Scan using competition_auction_deadline on competition_auctions ca  (cost=0.43..11.96 rows=5 width=8) (actual time=0.005..0.006 rows=2 loops=1)"
"                                Index Cond: (deadline > 24300390)"
"                          ->  Index Scan using proposed_solutions_pkey on proposed_solutions ps  (cost=0.43..231.80 rows=19 width=16) (actual time=0.003..0.006 rows=1 loops=2)"
"                                Index Cond: (auction_id = ca.id)"
"                                Filter: is_winner"
"                                Rows Removed by Filter: 8"
"                    ->  Index Scan using settlements_auction_id on settlements s  (cost=0.43..41.69 rows=11 width=16) (actual time=0.003..0.003 rows=0 loops=2)"
"                          Index Cond: (auction_id = ca.id)"
"              ->  Index Only Scan using proposed_trade_executions_pkey on proposed_trade_executions pte  (cost=0.56..3.15 rows=1 width=73) (actual time=0.004..0.004 rows=1 loops=1)"
"                    Index Cond: ((auction_id = ps.auction_id) AND (solution_uid = ps.uid))"
"                    Heap Fetches: 1"
"Planning Time: 0.543 ms"
"Execution Time: 0.079 ms"
```
</details>

## How to test
added a new unit test for the DB query
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jan 26, 2026
@MartinquaXD MartinquaXD enabled auto-merge January 26, 2026 13:34
@MartinquaXD MartinquaXD added this pull request to the merge queue Jan 26, 2026
Merged via the queue into main with commit 5ba1e1e Jan 26, 2026
19 checks passed
@MartinquaXD MartinquaXD deleted the fetch-inflight-orders-from-db branch January 26, 2026 14:05
@github-actions github-actions Bot locked and limited conversation to collaborators Jan 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants