Skip to content

Commit 1519161

Browse files
greged93frisitano
andauthored
feat: add indexes and improve SQL default config (#281)
* feat: add indexes and improve SQL default config * feat: correctly apply indexes * update database connection config and migrate index creation to use migration file --------- Co-authored-by: frisitano <[email protected]>
1 parent 60f7b7a commit 1519161

File tree

6 files changed

+210
-6
lines changed

6 files changed

+210
-6
lines changed

crates/database/db/src/db.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1+
use std::{str::FromStr, time::Duration};
2+
13
use super::{transaction::DatabaseTransaction, DatabaseConnectionProvider};
24
use crate::error::DatabaseError;
35

4-
use sea_orm::{Database as SeaOrmDatabase, DatabaseConnection, TransactionTrait};
6+
use sea_orm::{
7+
sqlx::sqlite::SqliteConnectOptions, DatabaseConnection, SqlxSqliteConnector, TransactionTrait,
8+
};
9+
10+
// TODO: make these configurable via CLI.
11+
12+
/// The timeout duration for database busy errors.
13+
const BUSY_TIMEOUT_SECS: u64 = 5;
14+
15+
/// The maximum number of connections in the database connection pool.
16+
const MAX_CONNECTIONS: u32 = 10;
17+
18+
/// The timeout for acquiring a connection from the pool.
19+
const ACQUIRE_TIMEOUT_SECS: u64 = 5;
520

621
/// The [`Database`] struct is responsible for interacting with the database.
722
///
@@ -19,8 +34,20 @@ pub struct Database {
1934
impl Database {
2035
/// Creates a new [`Database`] instance associated with the provided database URL.
2136
pub async fn new(database_url: &str) -> Result<Self, DatabaseError> {
22-
let connection = SeaOrmDatabase::connect(database_url).await?;
23-
Ok(Self { connection })
37+
let options = SqliteConnectOptions::from_str(database_url)?
38+
.create_if_missing(true)
39+
.journal_mode(sea_orm::sqlx::sqlite::SqliteJournalMode::Wal)
40+
.busy_timeout(Duration::from_secs(BUSY_TIMEOUT_SECS))
41+
.foreign_keys(true)
42+
.synchronous(sea_orm::sqlx::sqlite::SqliteSynchronous::Normal);
43+
44+
let sqlx_pool = sea_orm::sqlx::sqlite::SqlitePoolOptions::new()
45+
.max_connections(MAX_CONNECTIONS)
46+
.acquire_timeout(Duration::from_secs(ACQUIRE_TIMEOUT_SECS))
47+
.connect_with(options)
48+
.await?;
49+
50+
Ok(Self { connection: SqlxSqliteConnector::from_sqlx_sqlite_pool(sqlx_pool) })
2451
}
2552

2653
/// Creates a new [`DatabaseTransaction`] which can be used for atomic operations.

crates/database/db/src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::L1MessageStart;
22
use alloy_eips::BlockId;
33
use alloy_primitives::B256;
4+
use sea_orm::sqlx::Error as SqlxError;
45

56
/// The error type for database operations.
67
#[derive(Debug, thiserror::Error)]
@@ -17,4 +18,7 @@ pub enum DatabaseError {
1718
/// The L1 message was not found in database.
1819
#[error("L1 message at index [{0}] not found in database")]
1920
L1MessageNotFound(L1MessageStart),
21+
/// An error occurred at the sqlx level.
22+
#[error("A sqlx error occurred: {0}")]
23+
SqlxError(#[from] SqlxError),
2024
}

crates/database/migration/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod m20250408_150338_load_header_metadata;
77
mod m20250411_072004_add_l2_block;
88
mod m20250616_223947_add_metadata;
99
mod m20250825_093350_remove_unsafe_l2_blocks;
10+
mod m20250829_042803_add_table_indexes;
1011
mod migration_info;
1112
pub use migration_info::{
1213
MigrationInfo, ScrollDevMigrationInfo, ScrollMainnetMigrationInfo, ScrollSepoliaMigrationInfo,
@@ -25,6 +26,7 @@ impl<MI: MigrationInfo + Send + Sync + 'static> MigratorTrait for Migrator<MI> {
2526
Box::new(m20250411_072004_add_l2_block::Migration::<MI>(Default::default())),
2627
Box::new(m20250616_223947_add_metadata::Migration),
2728
Box::new(m20250825_093350_remove_unsafe_l2_blocks::Migration),
29+
Box::new(m20250829_042803_add_table_indexes::Migration),
2830
]
2931
}
3032
}

crates/database/migration/src/m20250304_125946_add_l1_msg_table.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ impl MigrationTrait for Migration {
2323
.col(var_binary(L1Message::Input, 1024))
2424
.to_owned(),
2525
)
26-
.await
26+
.await?;
27+
28+
Ok(())
2729
}
2830

2931
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
@@ -32,7 +34,7 @@ impl MigrationTrait for Migration {
3234
}
3335

3436
#[derive(DeriveIden)]
35-
enum L1Message {
37+
pub(crate) enum L1Message {
3638
Table,
3739
QueueIndex,
3840
QueueHash,

crates/database/migration/src/m20250411_072004_add_l2_block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<MI: MigrationInfo + Send + Sync> MigrationTrait for Migration<MI> {
6767
}
6868

6969
#[derive(DeriveIden)]
70-
enum L2Block {
70+
pub(crate) enum L2Block {
7171
Table,
7272
BatchIndex,
7373
BatchHash,
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
use super::{
2+
m20220101_000001_create_batch_commit_table::BatchCommit,
3+
m20250304_125946_add_l1_msg_table::L1Message, m20250411_072004_add_l2_block::L2Block,
4+
};
5+
use sea_orm_migration::prelude::*;
6+
7+
#[derive(DeriveMigrationName)]
8+
pub struct Migration;
9+
10+
#[async_trait::async_trait]
11+
impl MigrationTrait for Migration {
12+
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
13+
// Create indexes for the `batch_commit` table.
14+
manager
15+
.create_index(
16+
Index::create()
17+
.name("idx_batch_commit_hash")
18+
.col(BatchCommit::Hash)
19+
.table(BatchCommit::Table)
20+
.to_owned(),
21+
)
22+
.await?;
23+
manager
24+
.create_index(
25+
Index::create()
26+
.name("idx_batch_commit_block_number")
27+
.col(BatchCommit::BlockNumber)
28+
.table(BatchCommit::Table)
29+
.to_owned(),
30+
)
31+
.await?;
32+
manager
33+
.create_index(
34+
Index::create()
35+
.name("idx_finalized_block_number")
36+
.col(BatchCommit::FinalizedBlockNumber)
37+
.table(BatchCommit::Table)
38+
.to_owned(),
39+
)
40+
.await?;
41+
42+
// Create indexes for the L1 message table.
43+
manager
44+
.create_index(
45+
Index::create()
46+
.name("idx_queue_hash")
47+
.col(L1Message::QueueHash)
48+
.table(L1Message::Table)
49+
.to_owned(),
50+
)
51+
.await?;
52+
manager
53+
.create_index(
54+
Index::create()
55+
.name("idx_l1_message_hash")
56+
.col(L1Message::Hash)
57+
.table(L1Message::Table)
58+
.to_owned(),
59+
)
60+
.await?;
61+
manager
62+
.create_index(
63+
Index::create()
64+
.name("idx_l1_block_number")
65+
.col(L1Message::L1BlockNumber)
66+
.table(L1Message::Table)
67+
.to_owned(),
68+
)
69+
.await?;
70+
71+
// Create indexes for L2 block table.
72+
manager
73+
.create_index(
74+
Index::create()
75+
.name("idx_l2_block_block_number")
76+
.col(L2Block::BlockNumber)
77+
.table(L2Block::Table)
78+
.to_owned(),
79+
)
80+
.await?;
81+
manager
82+
.create_index(
83+
Index::create()
84+
.name("idx_block_hash")
85+
.col(L2Block::BlockHash)
86+
.table(L2Block::Table)
87+
.to_owned(),
88+
)
89+
.await?;
90+
manager
91+
.create_index(
92+
Index::create()
93+
.name("idx_batch_hash")
94+
.col(L2Block::BatchHash)
95+
.table(L2Block::Table)
96+
.to_owned(),
97+
)
98+
.await?;
99+
manager
100+
.create_index(
101+
Index::create()
102+
.name("idx_batch_index")
103+
.col(L2Block::BatchIndex)
104+
.table(L2Block::Table)
105+
.to_owned(),
106+
)
107+
.await?;
108+
109+
Ok(())
110+
}
111+
112+
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
113+
// Drop indexes for the `batch_commit` table.
114+
manager
115+
.drop_index(
116+
Index::drop().name("idx_batch_commit_hash").table(BatchCommit::Table).to_owned(),
117+
)
118+
.await?;
119+
manager
120+
.drop_index(
121+
Index::drop()
122+
.name("idx_batch_commit_block_number")
123+
.table(BatchCommit::Table)
124+
.to_owned(),
125+
)
126+
.await?;
127+
manager
128+
.drop_index(
129+
Index::drop()
130+
.name("idx_finalized_block_number")
131+
.table(BatchCommit::Table)
132+
.to_owned(),
133+
)
134+
.await?;
135+
136+
// Drop indexes for the L1 message table.
137+
manager
138+
.drop_index(Index::drop().name("idx_queue_hash").table(L1Message::Table).to_owned())
139+
.await?;
140+
manager
141+
.drop_index(
142+
Index::drop().name("idx_l1_message_hash").table(L1Message::Table).to_owned(),
143+
)
144+
.await?;
145+
manager
146+
.drop_index(
147+
Index::drop().name("idx_l1_block_number").table(L1Message::Table).to_owned(),
148+
)
149+
.await?;
150+
151+
// Drop indexes for L2 block table.
152+
manager
153+
.drop_index(
154+
Index::drop().name("idx_l2_block_block_number").table(L2Block::Table).to_owned(),
155+
)
156+
.await?;
157+
manager
158+
.drop_index(Index::drop().name("idx_block_hash").table(L2Block::Table).to_owned())
159+
.await?;
160+
manager
161+
.drop_index(Index::drop().name("idx_batch_hash").table(L2Block::Table).to_owned())
162+
.await?;
163+
manager
164+
.drop_index(Index::drop().name("idx_batch_index").table(L2Block::Table).to_owned())
165+
.await?;
166+
167+
Ok(())
168+
}
169+
}

0 commit comments

Comments
 (0)