Skip to content

Commit 18a76fb

Browse files
fuzzbuckabonander
andauthored
customizable db locking during migration (launchbadge#2063)
* customizable db locking during migration * Update sqlx-core/src/migrate/migrator.rs Co-authored-by: Austin Bonander <austin.bonander@gmail.com> * [migrator.rs] cargo fmt * fix Migrator 'locking' param doctest fail Co-authored-by: Austin Bonander <austin.bonander@gmail.com>
1 parent c5f3513 commit 18a76fb

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

sqlx-core/src/migrate/migrator.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::slice;
99
pub struct Migrator {
1010
pub migrations: Cow<'static, [Migration]>,
1111
pub ignore_missing: bool,
12+
pub locking: bool,
1213
}
1314

1415
fn validate_applied_migrations(
@@ -56,6 +57,7 @@ impl Migrator {
5657
Ok(Self {
5758
migrations: Cow::Owned(source.resolve().await.map_err(MigrateError::Source)?),
5859
ignore_missing: false,
60+
locking: true,
5961
})
6062
}
6163

@@ -65,6 +67,19 @@ impl Migrator {
6567
self
6668
}
6769

70+
/// Specify whether or not to lock database during migration. Defaults to `true`.
71+
///
72+
/// ### Warning
73+
/// Disabling locking can lead to errors or data loss if multiple clients attempt to apply migrations simultaneously
74+
/// without some sort of mutual exclusion.
75+
///
76+
/// This should only be used if the database does not support locking, e.g. CockroachDB which talks the Postgres
77+
/// protocol but does not support advisory locks used by SQLx's migrations support for Postgres.
78+
pub fn set_locking(&mut self, locking: bool) -> &Self {
79+
self.locking = locking;
80+
self
81+
}
82+
6883
/// Get an iterator over all known migrations.
6984
pub fn iter(&self) -> slice::Iter<'_, Migration> {
7085
self.migrations.iter()
@@ -103,7 +118,9 @@ impl Migrator {
103118
C: Migrate,
104119
{
105120
// lock the database for exclusive access by the migrator
106-
conn.lock().await?;
121+
if self.locking {
122+
conn.lock().await?;
123+
}
107124

108125
// creates [_migrations] table only if needed
109126
// eventually this will likely migrate previous versions of the table
@@ -141,7 +158,9 @@ impl Migrator {
141158

142159
// unlock the migrator to allow other migrators to run
143160
// but do nothing as we already migrated
144-
conn.unlock().await?;
161+
if self.locking {
162+
conn.unlock().await?;
163+
}
145164

146165
Ok(())
147166
}
@@ -170,7 +189,9 @@ impl Migrator {
170189
let mut conn = migrator.acquire().await?;
171190

172191
// lock the database for exclusive access by the migrator
173-
conn.lock().await?;
192+
if self.locking {
193+
conn.lock().await?;
194+
}
174195

175196
// creates [_migrations] table only if needed
176197
// eventually this will likely migrate previous versions of the table
@@ -201,7 +222,9 @@ impl Migrator {
201222

202223
// unlock the migrator to allow other migrators to run
203224
// but do nothing as we already migrated
204-
conn.unlock().await?;
225+
if self.locking {
226+
conn.unlock().await?;
227+
}
205228

206229
Ok(())
207230
}

sqlx-macros/src/migrate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ pub(crate) fn expand_migrator(path: &Path) -> crate::Result<TokenStream> {
146146
#(#migrations),*
147147
]),
148148
ignore_missing: false,
149+
locking: true,
149150
}
150151
})
151152
}

src/macros/test.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ use sqlx::PgPool;
132132
# static MIGRATOR: sqlx::migrate::Migrator = sqlx::migrate::Migrator {
133133
# migrations: Cow::Borrowed(&[]),
134134
# ignore_missing: false,
135+
# locking: true,
135136
# };
136137
# }
137138

0 commit comments

Comments
 (0)