mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-31 13:54:27 +01:00
Merge 'core: Disable autovacuum by default' from Pekka Enberg
People have discovered various bugs in autovacuum so let's disable it by default for now. Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com> Closes #3899
This commit is contained in:
@@ -317,7 +317,7 @@ impl Drop for Connection {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
#[pyfunction(signature = (path))]
|
||||
pub fn connect(path: &str) -> Result<Connection> {
|
||||
match turso_core::Connection::from_uri(path, true, false, false, false, false, false) {
|
||||
match turso_core::Connection::from_uri(path, true, false, false, false, false, false, false) {
|
||||
Ok((io, conn)) => Ok(Connection { conn, _io: io }),
|
||||
Err(e) => Err(PyErr::new::<ProgrammingError, _>(format!(
|
||||
"Failed to create connection: {e:?}"
|
||||
|
||||
@@ -80,6 +80,8 @@ pub struct Opts {
|
||||
pub experimental_encryption: bool,
|
||||
#[clap(long, help = "Enable experimental index method feature")]
|
||||
pub experimental_index_method: bool,
|
||||
#[clap(long, help = "Enable experimental autovacuum feature")]
|
||||
pub experimental_autovacuum: bool,
|
||||
}
|
||||
|
||||
const PROMPT: &str = "turso> ";
|
||||
@@ -195,6 +197,7 @@ impl Limbo {
|
||||
opts.experimental_strict,
|
||||
opts.experimental_encryption,
|
||||
opts.experimental_index_method,
|
||||
opts.experimental_autovacuum,
|
||||
)?
|
||||
} else {
|
||||
let flags = if opts.readonly {
|
||||
@@ -213,6 +216,7 @@ impl Limbo {
|
||||
.with_strict(opts.experimental_strict)
|
||||
.with_encryption(opts.experimental_encryption)
|
||||
.with_index_method(opts.experimental_index_method)
|
||||
.with_autovacuum(opts.experimental_autovacuum)
|
||||
.turso_cli(),
|
||||
None,
|
||||
)?;
|
||||
|
||||
@@ -408,7 +408,7 @@ impl TursoMcpServer {
|
||||
|
||||
// Open the new database connection
|
||||
let conn = if path == ":memory:" || path.contains([':', '?', '&', '#']) {
|
||||
match Connection::from_uri(&path, true, false, false, false, false, false) {
|
||||
match Connection::from_uri(&path, true, false, false, false, false, false, false) {
|
||||
Ok((_io, c)) => c,
|
||||
Err(e) => return format!("Failed to open database '{path}': {e}"),
|
||||
}
|
||||
@@ -417,7 +417,9 @@ impl TursoMcpServer {
|
||||
&path,
|
||||
None::<&str>,
|
||||
OpenFlags::default(),
|
||||
DatabaseOpts::new().with_indexes(true),
|
||||
DatabaseOpts::new()
|
||||
.with_indexes(true)
|
||||
.with_autovacuum(false),
|
||||
None,
|
||||
) {
|
||||
Ok((_io, db)) => match db.connect() {
|
||||
|
||||
@@ -317,6 +317,7 @@ mod tests {
|
||||
enable_load_extension: false,
|
||||
enable_encryption: false,
|
||||
enable_index_method: false,
|
||||
enable_autovacuum: false,
|
||||
},
|
||||
None,
|
||||
)?;
|
||||
|
||||
35
core/lib.rs
35
core/lib.rs
@@ -120,6 +120,7 @@ pub struct DatabaseOpts {
|
||||
pub enable_strict: bool,
|
||||
pub enable_encryption: bool,
|
||||
pub enable_index_method: bool,
|
||||
pub enable_autovacuum: bool,
|
||||
enable_load_extension: bool,
|
||||
}
|
||||
|
||||
@@ -132,6 +133,7 @@ impl Default for DatabaseOpts {
|
||||
enable_strict: false,
|
||||
enable_encryption: false,
|
||||
enable_index_method: false,
|
||||
enable_autovacuum: false,
|
||||
enable_load_extension: false,
|
||||
}
|
||||
}
|
||||
@@ -177,6 +179,11 @@ impl DatabaseOpts {
|
||||
self.enable_index_method = enable;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_autovacuum(mut self, enable: bool) -> Self {
|
||||
self.enable_autovacuum = enable;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -583,11 +590,24 @@ impl Database {
|
||||
AutoVacuumMode::None
|
||||
};
|
||||
|
||||
pager.set_auto_vacuum_mode(mode);
|
||||
// Force autovacuum to None if the experimental flag is not enabled
|
||||
let final_mode = if !self.opts.enable_autovacuum {
|
||||
if mode != AutoVacuumMode::None {
|
||||
tracing::warn!(
|
||||
"Database has autovacuum enabled but --experimental-autovacuum flag is not set. Forcing autovacuum to None."
|
||||
);
|
||||
}
|
||||
AutoVacuumMode::None
|
||||
} else {
|
||||
mode
|
||||
};
|
||||
|
||||
pager.set_auto_vacuum_mode(final_mode);
|
||||
|
||||
tracing::debug!(
|
||||
"Opened existing database. Detected auto_vacuum_mode from header: {:?}",
|
||||
mode
|
||||
"Opened existing database. Detected auto_vacuum_mode from header: {:?}, final mode: {:?}",
|
||||
mode,
|
||||
final_mode
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1510,6 +1530,7 @@ impl Connection {
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_uri(
|
||||
uri: &str,
|
||||
use_indexes: bool,
|
||||
@@ -1520,6 +1541,8 @@ impl Connection {
|
||||
encryption: bool,
|
||||
// flag to opt-in custom modules support
|
||||
custom_modules: bool,
|
||||
// flag to opt-in autovacuum support
|
||||
autovacuum: bool,
|
||||
) -> Result<(Arc<dyn IO>, Arc<Connection>)> {
|
||||
use crate::util::MEMORY_PATH;
|
||||
let opts = OpenOptions::parse(uri)?;
|
||||
@@ -1536,7 +1559,8 @@ impl Connection {
|
||||
.with_views(views)
|
||||
.with_strict(strict)
|
||||
.with_encryption(encryption)
|
||||
.with_index_method(custom_modules),
|
||||
.with_index_method(custom_modules)
|
||||
.with_autovacuum(autovacuum),
|
||||
None,
|
||||
)?;
|
||||
let conn = db.connect()?;
|
||||
@@ -1566,7 +1590,8 @@ impl Connection {
|
||||
.with_views(views)
|
||||
.with_strict(strict)
|
||||
.with_encryption(encryption)
|
||||
.with_index_method(custom_modules),
|
||||
.with_index_method(custom_modules)
|
||||
.with_autovacuum(autovacuum),
|
||||
encryption_opts.clone(),
|
||||
)?;
|
||||
if let Some(modeof) = opts.modeof {
|
||||
|
||||
@@ -390,7 +390,7 @@ struct CommitInfo {
|
||||
}
|
||||
|
||||
/// Track the state of the auto-vacuum mode.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum AutoVacuumMode {
|
||||
None,
|
||||
Full,
|
||||
|
||||
@@ -241,6 +241,14 @@ fn update_pragma(
|
||||
Ok((program, TransactionMode::None))
|
||||
}
|
||||
PragmaName::AutoVacuum => {
|
||||
// Check if autovacuum is enabled in database opts
|
||||
if !connection.db.opts.enable_autovacuum {
|
||||
return Err(LimboError::InvalidArgument(
|
||||
"Autovacuum is not enabled. Use --experimental-autovacuum flag to enable it."
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let is_empty = is_database_empty(resolver.schema, &pager)?;
|
||||
tracing::debug!(
|
||||
"Checking if database is empty for auto_vacuum pragma: {}",
|
||||
|
||||
@@ -1225,11 +1225,15 @@ fn reopen_database(env: &mut SimulatorEnv) {
|
||||
}
|
||||
SimulationType::Default | SimulationType::Doublecheck => {
|
||||
env.db = None;
|
||||
let db = match turso_core::Database::open_file(
|
||||
let db = match turso_core::Database::open_file_with_flags(
|
||||
env.io.clone(),
|
||||
env.get_db_path().to_str().expect("path should be 'to_str'"),
|
||||
mvcc,
|
||||
indexes,
|
||||
turso_core::OpenFlags::default(),
|
||||
turso_core::DatabaseOpts::new()
|
||||
.with_mvcc(mvcc)
|
||||
.with_indexes(indexes)
|
||||
.with_autovacuum(true),
|
||||
None,
|
||||
) {
|
||||
Ok(db) => db,
|
||||
Err(e) => {
|
||||
|
||||
@@ -235,11 +235,15 @@ impl SimulatorEnv {
|
||||
}
|
||||
self.db = None;
|
||||
|
||||
let db = match Database::open_file(
|
||||
let db = match Database::open_file_with_flags(
|
||||
io.clone(),
|
||||
db_path.to_str().unwrap(),
|
||||
self.profile.experimental_mvcc,
|
||||
self.profile.query.gen_opts.indexes,
|
||||
turso_core::OpenFlags::default(),
|
||||
turso_core::DatabaseOpts::new()
|
||||
.with_mvcc(self.profile.experimental_mvcc)
|
||||
.with_indexes(self.profile.query.gen_opts.indexes)
|
||||
.with_autovacuum(true),
|
||||
None,
|
||||
) {
|
||||
Ok(db) => db,
|
||||
Err(e) => {
|
||||
@@ -382,11 +386,15 @@ impl SimulatorEnv {
|
||||
)
|
||||
};
|
||||
|
||||
let db = match Database::open_file(
|
||||
let db = match Database::open_file_with_flags(
|
||||
io.clone(),
|
||||
db_path.to_str().unwrap(),
|
||||
profile.experimental_mvcc,
|
||||
profile.query.gen_opts.indexes,
|
||||
turso_core::OpenFlags::default(),
|
||||
turso_core::DatabaseOpts::new()
|
||||
.with_mvcc(profile.experimental_mvcc)
|
||||
.with_indexes(profile.query.gen_opts.indexes)
|
||||
.with_autovacuum(true),
|
||||
None,
|
||||
) {
|
||||
Ok(db) => db,
|
||||
Err(e) => {
|
||||
|
||||
@@ -54,6 +54,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
let mut row_count = 0;
|
||||
run_query_on_row(&tmp_db, &conn, "SELECT * FROM test", |row: &Row| {
|
||||
@@ -77,6 +78,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
run_query(
|
||||
&tmp_db,
|
||||
@@ -99,6 +101,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
run_query(
|
||||
&tmp_db,
|
||||
@@ -129,6 +132,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
let should_panic = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
run_query_on_row(&tmp_db, &conn, "SELECT * FROM test", |_row: &Row| {}).unwrap();
|
||||
@@ -150,6 +154,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
}));
|
||||
@@ -172,6 +177,7 @@ fn test_per_page_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
}));
|
||||
@@ -247,6 +253,7 @@ fn test_non_4k_page_size_encryption() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
run_query_on_row(&tmp_db, &conn, "SELECT * FROM test", |row: &Row| {
|
||||
assert_eq!(row.get::<i64>(0).unwrap(), 1);
|
||||
@@ -313,6 +320,7 @@ fn test_corruption_turso_magic_bytes() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
run_query_on_row(&tmp_db, &conn, "SELECT * FROM test", |_row: &Row| {}).unwrap();
|
||||
@@ -406,6 +414,7 @@ fn test_corruption_associated_data_bytes() -> anyhow::Result<()> {
|
||||
false,
|
||||
ENABLE_ENCRYPTION,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
run_query_on_row(&test_tmp_db, &conn, "SELECT * FROM test", |_row: &Row| {})
|
||||
|
||||
Reference in New Issue
Block a user