Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate auctions to new database table #3067

Closed
wants to merge 2 commits into from
Closed

Conversation

sunce86
Copy link
Contributor

@sunce86 sunce86 commented Oct 17, 2024

Description

Fixes #3055

Data migration is controlled by configuration parameter, so it can be enabled on one by one network.

Data migration is done in a background task. Separate batched transactions are executed until all data from solver_competition table is moved to new auction table.

How to test

Manually on sepolia staging, then rest.

@sunce86 sunce86 self-assigned this Oct 17, 2024
@sunce86 sunce86 requested a review from a team as a code owner October 17, 2024 15:44
@@ -802,6 +802,92 @@ impl Persistence {
ex.commit().await?;
Ok(())
}

pub async fn populate_historic_auctions(&self) -> Result<(), DatabaseError> {
Copy link
Contributor

Choose a reason for hiding this comment

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

is it possible to test this beforehand in a unit test or e2e test?

Copy link
Contributor

Choose a reason for hiding this comment

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

We could even set up a snapshot of the actual DB and and run a local DB migration with that to see how it will behave with real data.

ex = self.postgres.pool.begin().await?;

// update the current auction id
current_auction_id = competitions.last().unwrap().id;
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if this process get interrupted in the middle of it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Another point for a separate script, which could store the counter on disk.

@@ -449,6 +449,11 @@ pub async fn run(args: Arguments) {
.instrument(tracing::info_span!("order_events_cleaner")),
);

if args.migrate_auctions {
let persistence_clone = persistence.clone();
tokio::spawn(async move { persistence_clone.populate_historic_auctions().await });
Copy link
Contributor

Choose a reason for hiding this comment

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

when we spawn this I assume we are still populating both tables, therefore the migration will never end, right? 🤔

Copy link
Contributor

@MartinquaXD MartinquaXD left a comment

Choose a reason for hiding this comment

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

Rather than injecting this code into this code base which relies a restart to run wouldn't it be more convenient to build a separate small CLI tool for that? That way this code can be run / tested independently from the services.

.clone(),
};

if let Err(err) = database::auction::save(&mut ex, auction).await {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there are reason we only populate one of the new tables. AFAICS we can populate the proposed_solutions and proposed_trade_executions (at least partially).
I think it might be good to migrate as much as data as possible if we are considering deleting the old table entirely some time in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a separate issue for proposed solutions migration: #3056

The migration of solver competition is a bit more complicated and I planned doing it in a separate step -> smaller PRs

Copy link
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.

I’ll second for a separate script. Not sure why we need this in the codebase. I understand this is required only to populate the new table with historical data, so it is like a one-shot operation.

@sunce86
Copy link
Contributor Author

sunce86 commented Oct 18, 2024

Looks like there is a consensus this is not a right approach. Let me summarize the options:

  1. SQL migration file - Tried first with this, but writing a proper SQL query to convert from data types saved as json into strongly typed new tables was a nightmare to get it right (spent a lot of hours just to get the Auction part right).
  2. Same as (1) but execute SQL queries manually on each database. This would give us more certainty that performance is not problematic, but writing the queries is still painful.
  3. Do it through Rust code. Gives certainty that types are converted properly and much easier to write the code. But has this cons you mentioned - not super elegant and needs a cleanup PR after. But still requires the least engineering time.
  4. A separate tool - probably the most elegant way, but it requires more time - a separate repo with all dependencies, infrastructure PR to setup the tool for execution etc. (or am i missing some shortcut here?)

@squadgazzz
Copy link
Contributor

Looks like there is a consensus this is not a right approach. Let me summarize the options:

  1. SQL migration file - Tried first with this, but writing a proper SQL query to convert from data types saved as json into strongly typed new tables was a nightmare to get it right (spent a lot of hours just to get the Auction part right).
  2. Same as (1) but execute SQL queries manually on each database. This would give us more certainty that performance is not problematic, but writing the queries is still painful.
  3. Do it through Rust code. Gives certainty that types are converted properly and much easier to write the code. But has this cons you mentioned - not super elegant and needs a cleanup PR after. But still requires the least engineering time.
  4. A separate tool - probably the most elegant way, but it requires more time - a separate repo with all dependencies, infrastructure PR to setup the tool for execution etc. (or am i missing some shortcut here?)

Why not a simple Python script? Too time-consuming? Chatgpt should work well with generating something from the existing resources.

@MartinquaXD
Copy link
Contributor

With a separate tool you don't necessarily have to set up everything to have it automatically be spawned by kubernetes. You could have the tool and still run it manually inside the cluster using k9s.
If you decide to use a python script like @squadgazzz suggested you'd only have to install python in a pod and copy the script into it (easy with k9s). If you decide to go for the rust approach you can cross-compile the binary for linux on your machine and copy that onto the pod.
Cross compiling and copying stuff on and off a pod is covered in this notion doc.

@sunce86
Copy link
Contributor Author

sunce86 commented Oct 24, 2024

Closing as it will be executed via external tool

@sunce86 sunce86 closed this Oct 24, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Oct 24, 2024
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.

chore: Populate historic entries for new auction table
4 participants